From a8818139fd87187953f99b8e81c22d4c36672f34 Mon Sep 17 00:00:00 2001 From: John Sterling Date: Fri, 5 Jul 2013 11:27:53 +0200 Subject: [PATCH 01/96] Only loop through array indices and error checking --- src/pixi/utils/EventTarget.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/pixi/utils/EventTarget.js b/src/pixi/utils/EventTarget.js index b0dc71f..f3656ee 100644 --- a/src/pixi/utils/EventTarget.js +++ b/src/pixi/utils/EventTarget.js @@ -24,10 +24,16 @@ PIXI.EventTarget = function () { }; this.dispatchEvent = this.emit = function ( event ) { - - for ( var listener in listeners[ event.type ] ) { - listeners[ event.type ][ listener ]( event ); + if ( typeof listeners[ event.type ] !== 'function' ) { + + return; + + } + + for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { + + listeners[ event.type ][ i ]( event ); } From ff2b77bb2882f0af6697eb4b8f4972d906e1564f Mon Sep 17 00:00:00 2001 From: Louis Acresti Date: Mon, 15 Jul 2013 19:50:13 -0400 Subject: [PATCH 02/96] fix RenderTexture stage flipping --- src/pixi/textures/RenderTexture.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pixi/textures/RenderTexture.js b/src/pixi/textures/RenderTexture.js index cff3713..544fb22 100644 --- a/src/pixi/textures/RenderTexture.js +++ b/src/pixi/textures/RenderTexture.js @@ -174,6 +174,7 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle var children = displayObject.children; //TODO -? create a new one??? dont think so! + var originalWorldTransform = displayObject.worldTransform; displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; // modify to flip... displayObject.worldTransform[4] = -1; @@ -212,6 +213,8 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle this.renderGroup.setRenderable(displayObject); this.renderGroup.render(this.projection); } + + displayObject.worldTransform = originalWorldTransform; } From 780ec2dca3ee4904adc55026e59754bbe08349e0 Mon Sep 17 00:00:00 2001 From: Louis Acresti Date: Tue, 23 Jul 2013 19:27:40 -0400 Subject: [PATCH 03/96] removed `childIndex` --- src/pixi/display/DisplayObject.js | 9 --------- src/pixi/display/DisplayObjectContainer.js | 1 - src/pixi/utils/Utils.js | 3 +-- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/pixi/display/DisplayObject.js b/src/pixi/display/DisplayObject.js index f8ee024..cc31157 100644 --- a/src/pixi/display/DisplayObject.js +++ b/src/pixi/display/DisplayObject.js @@ -113,15 +113,6 @@ PIXI.DisplayObject = function() */ this.stage = null; - /** - * [read-only] The index of this object in the parent's `children` array - * - * @property childIndex - * @type Number - * @readOnly - */ - this.childIndex = 0; - /** * [read-only] The multiplied alpha of the displayobject * diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index 649169f..8ae41d7 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -58,7 +58,6 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) } child.parent = this; - child.childIndex = this.children.length; this.children.push(child); diff --git a/src/pixi/utils/Utils.js b/src/pixi/utils/Utils.js index 6372c8a..9534c83 100644 --- a/src/pixi/utils/Utils.js +++ b/src/pixi/utils/Utils.js @@ -124,9 +124,8 @@ PIXI.runList = function(item) while(tmp._iNext) { safe++; -// console.log(tmp.childIndex + tmp); tmp = tmp._iNext; - console.log(tmp);//.childIndex); + console.log(tmp); // console.log(tmp); if(safe > 100) From 7e634ecae44610b53b4cefde6fb3794301776dd2 Mon Sep 17 00:00:00 2001 From: Sergei Gorshechnikov Date: Sat, 27 Jul 2013 15:30:21 +0400 Subject: [PATCH 04/96] Fixed empty slots handling (#220); Fixed scaled slots handling (#205) --- src/pixi/extras/Spine.js | 204 ++++++++++++++++++++------------------- 1 file changed, 105 insertions(+), 99 deletions(-) diff --git a/src/pixi/extras/Spine.js b/src/pixi/extras/Spine.js index 5ee161a..a07f520 100644 --- a/src/pixi/extras/Spine.js +++ b/src/pixi/extras/Spine.js @@ -1,10 +1,10 @@ /** * @author Mat Groves http://matgroves.com/ @Doormat23 * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * + * * Awesome JS run time provided by EsotericSoftware * https://github.com/EsotericSoftware/spine-runtimes - * + * */ /** @@ -17,48 +17,40 @@ * @constructor * @param url {String} The url of the spine anim file to be used */ -PIXI.Spine = function(url) -{ +PIXI.Spine = function (url) { PIXI.DisplayObjectContainer.call(this); - + this.spineData = PIXI.AnimCache[url]; - - if(!this.spineData) - { + + if (!this.spineData) { throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: " + url); - return; } - - this.count = 0; - - this.sprites = []; - + this.skeleton = new spine.Skeleton(this.spineData); this.skeleton.updateWorldTransform(); - this.stateData = new spine.AnimationStateData(this.spineData); + this.stateData = new spine.AnimationStateData(this.spineData); this.state = new spine.AnimationState(this.stateData); - - // add the sprites.. - for (var i = 0; i < this.skeleton.drawOrder.length; i++) { - - var attachmentName = this.skeleton.drawOrder[i].data.attachmentName; - - // kind of an assumtion here. that its a png - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; - } - - - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(attachmentName)); - sprite.anchor.x = sprite.anchor.y = 0.5; - this.addChild(sprite); - this.sprites.push(sprite); - }; -} -PIXI.Spine.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); + 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)) { + continue; + } + var spriteName = attachment.rendererObject.name; + var sprite = this.createSprite(slot, attachment.rendererObject); + slot.currentSprite = sprite; + slotContainer.addChild(sprite); + } +}; + +PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); PIXI.Spine.prototype.constructor = PIXI.Spine; /* @@ -67,49 +59,68 @@ PIXI.Spine.prototype.constructor = PIXI.Spine; * @method updateTransform * @private */ -PIXI.Spine.prototype.updateTransform = function() -{ - // TODO should make this time based really.. - this.state.update(1/60); +PIXI.Spine.prototype.updateTransform = function () { + this.lastTime = this.lastTime || Date.now(); + var timeDelta = (Date.now() - this.lastTime) * 0.001; + this.lastTime = Date.now(); + this.state.update(timeDelta); this.state.apply(this.skeleton); this.skeleton.updateWorldTransform(); - - for (var i = 0; i < this.skeleton.drawOrder.length; i++) - { - var slot = this.skeleton.drawOrder[i]; + 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 instanceof spine.RegionAttachment)) { + slotContainer.visible = false; + continue; + } - var x = slot.bone.worldX + slot.attachment.x * slot.bone.m00 + slot.attachment.y * slot.bone.m01 + slot.attachment.width * 0.5; - var y = slot.bone.worldY + slot.attachment.x * slot.bone.m10 + slot.attachment.y * slot.bone.m11 + slot.attachment.height * 0.5; - //console.log(x + ' : ' + y); - - - //console.log(slot.attachment.name) - if(slot.cacheName != slot.attachment.name) - { - var attachmentName = slot.attachment.name; - - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; + if (attachment.rendererObject) { + if (!slot.data.attachmentName || attachment.rendererObject.name != slot.data.attachmentName) { + var spriteName = attachment.rendererObject.name; + if (slot.currentSprite !== undefined) { + slot.currentSprite.visible = false; } - - this.sprites[i].setTexture(PIXI.TextureCache[attachmentName]); - - slot.cacheName = slot.attachment.name; + slot.sprites = slot.sprites || {}; + if (slot.sprites[spriteName] !== undefined) { + slot.sprites[spriteName].visible = true; + } else { + var sprite = this.createSprite(slot, attachment.rendererObject); + slotContainer.addChild(sprite); + slot.data.attachmentName = attachment.rendererObject.name; + } + slot.currentSprite = slot.sprites[spriteName]; } - - x += -((slot.attachment.width * (slot.bone.worldScaleX + slot.attachment.scaleX - 1))>>1); - y += -((slot.attachment.height * (slot.bone.worldScaleY + slot.attachment.scaleY - 1))>>1); - - - this.sprites[i].position.x = x; - this.sprites[i].position.y = y; - this.sprites[i].rotation = (-(slot.bone.worldRotation + slot.attachment.rotation)) * (Math.PI/180); - } - + } + slotContainer.visible = true; + + 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 * Math.PI / 180); + } + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -} +}; + + +PIXI.Spine.prototype.createSprite = function (slot, descriptor) { + var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; + var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); + sprite.scale = descriptor.scale; + sprite.rotation = descriptor.rotation; + sprite.anchor.x = sprite.anchor.y = 0.5; + + slot.sprites = slot.sprites || {}; + slot.sprites[descriptor.name] = sprite; + return sprite; +}; /* * Awesome JS run time provided by EsotericSoftware @@ -225,7 +236,7 @@ spine.Slot.prototype = { this.g = data.g; this.b = data.b; this.a = data.a; - + var slotDatas = this.skeleton.data.slots; for (var i = 0, n = slotDatas.length; i < n; i++) { if (slotDatas[i] == data) { @@ -456,6 +467,7 @@ spine.TranslateTimeline.prototype = { var frameTime = frames[frameIndex]; var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); + bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; } @@ -480,14 +492,12 @@ spine.ScaleTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. - + var bone = skeleton.bones[this.boneIndex]; if (time >= frames[frames.length - 3]) { // Time is after last frame. bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - - return; } @@ -525,6 +535,7 @@ spine.ColorTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. + var slot = skeleton.slots[this.slotIndex]; if (time >= frames[frames.length - 5]) { // Time is after last frame. @@ -574,7 +585,7 @@ spine.AttachmentTimeline = function (frameCount) { spine.AttachmentTimeline.prototype = { slotIndex: 0, getFrameCount: function () { - return this.frames.length / 2; + return this.frames.length; }, setFrame: function (frameIndex, time, attachmentName) { this.frames[frameIndex] = time; @@ -591,11 +602,6 @@ spine.AttachmentTimeline.prototype = { frameIndex = spine.binarySearch(frames, time, 1) - 1; var attachmentName = this.attachmentNames[frameIndex]; - //console.log(skeleton.slots[this.slotIndex]) - - // change the name! - // skeleton.slots[this.slotIndex].attachmentName = attachmentName; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); } }; @@ -767,11 +773,9 @@ spine.Skeleton.prototype = { if (slot.data.name == slotName) { var attachment = null; if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; } - slot.setAttachment(attachment); return; } @@ -853,7 +857,6 @@ spine.RegionAttachment.prototype = { offset[7/*Y4*/] = localYCos + localX2Sin; }, computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; y += bone.worldY; var m00 = bone.m00; @@ -877,6 +880,7 @@ spine.AnimationStateData = function (skeletonData) { this.animationToMixTime = {}; }; spine.AnimationStateData.prototype = { + defaultMix: 0, setMixByName: function (fromName, toName, duration) { var from = this.skeletonData.findAnimation(fromName); if (!from) throw "Animation not found: " + fromName; @@ -889,7 +893,7 @@ spine.AnimationStateData.prototype = { }, getMix: function (from, to) { var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : 0; + return time ? time : this.defaultMix; } }; @@ -929,7 +933,7 @@ spine.AnimationState.prototype = { this.previous = null; } this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else + } else this.current.apply(skeleton, this.currentTime, this.currentLoop); }, clearAnimation: function () { @@ -1075,16 +1079,9 @@ spine.SkeletonJson.prototype = { name = map["name"] || name; var type = spine.AttachmentType[map["type"] || "region"]; - - // @ekelokorpi - // var attachment = this.attachmentLoader.newAttachment(skin, type, name); - var attachment = new spine.RegionAttachment(); - - // @Doormat23 - // add the name of the attachment - attachment.name = name; - + if (type == spine.AttachmentType.region) { + var attachment = new spine.RegionAttachment(); attachment.x = (map["x"] || 0) * this.scale; attachment.y = (map["y"] || 0) * this.scale; attachment.scaleX = map["scaleX"] || 1; @@ -1093,10 +1090,19 @@ spine.SkeletonJson.prototype = { attachment.width = (map["width"] || 32) * this.scale; attachment.height = (map["height"] || 32) * this.scale; attachment.updateOffset(); + + attachment.rendererObject = {}; + attachment.rendererObject.name = name; + attachment.rendererObject.scale = {}; + attachment.rendererObject.scale.x = attachment.scaleX; + attachment.rendererObject.scale.y = attachment.scaleY; + attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; + return attachment; } - return attachment; + throw "Unknown attachment type: " + type; }, + readAnimation: function (name, map, skeletonData) { var timelines = []; var duration = 0; @@ -1147,7 +1153,7 @@ spine.SkeletonJson.prototype = { } timelines.push(timeline); duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - + } else throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; } @@ -1190,8 +1196,8 @@ spine.SkeletonJson.prototype = { timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); } timelines.push(timeline); - // PIXI FIX - duration = Math.max(duration, timeline.frames[Math.floor(timeline.getFrameCount()) - 1]); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } else throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; } From a50737e2e56de2855a92114a69ffd362f11df15d Mon Sep 17 00:00:00 2001 From: Chad Engler Date: Sat, 10 Aug 2013 12:42:56 -0700 Subject: [PATCH 05/96] consider points on the edge 'inside' --- src/pixi/core/Rectangle.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pixi/core/Rectangle.js b/src/pixi/core/Rectangle.js index 66fb5d6..5748417 100644 --- a/src/pixi/core/Rectangle.js +++ b/src/pixi/core/Rectangle.js @@ -68,11 +68,11 @@ PIXI.Rectangle.prototype.contains = function(x, y) return false; var x1 = this.x; - if(x > x1 && x < x1 + this.width) + if(x >= x1 && x <= x1 + this.width) { var y1 = this.y; - if(y > y1 && y < y1 + this.height) + if(y >= y1 && y <= y1 + this.height) { return true; } From 1d896845fb83c25a0a941ee11579988c2c639327 Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Mon, 12 Aug 2013 21:55:14 +0100 Subject: [PATCH 06/96] fixes #234 --- src/pixi/renderers/webgl/WebGLRenderGroup.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pixi/renderers/webgl/WebGLRenderGroup.js b/src/pixi/renderers/webgl/WebGLRenderGroup.js index 759a372..0a12de3 100644 --- a/src/pixi/renderers/webgl/WebGLRenderGroup.js +++ b/src/pixi/renderers/webgl/WebGLRenderGroup.js @@ -82,15 +82,15 @@ PIXI.WebGLRenderGroup.prototype.render = function(projection) } else if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(renderable.worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(renderable.worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); + if(renderable.worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); } else if(renderable instanceof PIXI.FilterBlock) { @@ -304,19 +304,19 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) { if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(renderable.worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(renderable.worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.CustomRenderable) { - if(renderable.visible) renderable.renderWebGL(this, projection); + if(renderable.worldVisible) renderable.renderWebGL(this, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); + if(renderable.worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); } else if(renderable instanceof PIXI.FilterBlock) { From d764a9fc20efcee02b2a947885214ce155a44cb8 Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Mon, 12 Aug 2013 23:02:32 +0100 Subject: [PATCH 07/96] fixes DestroyTexture --- src/pixi/renderers/webgl/WebGLRenderer.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js index 2d6d307..0807f41 100644 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ b/src/pixi/renderers/webgl/WebGLRenderer.js @@ -210,8 +210,9 @@ PIXI.WebGLRenderer.prototype.render = function(stage) */ PIXI.WebGLRenderer.updateTextures = function() { - for (var i=0; i < PIXI.texturesToUpdate.length; i++) this.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) this.destroyTexture(PIXI.texturesToDestroy[i]); + //TODO break this out into a texture manager... + for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); + for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; } @@ -226,6 +227,7 @@ PIXI.WebGLRenderer.updateTextures = function() */ PIXI.WebGLRenderer.updateTexture = function(texture) { + //TODO break this out into a texture manager... var gl = PIXI.gl; if(!texture._glTexture) @@ -266,9 +268,10 @@ PIXI.WebGLRenderer.updateTexture = function(texture) * @param texture {Texture} The texture to update * @private */ -PIXI.WebGLRenderer.prototype.destroyTexture = function(texture) +PIXI.WebGLRenderer.destroyTexture = function(texture) { - var gl = this.gl; + //TODO break this out into a texture manager... + var gl = PIXI.gl; if(texture._glTexture) { From be1126bb5ec6da4a2ffbca141f9ffb3f2f6effc4 Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Mon, 12 Aug 2013 23:03:53 +0100 Subject: [PATCH 08/96] Removed unused js inports in example 12 index --- examples/example 12 - Spine/index.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/example 12 - Spine/index.html b/examples/example 12 - Spine/index.html index 8b4dc17..50a5ba4 100644 --- a/examples/example 12 - Spine/index.html +++ b/examples/example 12 - Spine/index.html @@ -12,8 +12,6 @@ - - + + + + + + From 4d33d14fae9a621b5b3f7319166114360b8d9769 Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Sun, 18 Aug 2013 17:40:46 +0100 Subject: [PATCH 16/96] Fixed bug when mouseUp being called instead of MouseOut --- src/pixi/InteractionManager.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index a98e203..1b57de7 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -131,7 +131,7 @@ PIXI.InteractionManager.prototype.setTarget = function(target) target.view.addEventListener('mousemove', this.onMouseMove.bind(this), true); target.view.addEventListener('mousedown', this.onMouseDown.bind(this), true); document.body.addEventListener('mouseup', this.onMouseUp.bind(this), true); - target.view.addEventListener('mouseout', this.onMouseUp.bind(this), true); + target.view.addEventListener('mouseout', this.onMouseOut.bind(this), true); // aint no multi touch just yet! target.view.addEventListener("touchstart", this.onTouchStart.bind(this), true); @@ -187,7 +187,6 @@ PIXI.InteractionManager.prototype.update = function() var item = this.interactiveItems[i]; - //if(!item.visible)continue; // OPTIMISATION - only calculate every time if the mousemove function exists.. @@ -307,6 +306,26 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) } } + +PIXI.InteractionManager.prototype.onMouseOut = function(event) +{ + var length = this.interactiveItems.length; + + this.target.view.style.cursor = "default"; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.__isOver) + { + this.mouse.target = item; + if(item.mouseout)item.mouseout(this.mouse); + item.__isOver = false; + } + } +} + /** * Is called when the mouse button is released on the renderer element * From c2a9798f18ad6f2bac06635c8aecddf7303ba2b7 Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Sun, 18 Aug 2013 17:45:29 +0100 Subject: [PATCH 17/96] touch/mouse prevent default now to be handled by the user Examples updated to reflect change --- examples/example 8 - Dragging/index.html | 3 +++ src/pixi/InteractionManager.js | 13 +------------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/examples/example 8 - Dragging/index.html b/examples/example 8 - Dragging/index.html index fffb17b..bc2c6ab 100644 --- a/examples/example 8 - Dragging/index.html +++ b/examples/example 8 - Dragging/index.html @@ -61,6 +61,9 @@ // use the mousedown and touchstart bunny.mousedown = bunny.touchstart = function(data) { + // stop the default event... + data.originalEvent.preventDefault(); + // store a refference to the data // The reason for this is because of multitouch // we want to track the movement of this particular touch diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 1b57de7..bd80333 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -39,14 +39,7 @@ PIXI.InteractionManager = function(stage) this.touchs = {}; - /** - * sets whether or not the touchStart and mouseDown interactions stop the high level browser functions like zoom and pan. - * It is true by default, Meaning the native zoom/pan functions will be disabled on mobiles - * @property preventDefault - * @type Boolean - */ - this.preventDefault = true; - + // helpers this.tempPoint = new PIXI.Point(); //this.tempMatrix = mat3.create(); @@ -268,8 +261,6 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) */ PIXI.InteractionManager.prototype.onMouseDown = function(event) { - if(this.preventDefault)event.preventDefault(); - this.mouse.originalEvent = event || window.event; //IE uses window.event // loop through inteaction tree... @@ -491,8 +482,6 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) */ PIXI.InteractionManager.prototype.onTouchStart = function(event) { - if(this.preventDefault)event.preventDefault(); - var rect = this.target.view.getBoundingClientRect(); var changedTouches = event.changedTouches; From 24a784de30baa557b8a88242c8319a542e2fbae2 Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Sun, 18 Aug 2013 18:17:19 +0100 Subject: [PATCH 18/96] Code Tidy Little house cleaning on the code --- src/pixi/display/DisplayObject.js | 29 ------------ src/pixi/display/DisplayObjectContainer.js | 9 ++-- src/pixi/display/MovieClip.js | 2 + src/pixi/display/Stage.js | 32 -------------- src/pixi/renderers/canvas/CanvasGraphics.js | 4 -- src/pixi/renderers/canvas/CanvasRenderer.js | 9 +--- src/pixi/renderers/webgl/WebGLBatch.js | 16 +++---- src/pixi/renderers/webgl/WebGLGraphics.js | 2 +- src/pixi/renderers/webgl/WebGLRenderGroup.js | 46 +------------------- src/pixi/renderers/webgl/WebGLRenderer.js | 8 ---- 10 files changed, 14 insertions(+), 143 deletions(-) diff --git a/src/pixi/display/DisplayObject.js b/src/pixi/display/DisplayObject.js index 84326a3..82d5366 100644 --- a/src/pixi/display/DisplayObject.js +++ b/src/pixi/display/DisplayObject.js @@ -86,15 +86,6 @@ PIXI.DisplayObject = function() */ this.renderable = false; - /** - * [read-only] The visibility of the object based on world (parent) factors. - * - * @property worldVisible - * @type Boolean - * @readOnly - */ - this.worldVisible = false; - /** * [read-only] The display object container that contains this display object. * @@ -251,17 +242,6 @@ PIXI.DisplayObject = function() // constructor PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObject.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - } -});*/ - /** * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default * Instead of using this function you can now simply set the interactive property to true or false @@ -334,12 +314,10 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) if(this.filter)return; this.filter = true; - // insert a filter block.. var start = new PIXI.FilterBlock(); var end = new PIXI.FilterBlock(); - start.mask = mask; end.mask = mask; @@ -349,9 +327,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) start.open = true; /* - * * insert start - * */ var childFirst = start @@ -382,9 +358,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) // now insert the end filter block.. /* - * * insert end filter - * */ var childFirst = end var childLast = end @@ -460,8 +434,6 @@ PIXI.DisplayObject.prototype.removeFilter = function() previousObject._iNext = nextObject; // this is always true too! -// if(this.last == lastBlock) - //{ var tempLast = lastBlock._iPrev; // need to make sure the parents last is updated too var updateLast = this; @@ -480,7 +452,6 @@ PIXI.DisplayObject.prototype.removeFilter = function() { this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); } - //} } /* diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index 8ae41d7..01b566d 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -61,7 +61,7 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) this.children.push(child); - // updae the stage refference.. + // update the stage refference.. if(this.stage) { @@ -96,7 +96,6 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) nextObject = previousObject._iNext; // always true in this case - //this.last = child.last; // need to make sure the parents last is updated too var updateLast = this; var prevLast = previousObject; @@ -160,7 +159,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) } // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject; var previousObject; @@ -168,7 +167,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) if(index == this.children.length) { previousObject = this.last; - var updateLast = this;//.parent; + var updateLast = this; var prevLast = this.last; while(updateLast) { @@ -297,7 +296,7 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child) { // unlink // // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject = childLast._iNext; diff --git a/src/pixi/display/MovieClip.js b/src/pixi/display/MovieClip.js index 7a77856..40a0a18 100644 --- a/src/pixi/display/MovieClip.js +++ b/src/pixi/display/MovieClip.js @@ -131,7 +131,9 @@ PIXI.MovieClip.prototype.updateTransform = function() if(!this.playing)return; this.currentFrame += this.animationSpeed; + var round = (this.currentFrame + 0.5) | 0; + if(this.loop || round < this.textures.length) { this.setTexture(this.textures[round % this.textures.length]); diff --git a/src/pixi/display/Stage.js b/src/pixi/display/Stage.js index 681c91b..c70deff 100644 --- a/src/pixi/display/Stage.js +++ b/src/pixi/display/Stage.js @@ -119,35 +119,3 @@ PIXI.Stage.prototype.getMousePosition = function() { return this.interactionManager.mouse.global; } -/* -PIXI.Stage.prototype.__addChild = function(child) -{ - if(child.interactive)this.dirty = true; - - child.stage = this; - - if(child.children) - { - for (var i=0; i < child.children.length; i++) - { - this.__addChild(child.children[i]); - }; - } - -} - - -PIXI.Stage.prototype.__removeChild = function(child) -{ - if(child.interactive)this.dirty = true; - - child.stage = undefined; - - if(child.children) - { - for(var i=0,j=child.children.length; i 0) - { - this.checkVisibility(child, child.worldVisible); - } - }; -}*/ - /** * Updates a webgl texture * diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js index 276426b..f05c162 100644 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ b/src/pixi/renderers/webgl/WebGLRenderer.js @@ -134,7 +134,6 @@ PIXI.WebGLRenderer.prototype.render = function(stage) { // TODO make this work // dont think this is needed any more? - //if(this.__stage)this.checkVisibility(this.__stage, false) this.__stage = stage; this.stageRenderGroup.setRenderable(stage); } @@ -151,9 +150,6 @@ PIXI.WebGLRenderer.prototype.render = function(stage) // update any textures PIXI.WebGLRenderer.updateTextures(); - // recursivly loop through all items! - //this.checkVisibility(stage, true); - // update the scene graph PIXI.visibleCount++; stage.updateTransform(); @@ -164,16 +160,12 @@ PIXI.WebGLRenderer.prototype.render = function(stage) gl.colorMask(true, true, true, this.transparent); gl.viewport(0, 0, this.width, this.height); - // set the correct matrix.. - // gl.uniformMatrix4fv(this.shaderProgram.mvMatrixUniform, false, this.projectionMatrix); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); gl.clear(gl.COLOR_BUFFER_BIT); // HACK TO TEST - //PIXI.projectionMatrix = this.projectionMatrix; this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; this.stageRenderGroup.render(PIXI.projection); From bc3c8efe1022baf391fa7e230b699424916bba22 Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Sun, 18 Aug 2013 19:10:25 +0100 Subject: [PATCH 19/96] Set antialising to true to Graphics example --- examples/example 13 - Graphics/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/example 13 - Graphics/index.html b/examples/example 13 - Graphics/index.html index 3912c40..081f15d 100644 --- a/examples/example 13 - Graphics/index.html +++ b/examples/example 13 - Graphics/index.html @@ -25,8 +25,8 @@ var sprite= PIXI.Sprite.fromImage("spinObj_02.png"); //stage.addChild(sprite); // create a renderer instance - //var renderer = new PIXI.CanvasRenderer(800, 600);//PIXI.autoDetectRenderer(800, 600); - var renderer = PIXI.autoDetectRenderer(620, 380); + // the 5the parameter is the anti aliasing + var renderer = PIXI.autoDetectRenderer(620, 380, null, false, true); // set the canvas width and height to fill the screen //renderer.view.style.width = window.innerWidth + "px"; From c74c608e38d77dae3323e1c811ca2e70bd8ee18e Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Sun, 18 Aug 2013 19:13:57 +0100 Subject: [PATCH 20/96] Example 3 updated --- examples/example 3 - MovieClip/index.html | 98 +++-------------------- 1 file changed, 12 insertions(+), 86 deletions(-) diff --git a/examples/example 3 - MovieClip/index.html b/examples/example 3 - MovieClip/index.html index 66d73b5..5cd0939 100755 --- a/examples/example 3 - MovieClip/index.html +++ b/examples/example 3 - MovieClip/index.html @@ -10,9 +10,6 @@ } - - - @@ -38,7 +38,7 @@ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(wf, s); })(); - + function runList(item) { console.log(">>>>>>>>>") @@ -52,15 +52,15 @@ tmp = tmp._iNext; console.log(tmp);//.childIndex); // console.log(tmp); - + if(safe > 100) { console.log("BREAK") break } - } + } } - + function init() { var assetsToLoader = ["desyrel.xml"]; @@ -72,24 +72,24 @@ loader.onComplete = onAssetsLoaded; //begin load - + // create an new instance of a pixi stage var stage = new PIXI.Stage(0x66FF99); - + loader.load(); function onAssetsLoaded() { var bitmapFontText = new PIXI.BitmapText("bitmap fonts are\n now supported!", {font: "35px Desyrel", align: "right"}); bitmapFontText.position.x = 620 - bitmapFontText.width - 20; bitmapFontText.position.y = 20; - + runList(bitmapFontText) stage.addChild(bitmapFontText); } - + // add a shiney background.. var background = PIXI.Sprite.fromImage("textDemoBG.jpg"); @@ -101,7 +101,7 @@ document.body.appendChild(renderer.view); requestAnimFrame(animate); - + // create some white text using the Snippet webfont var textSample = new PIXI.Text("Pixi.js can has\nmultiline text!", {font: "35px Snippet", fill: "white", align: "left"}); textSample.position.x = 20; @@ -119,11 +119,11 @@ countingText.position.x = 620 / 2; countingText.position.y = 320; countingText.anchor.x = 0.5; - + stage.addChild(textSample); stage.addChild(spinningText); stage.addChild(countingText); - + var count = 0; var score = 0; @@ -137,16 +137,16 @@ score++; // update the text... countingText.setText("COUNT 4EVAR: " + score); - + } // just for fun, lets rotate the text spinningText.rotation += 0.03; - - // render the stage + + // render the stage renderer.render(stage); } } - + diff --git a/examples/example 11 - RenderTexture/index.html b/examples/example 11 - RenderTexture/index.html index 4020156..367a309 100644 --- a/examples/example 11 - RenderTexture/index.html +++ b/examples/example 11 - RenderTexture/index.html @@ -9,71 +9,71 @@ background-color: #000000; } - - + + - + - + @@ -39,7 +39,7 @@ renderer = PIXI.autoDetectRenderer(w, h); stage = new PIXI.Stage; - + document.body.appendChild(renderer.view); for (var i = 0; i < starCount; i++) @@ -77,10 +77,10 @@ { w = $(window).width() - 16; h = $(window).height() - 16; - + slideX = w / 2; slideY = h / 2; - + renderer.resize(w, h); } diff --git a/examples/example 5 - Morph/index.html b/examples/example 5 - Morph/index.html index 0c8c5c3..85cdf2b 100755 --- a/examples/example 5 - Morph/index.html +++ b/examples/example 5 - Morph/index.html @@ -4,7 +4,7 @@ Pixi Morph by Photon Storm - + @@ -45,7 +45,7 @@ renderer = PIXI.autoDetectRenderer(w, h); stage = new PIXI.Stage; - + document.body.appendChild(renderer.view); makeObject(0); @@ -298,7 +298,7 @@ { w = $(window).width() - 16; h = $(window).height() - 16; - + renderer.resize(w, h); } diff --git a/examples/example 6 - Interactivity/index.html b/examples/example 6 - Interactivity/index.html index d6ef03f..3292b16 100644 --- a/examples/example 6 - Interactivity/index.html +++ b/examples/example 6 - Interactivity/index.html @@ -8,7 +8,7 @@ padding: 0; background-color: #000000; } - + #help{ position: absolute; z-index: 20; @@ -19,71 +19,71 @@ - + diff --git a/examples/example 7 - Transparent Background/index.html b/examples/example 7 - Transparent Background/index.html index 5fbdf00..d723c46 100644 --- a/examples/example 7 - Transparent Background/index.html +++ b/examples/example 7 - Transparent Background/index.html @@ -8,7 +8,7 @@ padding: 0; background-color: #FFFFFF; } - + .textHolder{ width: 400px; } @@ -27,43 +27,43 @@ blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah + + + + + + diff --git a/examples/example 15 - Filters/panda.png b/examples/example 15 - Filters/panda.png new file mode 100644 index 0000000000000000000000000000000000000000..215a4a9331fbe6bb3efe9501b672df8e5d8be76e GIT binary patch literal 69177 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 x1 && x <= x1 + this.width) + { + var y1 = this.y; + + if(y >= y1 && y <= y1 + this.height) + { + return true; + } + } + + return false; +} + +// constructor +PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; + + +/** + * @author Adrien Brault + */ + +/** + * @class Polygon + * @constructor + * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, + * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be + * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the + * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are + * Numbers. + */ +PIXI.Polygon = function(points) +{ + //if points isn't an array, use arguments as the array + if(!(points instanceof Array)) + points = Array.prototype.slice.call(arguments); + + //if this is a flat array of numbers, convert it to points + if(typeof points[0] === 'number') { + var p = []; + for(var i = 0, il = points.length; i < il; i+=2) { + p.push( + new PIXI.Point(points[i], points[i + 1]) + ); + } + + points = p; + } + + this.points = points; +} + +/** + * Creates a clone of this polygon + * + * @method clone + * @return {Polygon} a copy of the polygon + */ +PIXI.Polygon.prototype.clone = function() +{ + var points = []; + for (var i=0; i y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + + if(intersect) inside = !inside; + } + + return inside; +} + +// constructor +PIXI.Polygon.prototype.constructor = PIXI.Polygon; + +/** + * @author Chad Engler + */ + +/** + * The Circle object can be used to specify a hit area for displayobjects + * + * @class Circle + * @constructor + * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle + * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle + * @param radius {Number} The radius of the circle + */ +PIXI.Circle = function(x, y, radius) +{ + /** + * @property x + * @type Number + * @default 0 + */ + this.x = x || 0; + + /** + * @property y + * @type Number + * @default 0 + */ + this.y = y || 0; + + /** + * @property radius + * @type Number + * @default 0 + */ + this.radius = radius || 0; +} + +/** + * Creates a clone of this Circle instance + * + * @method clone + * @return {Circle} a copy of the polygon + */ +PIXI.Circle.prototype.clone = function() +{ + return new PIXI.Circle(this.x, this.y, this.radius); +} + +/** + * Checks if the x, and y coords passed to this function are contained within this circle + * + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return {Boolean} if the x/y coords are within this polygon + */ +PIXI.Circle.prototype.contains = function(x, y) +{ + if(this.radius <= 0) + return false; + + var dx = (this.x - x), + dy = (this.y - y), + r2 = this.radius * this.radius; + + dx *= dx; + dy *= dy; + + return (dx + dy <= r2); +} + +// constructor +PIXI.Circle.prototype.constructor = PIXI.Circle; + + +/** + * @author Chad Engler + */ + +/** + * The Ellipse object can be used to specify a hit area for displayobjects + * + * @class Ellipse + * @constructor + * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse + * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse + * @param width {Number} The overall width of this ellipse + * @param height {Number} The overall height of this ellipse + */ +PIXI.Ellipse = function(x, y, width, height) +{ + /** + * @property x + * @type Number + * @default 0 + */ + this.x = x || 0; + + /** + * @property y + * @type Number + * @default 0 + */ + this.y = y || 0; + + /** + * @property width + * @type Number + * @default 0 + */ + this.width = width || 0; + + /** + * @property height + * @type Number + * @default 0 + */ + this.height = height || 0; +} + +/** + * Creates a clone of this Ellipse instance + * + * @method clone + * @return {Ellipse} a copy of the ellipse + */ +PIXI.Ellipse.prototype.clone = function() +{ + return new PIXI.Ellipse(this.x, this.y, this.width, this.height); +} + +/** + * Checks if the x, and y coords passed to this function are contained within this ellipse + * + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return {Boolean} if the x/y coords are within this ellipse + */ +PIXI.Ellipse.prototype.contains = function(x, y) +{ + if(this.width <= 0 || this.height <= 0) + return false; + + //normalize the coords to an ellipse with center 0,0 + //and a radius of 0.5 + var normx = ((x - this.x) / this.width) - 0.5, + normy = ((y - this.y) / this.height) - 0.5; + + normx *= normx; + normy *= normy; + + return (normx + normy < 0.25); +} + +PIXI.Ellipse.getBounds = function() +{ + return new PIXI.Rectangle(this.x, this.y, this.width, this.height); +} + +// constructor +PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; + + + +/* + * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV + * you both rock! + */ + +function determineMatrixArrayType() { + PIXI.Matrix = (typeof Float32Array !== 'undefined') ? Float32Array : Array; + return PIXI.Matrix; +} + +determineMatrixArrayType(); + +PIXI.mat3 = {}; + +PIXI.mat3.create = function() +{ + var matrix = new PIXI.Matrix(9); + + matrix[0] = 1; + matrix[1] = 0; + matrix[2] = 0; + matrix[3] = 0; + matrix[4] = 1; + matrix[5] = 0; + matrix[6] = 0; + matrix[7] = 0; + matrix[8] = 1; + + return matrix; +} + + +PIXI.mat3.identity = function(matrix) +{ + matrix[0] = 1; + matrix[1] = 0; + matrix[2] = 0; + matrix[3] = 0; + matrix[4] = 1; + matrix[5] = 0; + matrix[6] = 0; + matrix[7] = 0; + matrix[8] = 1; + + return matrix; +} + + +PIXI.mat4 = {}; + +PIXI.mat4.create = function() +{ + var matrix = new PIXI.Matrix(16); + + matrix[0] = 1; + matrix[1] = 0; + matrix[2] = 0; + matrix[3] = 0; + matrix[4] = 0; + matrix[5] = 1; + matrix[6] = 0; + matrix[7] = 0; + matrix[8] = 0; + matrix[9] = 0; + matrix[10] = 1; + matrix[11] = 0; + matrix[12] = 0; + matrix[13] = 0; + matrix[14] = 0; + matrix[15] = 1; + + return matrix; +} + +PIXI.mat3.multiply = function (mat, mat2, dest) +{ + if (!dest) { dest = mat; } + + // Cache the matrix values (makes for huge speed increases!) + var a00 = mat[0], a01 = mat[1], a02 = mat[2], + a10 = mat[3], a11 = mat[4], a12 = mat[5], + a20 = mat[6], a21 = mat[7], a22 = mat[8], + + b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], + b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], + b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; + + dest[0] = b00 * a00 + b01 * a10 + b02 * a20; + dest[1] = b00 * a01 + b01 * a11 + b02 * a21; + dest[2] = b00 * a02 + b01 * a12 + b02 * a22; + + dest[3] = b10 * a00 + b11 * a10 + b12 * a20; + dest[4] = b10 * a01 + b11 * a11 + b12 * a21; + dest[5] = b10 * a02 + b11 * a12 + b12 * a22; + + dest[6] = b20 * a00 + b21 * a10 + b22 * a20; + dest[7] = b20 * a01 + b21 * a11 + b22 * a21; + dest[8] = b20 * a02 + b21 * a12 + b22 * a22; + + return dest; +} + +PIXI.mat3.clone = function(mat) +{ + var matrix = new PIXI.Matrix(9); + + matrix[0] = mat[0]; + matrix[1] = mat[1]; + matrix[2] = mat[2]; + matrix[3] = mat[3]; + matrix[4] = mat[4]; + matrix[5] = mat[5]; + matrix[6] = mat[6]; + matrix[7] = mat[7]; + matrix[8] = mat[8]; + + return matrix; +} + +PIXI.mat3.transpose = function (mat, dest) +{ + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (!dest || mat === dest) { + var a01 = mat[1], a02 = mat[2], + a12 = mat[5]; + + mat[1] = mat[3]; + mat[2] = mat[6]; + mat[3] = a01; + mat[5] = mat[7]; + mat[6] = a02; + mat[7] = a12; + return mat; + } + + dest[0] = mat[0]; + dest[1] = mat[3]; + dest[2] = mat[6]; + dest[3] = mat[1]; + dest[4] = mat[4]; + dest[5] = mat[7]; + dest[6] = mat[2]; + dest[7] = mat[5]; + dest[8] = mat[8]; + return dest; +} + +PIXI.mat3.toMat4 = function (mat, dest) +{ + if (!dest) { dest = PIXI.mat4.create(); } + + dest[15] = 1; + dest[14] = 0; + dest[13] = 0; + dest[12] = 0; + + dest[11] = 0; + dest[10] = mat[8]; + dest[9] = mat[7]; + dest[8] = mat[6]; + + dest[7] = 0; + dest[6] = mat[5]; + dest[5] = mat[4]; + dest[4] = mat[3]; + + dest[3] = 0; + dest[2] = mat[2]; + dest[1] = mat[1]; + dest[0] = mat[0]; + + return dest; +} + + +///// + + +PIXI.mat4.create = function() +{ + var matrix = new PIXI.Matrix(16); + + matrix[0] = 1; + matrix[1] = 0; + matrix[2] = 0; + matrix[3] = 0; + matrix[4] = 0; + matrix[5] = 1; + matrix[6] = 0; + matrix[7] = 0; + matrix[8] = 0; + matrix[9] = 0; + matrix[10] = 1; + matrix[11] = 0; + matrix[12] = 0; + matrix[13] = 0; + matrix[14] = 0; + matrix[15] = 1; + + return matrix; +} + +PIXI.mat4.transpose = function (mat, dest) +{ + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (!dest || mat === dest) + { + var a01 = mat[1], a02 = mat[2], a03 = mat[3], + a12 = mat[6], a13 = mat[7], + a23 = mat[11]; + + mat[1] = mat[4]; + mat[2] = mat[8]; + mat[3] = mat[12]; + mat[4] = a01; + mat[6] = mat[9]; + mat[7] = mat[13]; + mat[8] = a02; + mat[9] = a12; + mat[11] = mat[14]; + mat[12] = a03; + mat[13] = a13; + mat[14] = a23; + return mat; + } + + dest[0] = mat[0]; + dest[1] = mat[4]; + dest[2] = mat[8]; + dest[3] = mat[12]; + dest[4] = mat[1]; + dest[5] = mat[5]; + dest[6] = mat[9]; + dest[7] = mat[13]; + dest[8] = mat[2]; + dest[9] = mat[6]; + dest[10] = mat[10]; + dest[11] = mat[14]; + dest[12] = mat[3]; + dest[13] = mat[7]; + dest[14] = mat[11]; + dest[15] = mat[15]; + return dest; +} + +PIXI.mat4.multiply = function (mat, mat2, dest) +{ + if (!dest) { dest = mat; } + + // Cache the matrix values (makes for huge speed increases!) + var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; + var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; + var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; + var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; + + // Cache only the current line of the second matrix + var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; + dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + dest[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = mat2[4]; + b1 = mat2[5]; + b2 = mat2[6]; + b3 = mat2[7]; + dest[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + dest[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + dest[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + dest[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = mat2[8]; + b1 = mat2[9]; + b2 = mat2[10]; + b3 = mat2[11]; + dest[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + dest[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + dest[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + dest[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = mat2[12]; + b1 = mat2[13]; + b2 = mat2[14]; + b3 = mat2[15]; + dest[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + dest[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + dest[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + dest[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + return dest; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * The base class for all objects that are rendered on the screen. + * + * @class DisplayObject + * @constructor + */ +PIXI.DisplayObject = function() +{ + this.last = this; + this.first = this; + /** + * The coordinate of the object relative to the local coordinates of the parent. + * + * @property position + * @type Point + */ + this.position = new PIXI.Point(); + + /** + * The scale factor of the object. + * + * @property scale + * @type Point + */ + this.scale = new PIXI.Point(1,1);//{x:1, y:1}; + + /** + * The pivot point of the displayObject that it rotates around + * + * @property pivot + * @type Point + */ + this.pivot = new PIXI.Point(0,0); + + /** + * The rotation of the object in radians. + * + * @property rotation + * @type Number + */ + this.rotation = 0; + + /** + * The opacity of the object. + * + * @property alpha + * @type Number + */ + this.alpha = 1; + + /** + * The visibility of the object. + * + * @property visible + * @type Boolean + */ + this.visible = true; + + /** + * This is the defined area that will pick up mouse / touch events. It is null by default. + * Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children) + * + * @property hitArea + * @type Rectangle|Circle|Ellipse|Polygon + */ + this.hitArea = null; + + /** + * This is used to indicate if the displayObject should display a mouse hand cursor on rollover + * + * @property buttonMode + * @type Boolean + */ + this.buttonMode = false; + + /** + * Can this object be rendered + * + * @property renderable + * @type Boolean + */ + this.renderable = false; + + /** + * [read-only] The display object container that contains this display object. + * + * @property parent + * @type DisplayObjectContainer + * @readOnly + */ + this.parent = null; + + /** + * [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage. + * + * @property stage + * @type Stage + * @readOnly + */ + this.stage = null; + + /** + * [read-only] The multiplied alpha of the displayobject + * + * @property worldAlpha + * @type Number + * @readOnly + */ + this.worldAlpha = 1; + + /** + * [read-only] Whether or not the object is interactive, do not toggle directly! use the `interactive` property + * + * @property _interactive + * @type Boolean + * @readOnly + * @private + */ + this._interactive = false; + + /** + * [read-only] Current transform of the object based on world (parent) factors + * + * @property worldTransform + * @type Mat3 + * @readOnly + * @private + */ + this.worldTransform = PIXI.mat3.create()//mat3.identity(); + + /** + * [read-only] Current transform of the object locally + * + * @property localTransform + * @type Mat3 + * @readOnly + * @private + */ + this.localTransform = PIXI.mat3.create()//mat3.identity(); + + /** + * [NYI] Unkown + * + * @property color + * @type Array<> + * @private + */ + this.color = []; + + /** + * [NYI] Holds whether or not this object is dynamic, for rendering optimization + * + * @property dynamic + * @type Boolean + * @private + */ + this.dynamic = true; + + // chach that puppy! + this._sr = 0; + this._cr = 1; + + /* + * MOUSE Callbacks + */ + + /** + * A callback that is used when the users clicks on the displayObject with their mouse + * @method click + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user clicks the mouse down over the sprite + * @method mousedown + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases the mouse that was over the displayObject + * for this callback to be fired the mouse must have been pressed down over the displayObject + * @method mouseup + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject + * for this callback to be fired, The touch must have started over the displayObject + * @method mouseupoutside + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the users mouse rolls over the displayObject + * @method mouseover + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the users mouse leaves the displayObject + * @method mouseout + * @param interactionData {InteractionData} + */ + + + /* + * TOUCH Callbacks + */ + + /** + * A callback that is used when the users taps on the sprite with their finger + * basically a touch version of click + * @method tap + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user touch's over the displayObject + * @method touchstart + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases a touch over the displayObject + * @method touchend + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases the touch that was over the displayObject + * for this callback to be fired, The touch must have started over the sprite + * @method touchendoutside + * @param interactionData {InteractionData} + */ +} + +// constructor +PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; + +/** + * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default + * Instead of using this function you can now simply set the interactive property to true or false + * + * @method setInteractive + * @param interactive {Boolean} + * @deprecated Simply set the `interactive` property directly + */ +PIXI.DisplayObject.prototype.setInteractive = function(interactive) +{ + this.interactive = interactive; +} + +/** + * Indicates if the sprite will have touch and mouse interactivity. It is false by default + * + * @property interactive + * @type Boolean + * @default false + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'interactive', { + get: function() { + return this._interactive; + }, + set: function(value) { + this._interactive = value; + + // TODO more to be done here.. + // need to sort out a re-crawl! + if(this.stage)this.stage.dirty = true; + } +}); + +/** + * Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. + * In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. + * To remove a mask, set this property to null. + * + * @property mask + * @type Graphics + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { + get: function() { + return this._mask; + }, + set: function(value) { + + + if(value) + { + if(this._mask) + { + value.start = this._mask.start; + value.end = this._mask.end; + } + else + { + this.addFilter(value); + value.renderable = false; + } + } + else + { + this.removeFilter(this._mask); + this._mask.renderable = true; + } + + this._mask = value; + } +}); + +/** + * Sets the filters for the displayObject. Currently there's a few limitations. + * 1: At the moment only one filter can be applied at a time.. + * 2: They cannot be nested. + * 3: There's no padding yet. + * 4: this is a webGL only feature. + * @property filters + * @type Array + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { + get: function() { + return this._filters; + }, + set: function(value) { + + //if(value == ) + if(value) + { + if(this._filters)this.removeFilter(this._filters); + this.addFilter(value) + } + else + { + if(this._filters)this.removeFilter(this._filters); + } + + this._filters = value; + } +}); + +/* + * Adds a filter to this displayObject + * + * @method addFilter + * @param mask {Graphics} the graphics object to use as a filter + * @private + */ +PIXI.DisplayObject.prototype.addFilter = function(data) +{ + //if(this.filter)return; + //this.filter = true; + + // insert a filter block.. + // TODO Onject pool thease bad boys.. + var start = new PIXI.FilterBlock(); + var end = new PIXI.FilterBlock(); + + data.start = start; + data.end = end; + + start.data = data; + end.data = data; + + start.first = start.last = this; + end.first = end.last = this; + + start.open = true; + + /* + * insert start + */ + + var childFirst = start + var childLast = start + var nextObject; + var previousObject; + + previousObject = this.first._iPrev; + + if(previousObject) + { + nextObject = previousObject._iNext; + childFirst._iPrev = previousObject; + previousObject._iNext = childFirst; + } + else + { + nextObject = this; + } + + if(nextObject) + { + nextObject._iPrev = childLast; + childLast._iNext = nextObject; + } + + + // now insert the end filter block.. + + /* + * insert end filter + */ + var childFirst = end + var childLast = end + var nextObject = null; + var previousObject = null; + + previousObject = this.last; + nextObject = previousObject._iNext; + + if(nextObject) + { + nextObject._iPrev = childLast; + childLast._iNext = nextObject; + } + + childFirst._iPrev = previousObject; + previousObject._iNext = childFirst; + + var updateLast = this; + + var prevLast = this.last; + while(updateLast) + { + if(updateLast.last == prevLast) + { + updateLast.last = end; + } + updateLast = updateLast.parent; + } + + this.first = start; + + // if webGL... + if(this.__renderGroup) + { + this.__renderGroup.addFilterBlocks(start, end); + } + +} + +/* + * Removes the filter to this displayObject + * + * @method removeFilter + * @private + */ +PIXI.DisplayObject.prototype.removeFilter = function(data) +{ + //if(!this.filter)return; + //this.filter = false; + console.log("YUOIO") + // modify the list.. + var startBlock = data.start; + + + var nextObject = startBlock._iNext; + var previousObject = startBlock._iPrev; + + if(nextObject)nextObject._iPrev = previousObject; + if(previousObject)previousObject._iNext = nextObject; + + this.first = startBlock._iNext; + + // remove the end filter + var lastBlock = data.end; + + var nextObject = lastBlock._iNext; + var previousObject = lastBlock._iPrev; + + if(nextObject)nextObject._iPrev = previousObject; + previousObject._iNext = nextObject; + + // this is always true too! + var tempLast = lastBlock._iPrev; + // need to make sure the parents last is updated too + var updateLast = this; + while(updateLast.last == lastBlock) + { + updateLast.last = tempLast; + updateLast = updateLast.parent; + if(!updateLast)break; + } + + // if webGL... + if(this.__renderGroup) + { + this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); + } +} + +/* + * Updates the object transform for rendering + * + * @method updateTransform + * @private + */ +PIXI.DisplayObject.prototype.updateTransform = function() +{ + // TODO OPTIMIZE THIS!! with dirty + if(this.rotation !== this.rotationCache) + { + this.rotationCache = this.rotation; + this._sr = Math.sin(this.rotation); + this._cr = Math.cos(this.rotation); + } + + var localTransform = this.localTransform; + var parentTransform = this.parent.worldTransform; + var worldTransform = this.worldTransform; + //console.log(localTransform) + localTransform[0] = this._cr * this.scale.x; + localTransform[1] = -this._sr * this.scale.y + localTransform[3] = this._sr * this.scale.x; + localTransform[4] = this._cr * this.scale.y; + + // TODO --> do we even need a local matrix??? + + var px = this.pivot.x; + var py = this.pivot.y; + + // Cache the matrix values (makes for huge speed increases!) + var a00 = localTransform[0], a01 = localTransform[1], a02 = this.position.x - localTransform[0] * px - py * localTransform[1], + a10 = localTransform[3], a11 = localTransform[4], a12 = this.position.y - localTransform[4] * py - px * localTransform[3], + + b00 = parentTransform[0], b01 = parentTransform[1], b02 = parentTransform[2], + b10 = parentTransform[3], b11 = parentTransform[4], b12 = parentTransform[5]; + + localTransform[2] = a02 + localTransform[5] = a12 + + worldTransform[0] = b00 * a00 + b01 * a10; + worldTransform[1] = b00 * a01 + b01 * a11; + worldTransform[2] = b00 * a02 + b01 * a12 + b02; + + worldTransform[3] = b10 * a00 + b11 * a10; + worldTransform[4] = b10 * a01 + b11 * a11; + worldTransform[5] = b10 * a02 + b11 * a12 + b12; + + // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! + // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); + this.worldAlpha = this.alpha * this.parent.worldAlpha; + + this.vcount = PIXI.visibleCount; + +} + +PIXI.visibleCount = 0; +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * A DisplayObjectContainer represents a collection of display objects. + * It is the base class of all display objects that act as a container for other objects. + * + * @class DisplayObjectContainer + * @extends DisplayObject + * @constructor + */ +PIXI.DisplayObjectContainer = function() +{ + PIXI.DisplayObject.call( this ); + + /** + * [read-only] The of children of this container. + * + * @property children + * @type Array + * @readOnly + */ + this.children = []; +} + +// constructor +PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); +PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; + +/** + * Adds a child to the container. + * + * @method addChild + * @param child {DisplayObject} The DisplayObject to add to the container + */ +PIXI.DisplayObjectContainer.prototype.addChild = function(child) +{ + if(child.parent != undefined) + { + + //// COULD BE THIS??? + child.parent.removeChild(child); + // return; + } + + child.parent = this; + + this.children.push(child); + + // update the stage refference.. + + if(this.stage) + { + var tmpChild = child; + do + { + if(tmpChild.interactive)this.stage.dirty = true; + tmpChild.stage = this.stage; + tmpChild = tmpChild._iNext; + } + while(tmpChild) + } + + // LINKED LIST // + + // modify the list.. + var childFirst = child.first + var childLast = child.last; + var nextObject; + var previousObject; + + // this could be wrong if there is a filter?? + if(this._filters) + { + previousObject = this.last._iPrev; + } + else + { + previousObject = this.last; + } + + nextObject = previousObject._iNext; + + // always true in this case + // need to make sure the parents last is updated too + var updateLast = this; + var prevLast = previousObject; + + while(updateLast) + { + if(updateLast.last == prevLast) + { + updateLast.last = child.last; + } + updateLast = updateLast.parent; + } + + if(nextObject) + { + nextObject._iPrev = childLast; + childLast._iNext = nextObject; + } + + childFirst._iPrev = previousObject; + previousObject._iNext = childFirst; + + // need to remove any render groups.. + if(this.__renderGroup) + { + // being used by a renderTexture.. if it exists then it must be from a render texture; + if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); + // add them to the new render group.. + this.__renderGroup.addDisplayObjectAndChildren(child); + } + +} + +/** + * Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown + * + * @method addChildAt + * @param child {DisplayObject} The child to add + * @param index {Number} The index to place the child in + */ +PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) +{ + if(index >= 0 && index <= this.children.length) + { + if(child.parent != undefined) + { + child.parent.removeChild(child); + } + child.parent = this; + + if(this.stage) + { + var tmpChild = child; + do + { + if(tmpChild.interactive)this.stage.dirty = true; + tmpChild.stage = this.stage; + tmpChild = tmpChild._iNext; + } + while(tmpChild) + } + + // modify the list.. + var childFirst = child.first; + var childLast = child.last; + var nextObject; + var previousObject; + + if(index == this.children.length) + { + previousObject = this.last; + var updateLast = this; + var prevLast = this.last; + while(updateLast) + { + if(updateLast.last == prevLast) + { + updateLast.last = child.last; + } + updateLast = updateLast.parent; + } + } + else if(index == 0) + { + previousObject = this; + } + else + { + previousObject = this.children[index-1].last; + } + + nextObject = previousObject._iNext; + + // always true in this case + if(nextObject) + { + nextObject._iPrev = childLast; + childLast._iNext = nextObject; + } + + childFirst._iPrev = previousObject; + previousObject._iNext = childFirst; + + this.children.splice(index, 0, child); + // need to remove any render groups.. + if(this.__renderGroup) + { + // being used by a renderTexture.. if it exists then it must be from a render texture; + if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); + // add them to the new render group.. + this.__renderGroup.addDisplayObjectAndChildren(child); + } + + } + else + { + throw new Error(child + " The index "+ index +" supplied is out of bounds " + this.children.length); + } +} + +/** + * [NYI] Swaps the depth of 2 displayObjects + * + * @method swapChildren + * @param child {DisplayObject} + * @param child2 {DisplayObject} + * @private + */ +PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2) +{ + /* + * this funtion needs to be recoded.. + * can be done a lot faster.. + */ + return; + + // need to fix this function :/ + /* + // TODO I already know this?? + var index = this.children.indexOf( child ); + var index2 = this.children.indexOf( child2 ); + + if ( index !== -1 && index2 !== -1 ) + { + // cool + + /* + if(this.stage) + { + // this is to satisfy the webGL batching.. + // TODO sure there is a nicer way to achieve this! + this.stage.__removeChild(child); + this.stage.__removeChild(child2); + + this.stage.__addChild(child); + this.stage.__addChild(child2); + } + + // swap the positions.. + this.children[index] = child2; + this.children[index2] = child; + + } + else + { + throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); + }*/ +} + +/** + * Returns the Child at the specified index + * + * @method getChildAt + * @param index {Number} The index to get the child from + */ +PIXI.DisplayObjectContainer.prototype.getChildAt = function(index) +{ + if(index >= 0 && index < this.children.length) + { + return this.children[index]; + } + else + { + throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); + } +} + +/** + * Removes a child from the container. + * + * @method removeChild + * @param child {DisplayObject} The DisplayObject to remove + */ +PIXI.DisplayObjectContainer.prototype.removeChild = function(child) +{ + var index = this.children.indexOf( child ); + if ( index !== -1 ) + { + // unlink // + // modify the list.. + var childFirst = child.first; + var childLast = child.last; + + var nextObject = childLast._iNext; + var previousObject = childFirst._iPrev; + + if(nextObject)nextObject._iPrev = previousObject; + previousObject._iNext = nextObject; + + if(this.last == childLast) + { + var tempLast = childFirst._iPrev; + // need to make sure the parents last is updated too + var updateLast = this; + while(updateLast.last == childLast.last) + { + updateLast.last = tempLast; + updateLast = updateLast.parent; + if(!updateLast)break; + } + } + + childLast._iNext = null; + childFirst._iPrev = null; + + // update the stage reference.. + if(this.stage) + { + var tmpChild = child; + do + { + if(tmpChild.interactive)this.stage.dirty = true; + tmpChild.stage = null; + tmpChild = tmpChild._iNext; + } + while(tmpChild) + } + + // webGL trim + if(child.__renderGroup) + { + child.__renderGroup.removeDisplayObjectAndChildren(child); + } + + child.parent = undefined; + this.children.splice( index, 1 ); + } + else + { + throw new Error(child + " The supplied DisplayObject must be a child of the caller " + this); + } +} + +/* + * Updates the container's children's transform for rendering + * + * @method updateTransform + * @private + */ +PIXI.DisplayObjectContainer.prototype.updateTransform = function() +{ + if(!this.visible)return; + + PIXI.DisplayObject.prototype.updateTransform.call( this ); + + for(var i=0,j=this.children.length; i} an array of {Texture} objects that make up the animation + */ +PIXI.MovieClip = function(textures) +{ + PIXI.Sprite.call(this, textures[0]); + + /** + * The array of textures that make up the animation + * + * @property textures + * @type Array + */ + this.textures = textures; + + /** + * The speed that the MovieClip will play at. Higher is faster, lower is slower + * + * @property animationSpeed + * @type Number + * @default 1 + */ + this.animationSpeed = 1; + + /** + * Whether or not the movie clip repeats after playing. + * + * @property loop + * @type Boolean + * @default true + */ + this.loop = true; + + /** + * Function to call when a MovieClip finishes playing + * + * @property onComplete + * @type Function + */ + this.onComplete = null; + + /** + * [read-only] The index MovieClips current frame (this may not have to be a whole number) + * + * @property currentFrame + * @type Number + * @default 0 + * @readOnly + */ + this.currentFrame = 0; + + /** + * [read-only] Indicates if the MovieClip is currently playing + * + * @property playing + * @type Boolean + * @readOnly + */ + this.playing = false; +} + +// constructor +PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); +PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; + +/** +* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures +* assigned to the MovieClip. +* +* @property totalFrames +* @type Number +* @default 0 +* @readOnly +*/ +Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { + get: function() { + + return this.textures.length; + } +}); + + +/** + * Stops the MovieClip + * + * @method stop + */ +PIXI.MovieClip.prototype.stop = function() +{ + this.playing = false; +} + +/** + * Plays the MovieClip + * + * @method play + */ +PIXI.MovieClip.prototype.play = function() +{ + this.playing = true; +} + +/** + * Stops the MovieClip and goes to a specific frame + * + * @method gotoAndStop + * @param frameNumber {Number} frame index to stop at + */ +PIXI.MovieClip.prototype.gotoAndStop = function(frameNumber) +{ + this.playing = false; + this.currentFrame = frameNumber; + var round = (this.currentFrame + 0.5) | 0; + this.setTexture(this.textures[round % this.textures.length]); +} + +/** + * Goes to a specific frame and begins playing the MovieClip + * + * @method gotoAndPlay + * @param frameNumber {Number} frame index to start at + */ +PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) +{ + this.currentFrame = frameNumber; + this.playing = true; +} + +/* + * Updates the object transform for rendering + * + * @method updateTransform + * @private + */ +PIXI.MovieClip.prototype.updateTransform = function() +{ + PIXI.Sprite.prototype.updateTransform.call(this); + + if(!this.playing)return; + + this.currentFrame += this.animationSpeed; + + var round = (this.currentFrame + 0.5) | 0; + + if(this.loop || round < this.textures.length) + { + this.setTexture(this.textures[round % this.textures.length]); + } + else if(round >= this.textures.length) + { + this.gotoAndStop(this.textures.length - 1); + if(this.onComplete) + { + this.onComplete(); + } + } +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + + +PIXI.FilterBlock = function() +{ + this.visible = true; + this.renderable = true; +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.ColorMatrixFilter = function() +{ + // set the uniforms + this.uniforms = { + matrix: {type: 'mat4', value: [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1]}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float invert;", + "uniform mat4 matrix;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", + "gl_FragColor = gl_FragColor * vColor;", + "}" + ]; + +} + + +Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { + get: function() { + return this.uniforms.matrix.value; + }, + set: function(value) { + this.uniforms.matrix.value = value; + } +}); +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * A Text Object will create a line(s) of text to split a line you can use "\n" + * + * @class Text + * @extends Sprite + * @constructor + * @param text {String} The copy that you would like the text to display + * @param [style] {Object} The style parameters + * @param [style.font] {String} default "bold 20pt Arial" The style and size of the font + * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") + * @param [style.stroke] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" + * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) + * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used + * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap + */ +PIXI.Text = function(text, style) +{ + this.canvas = document.createElement("canvas"); + this.context = this.canvas.getContext("2d"); + PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas)); + + this.setText(text); + this.setStyle(style); + + this.updateText(); + this.dirty = false; +}; + +// constructor +PIXI.Text.prototype = Object.create(PIXI.Sprite.prototype); +PIXI.Text.prototype.constructor = PIXI.Text; + +/** + * Set the style of the text + * + * @method setStyle + * @param [style] {Object} The style parameters + * @param [style.font="bold 20pt Arial"] {String} The style and size of the font + * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") + * @param [style.stroke="black"] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" + * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) + * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used + * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap + */ +PIXI.Text.prototype.setStyle = function(style) +{ + style = style || {}; + style.font = style.font || "bold 20pt Arial"; + style.fill = style.fill || "black"; + style.align = style.align || "left"; + style.stroke = style.stroke || "black"; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136 + style.strokeThickness = style.strokeThickness || 0; + style.wordWrap = style.wordWrap || false; + style.wordWrapWidth = style.wordWrapWidth || 100; + this.style = style; + this.dirty = true; +}; + +/** + * Set the copy for the text object. To split a line you can use "\n" + * + * @methos setText + * @param {String} text The copy that you would like the text to display + */ +PIXI.Text.prototype.setText = function(text) +{ + this.text = text.toString() || " "; + this.dirty = true; +}; + +/** + * Renders text + * + * @method updateText + * @private + */ +PIXI.Text.prototype.updateText = function() +{ + this.context.font = this.style.font; + + var outputText = this.text; + + // word wrap + // preserve original text + if(this.style.wordWrap)outputText = this.wordWrap(this.text); + + //split text into lines + var lines = outputText.split(/(?:\r\n|\r|\n)/); + + //calculate text width + var lineWidths = []; + var maxLineWidth = 0; + for (var i = 0; i < lines.length; i++) + { + var lineWidth = this.context.measureText(lines[i]).width; + lineWidths[i] = lineWidth; + maxLineWidth = Math.max(maxLineWidth, lineWidth); + } + this.canvas.width = maxLineWidth + this.style.strokeThickness; + + //calculate text height + var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; + this.canvas.height = lineHeight * lines.length; + + //set canvas text styles + this.context.fillStyle = this.style.fill; + this.context.font = this.style.font; + + this.context.strokeStyle = this.style.stroke; + this.context.lineWidth = this.style.strokeThickness; + + this.context.textBaseline = "top"; + + //draw lines line by line + for (i = 0; i < lines.length; i++) + { + var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); + + if(this.style.align == "right") + { + linePosition.x += maxLineWidth - lineWidths[i]; + } + else if(this.style.align == "center") + { + linePosition.x += (maxLineWidth - lineWidths[i]) / 2; + } + + if(this.style.stroke && this.style.strokeThickness) + { + this.context.strokeText(lines[i], linePosition.x, linePosition.y); + } + + if(this.style.fill) + { + this.context.fillText(lines[i], linePosition.x, linePosition.y); + } + } + + this.updateTexture(); +}; + +/** + * Updates texture size based on canvas size + * + * @method updateTexture + * @private + */ +PIXI.Text.prototype.updateTexture = function() +{ + this.texture.baseTexture.width = this.canvas.width; + this.texture.baseTexture.height = this.canvas.height; + this.texture.frame.width = this.canvas.width; + this.texture.frame.height = this.canvas.height; + + this._width = this.canvas.width; + this._height = this.canvas.height; + + PIXI.texturesToUpdate.push(this.texture.baseTexture); +}; + +/** + * Updates the transfor of this object + * + * @method updateTransform + * @private + */ +PIXI.Text.prototype.updateTransform = function() +{ + if(this.dirty) + { + this.updateText(); + this.dirty = false; + } + + PIXI.Sprite.prototype.updateTransform.call(this); +}; + +/* + * http://stackoverflow.com/users/34441/ellisbben + * great solution to the problem! + * + * @method determineFontHeight + * @param fontStyle {Object} + * @private + */ +PIXI.Text.prototype.determineFontHeight = function(fontStyle) +{ + // build a little reference dictionary so if the font style has been used return a + // cached version... + var result = PIXI.Text.heightCache[fontStyle]; + + if(!result) + { + var body = document.getElementsByTagName("body")[0]; + var dummy = document.createElement("div"); + var dummyText = document.createTextNode("M"); + dummy.appendChild(dummyText); + dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); + body.appendChild(dummy); + + result = dummy.offsetHeight; + PIXI.Text.heightCache[fontStyle] = result; + + body.removeChild(dummy); + } + + return result; +}; + +/** + * A Text Object will apply wordwrap + * + * @method wordWrap + * @param text {String} + * @private + */ +PIXI.Text.prototype.wordWrap = function(text) +{ + // search good wrap position + var searchWrapPos = function(ctx, text, start, end, wrapWidth) + { + var p = Math.floor((end-start) / 2) + start; + if(p == start) { + return 1; + } + + if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) + { + if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) + { + return p; + } + else + { + return arguments.callee(ctx, text, p, end, wrapWidth); + } + } + else + { + return arguments.callee(ctx, text, start, p, wrapWidth); + } + }; + + var lineWrap = function(ctx, text, wrapWidth) + { + if(ctx.measureText(text).width <= wrapWidth || text.length < 1) + { + return text; + } + var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); + return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); + }; + + var result = ""; + var lines = text.split("\n"); + for (var i = 0; i < lines.length; i++) + { + result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; + } + + return result; +}; + +/** + * Destroys this text object + * + * @method destroy + * @param destroyTexture {Boolean} + */ +PIXI.Text.prototype.destroy = function(destroyTexture) +{ + if(destroyTexture) + { + this.texture.destroy(); + } + +}; + +PIXI.Text.heightCache = {}; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" + * You can generate the fnt files using + * http://www.angelcode.com/products/bmfont/ for windows or + * http://www.bmglyph.com/ for mac. + * + * @class BitmapText + * @extends DisplayObjectContainer + * @constructor + * @param text {String} The copy that you would like the text to display + * @param style {Object} The style parameters + * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") + */ +PIXI.BitmapText = function(text, style) +{ + PIXI.DisplayObjectContainer.call(this); + + this.setText(text); + this.setStyle(style); + this.updateText(); + this.dirty = false + +}; + +// constructor +PIXI.BitmapText.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); +PIXI.BitmapText.prototype.constructor = PIXI.BitmapText; + +/** + * Set the copy for the text object + * + * @method setText + * @param text {String} The copy that you would like the text to display + */ +PIXI.BitmapText.prototype.setText = function(text) +{ + this.text = text || " "; + this.dirty = true; +}; + +/** + * Set the style of the text + * + * @method setStyle + * @param style {Object} The style parameters + * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") + */ +PIXI.BitmapText.prototype.setStyle = function(style) +{ + style = style || {}; + style.align = style.align || "left"; + this.style = style; + + var font = style.font.split(" "); + this.fontName = font[font.length - 1]; + this.fontSize = font.length >= 2 ? parseInt(font[font.length - 2], 10) : PIXI.BitmapText.fonts[this.fontName].size; + + this.dirty = true; +}; + +/** + * Renders text + * + * @method updateText + * @private + */ +PIXI.BitmapText.prototype.updateText = function() +{ + var data = PIXI.BitmapText.fonts[this.fontName]; + var pos = new PIXI.Point(); + var prevCharCode = null; + var chars = []; + var maxLineWidth = 0; + var lineWidths = []; + var line = 0; + var scale = this.fontSize / data.size; + for(var i = 0; i < this.text.length; i++) + { + var charCode = this.text.charCodeAt(i); + if(/(?:\r\n|\r|\n)/.test(this.text.charAt(i))) + { + lineWidths.push(pos.x); + maxLineWidth = Math.max(maxLineWidth, pos.x); + line++; + + pos.x = 0; + pos.y += data.lineHeight; + prevCharCode = null; + continue; + } + + var charData = data.chars[charCode]; + if(!charData) continue; + + if(prevCharCode && charData[prevCharCode]) + { + pos.x += charData.kerning[prevCharCode]; + } + chars.push({texture:charData.texture, line: line, charCode: charCode, position: new PIXI.Point(pos.x + charData.xOffset, pos.y + charData.yOffset)}); + pos.x += charData.xAdvance; + + prevCharCode = charCode; + } + + lineWidths.push(pos.x); + maxLineWidth = Math.max(maxLineWidth, pos.x); + + var lineAlignOffsets = []; + for(i = 0; i <= line; i++) + { + var alignOffset = 0; + if(this.style.align == "right") + { + alignOffset = maxLineWidth - lineWidths[i]; + } + else if(this.style.align == "center") + { + alignOffset = (maxLineWidth - lineWidths[i]) / 2; + } + lineAlignOffsets.push(alignOffset); + } + + for(i = 0; i < chars.length; i++) + { + var c = new PIXI.Sprite(chars[i].texture)//PIXI.Sprite.fromFrame(chars[i].charCode); + c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale; + c.position.y = chars[i].position.y * scale; + c.scale.x = c.scale.y = scale; + this.addChild(c); + } + + this.width = pos.x * scale; + this.height = (pos.y + data.lineHeight) * scale; +}; + +/** + * Updates the transfor of this object + * + * @method updateTransform + * @private + */ +PIXI.BitmapText.prototype.updateTransform = function() +{ + if(this.dirty) + { + while(this.children.length > 0) + { + this.removeChild(this.getChildAt(0)); + } + this.updateText(); + + this.dirty = false; + } + + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); +}; + +PIXI.BitmapText.fonts = {}; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + /** + * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive + * This manager also supports multitouch. + * + * @class InteractionManager + * @constructor + * @param stage {Stage} The stage to handle interactions + */ +PIXI.InteractionManager = function(stage) +{ + /** + * a refference to the stage + * + * @property stage + * @type Stage + */ + this.stage = stage; + + /** + * the mouse data + * + * @property mouse + * @type InteractionData + */ + this.mouse = new PIXI.InteractionData(); + + /** + * an object that stores current touches (InteractionData) by id reference + * + * @property touchs + * @type Object + */ + this.touchs = {}; + + + + // helpers + this.tempPoint = new PIXI.Point(); + //this.tempMatrix = mat3.create(); + + this.mouseoverEnabled = true; + + //tiny little interactiveData pool! + this.pool = []; + + this.interactiveItems = []; + this.interactionDOMElement = null; + + //this will make it so that you dont have to call bind all the time + this.onMouseMove = this.onMouseMove.bind( this ); + this.onMouseDown = this.onMouseDown.bind(this); + this.onMouseOut = this.onMouseOut.bind(this); + this.onMouseUp = this.onMouseUp.bind(this); + + this.onTouchStart = this.onTouchStart.bind(this); + this.onTouchEnd = this.onTouchEnd.bind(this); + this.onTouchMove = this.onTouchMove.bind(this); + + + this.last = 0; +} + +// constructor +PIXI.InteractionManager.prototype.constructor = PIXI.InteractionManager; + +/** + * Collects an interactive sprite recursively to have their interactions managed + * + * @method collectInteractiveSprite + * @param displayObject {DisplayObject} the displayObject to collect + * @param iParent {DisplayObject} + * @private + */ +PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObject, iParent) +{ + var children = displayObject.children; + var length = children.length; + + /// make an interaction tree... {item.__interactiveParent} + for (var i = length-1; i >= 0; i--) + { + var child = children[i]; + +// if(child.visible) { + // push all interactive bits + if(child.interactive) + { + iParent.interactiveChildren = true; + //child.__iParent = iParent; + this.interactiveItems.push(child); + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, child); + } + } + else + { + child.__iParent = null; + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, iParent); + } + } +// } + } +} + +/** + * Sets the target for event delegation + * + * @method setTarget + * @param target {WebGLRenderer|CanvasRenderer} the renderer to bind events to + * @private + */ +PIXI.InteractionManager.prototype.setTarget = function(target) +{ + this.target = target; + + //check if the dom element has been set. If it has don't do anything + if( this.interactionDOMElement === null ) { + + this.setTargetDomElement( target.view ); + } + + document.body.addEventListener('mouseup', this.onMouseUp, true); +} + + +/** + * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM + * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element + * to receive those events + * + * @method setTargetDomElement + * @param domElement {DOMElement} the dom element which will receive mouse and touch events + * @private + */ +PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) +{ + //remove previouse listeners + if( this.interactionDOMElement !== null ) + { + this.interactionDOMElement.style['-ms-content-zooming'] = ''; + this.interactionDOMElement.style['-ms-touch-action'] = ''; + + this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); + this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); + this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); + this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); + this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); + } + + + if (window.navigator.msPointerEnabled) + { + // time to remove some of that zoom in ja.. + domElement.style['-ms-content-zooming'] = 'none'; + domElement.style['-ms-touch-action'] = 'none'; + + // DO some window specific touch! + } + + this.interactionDOMElement = domElement; + + domElement.addEventListener('mousemove', this.onMouseMove, true); + domElement.addEventListener('mousedown', this.onMouseDown, true); + domElement.addEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + domElement.addEventListener('touchstart', this.onTouchStart, true); + domElement.addEventListener('touchend', this.onTouchEnd, true); + domElement.addEventListener('touchmove', this.onTouchMove, true); +} + + +/** + * updates the state of interactive objects + * + * @method update + * @private + */ +PIXI.InteractionManager.prototype.update = function() +{ + if(!this.target)return; + + // frequency of 30fps?? + var now = Date.now(); + var diff = now - this.last; + diff = (diff * 30) / 1000; + if(diff < 1)return; + this.last = now; + // + + // ok.. so mouse events?? + // yes for now :) + // OPTIMSE - how often to check?? + if(this.dirty) + { + this.dirty = false; + + var len = this.interactiveItems.length; + + for (var i=0; i < len; i++) { + this.interactiveItems[i].interactiveChildren = false; + } + + this.interactiveItems = []; + + if(this.stage.interactive)this.interactiveItems.push(this.stage); + // go through and collect all the objects that are interactive.. + this.collectInteractiveSprite(this.stage, this.stage); + } + + // loop through interactive objects! + var length = this.interactiveItems.length; + + this.interactionDOMElement.style.cursor = "default"; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + + //if(!item.visible)continue; + + // OPTIMISATION - only calculate every time if the mousemove function exists.. + // OK so.. does the object have any other interactive functions? + // hit-test the clip! + + + if(item.mouseover || item.mouseout || item.buttonMode) + { + // ok so there are some functions so lets hit test it.. + item.__hit = this.hitTest(item, this.mouse); + this.mouse.target = item; + // ok so deal with interactions.. + // loks like there was a hit! + if(item.__hit) + { + if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; + + if(!item.__isOver) + { + + if(item.mouseover)item.mouseover(this.mouse); + item.__isOver = true; + } + } + else + { + if(item.__isOver) + { + // roll out! + if(item.mouseout)item.mouseout(this.mouse); + item.__isOver = false; + } + } + } + + // ---> + } +} + +/** + * Is called when the mouse moves accross the renderer element + * + * @method onMouseMove + * @param event {Event} The DOM event of the mouse moving + * @private + */ +PIXI.InteractionManager.prototype.onMouseMove = function(event) +{ + this.mouse.originalEvent = event || window.event; //IE uses window.event + // TODO optimize by not check EVERY TIME! maybe half as often? // + var rect = this.interactionDOMElement.getBoundingClientRect(); + + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + + var length = this.interactiveItems.length; + var global = this.mouse.global; + + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.mousemove) + { + //call the function! + item.mousemove(this.mouse); + } + } +} + +/** + * Is called when the mouse button is pressed down on the renderer element + * + * @method onMouseDown + * @param event {Event} The DOM event of a mouse button being pressed down + * @private + */ +PIXI.InteractionManager.prototype.onMouseDown = function(event) +{ + this.mouse.originalEvent = event || window.event; //IE uses window.event + + // loop through inteaction tree... + // hit test each item! -> + // get interactive items under point?? + //stage.__i + var length = this.interactiveItems.length; + var global = this.mouse.global; + + var index = 0; + var parent = this.stage; + + // while + // hit test + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.mousedown || item.click) + { + item.__mouseIsDown = true; + item.__hit = this.hitTest(item, this.mouse); + + if(item.__hit) + { + //call the function! + if(item.mousedown)item.mousedown(this.mouse); + item.__isDown = true; + + // just the one! + if(!item.interactiveChildren)break; + } + } + } +} + + +PIXI.InteractionManager.prototype.onMouseOut = function(event) +{ + var length = this.interactiveItems.length; + + this.interactionDOMElement.style.cursor = "default"; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.__isOver) + { + this.mouse.target = item; + if(item.mouseout)item.mouseout(this.mouse); + item.__isOver = false; + } + } +} + +/** + * Is called when the mouse button is released on the renderer element + * + * @method onMouseUp + * @param event {Event} The DOM event of a mouse button being released + * @private + */ +PIXI.InteractionManager.prototype.onMouseUp = function(event) +{ + this.mouse.originalEvent = event || window.event; //IE uses window.event + + var global = this.mouse.global; + + + var length = this.interactiveItems.length; + var up = false; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.mouseup || item.mouseupoutside || item.click) + { + item.__hit = this.hitTest(item, this.mouse); + + if(item.__hit && !up) + { + //call the function! + if(item.mouseup) + { + item.mouseup(this.mouse); + } + if(item.__isDown) + { + if(item.click)item.click(this.mouse); + } + + if(!item.interactiveChildren)up = true; + } + else + { + if(item.__isDown) + { + if(item.mouseupoutside)item.mouseupoutside(this.mouse); + } + } + + item.__isDown = false; + } + } +} + +/** + * Tests if the current mouse coords hit a sprite + * + * @method hitTest + * @param item {DisplayObject} The displayObject to test for a hit + * @param interactionData {InteractionData} The interactiondata object to update in the case of a hit + * @private + */ +PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) +{ + var global = interactionData.global; + + if(item.vcount !== PIXI.visibleCount)return false; + + var isSprite = (item instanceof PIXI.Sprite), + worldTransform = item.worldTransform, + a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], + a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], + id = 1 / (a00 * a11 + a01 * -a10), + x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, + y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; + + interactionData.target = item; + + //a sprite or display object with a hit area defined + if(item.hitArea && item.hitArea.contains) { + if(item.hitArea.contains(x, y)) { + //if(isSprite) + interactionData.target = item; + + return true; + } + + return false; + } + // a sprite with no hitarea defined + else if(isSprite) + { + var width = item.texture.frame.width, + height = item.texture.frame.height, + x1 = -width * item.anchor.x, + y1; + + if(x > x1 && x < x1 + width) + { + y1 = -height * item.anchor.y; + + if(y > y1 && y < y1 + height) + { + // set the target property if a hit is true! + interactionData.target = item + return true; + } + } + } + + var length = item.children.length; + + for (var i = 0; i < length; i++) + { + var tempItem = item.children[i]; + var hit = this.hitTest(tempItem, interactionData); + if(hit) + { + // hmm.. TODO SET CORRECT TARGET? + interactionData.target = item + return true; + } + } + + return false; +} + +/** + * Is called when a touch is moved accross the renderer element + * + * @method onTouchMove + * @param event {Event} The DOM event of a touch moving accross the renderer view + * @private + */ +PIXI.InteractionManager.prototype.onTouchMove = function(event) +{ + var rect = this.interactionDOMElement.getBoundingClientRect(); + var changedTouches = event.changedTouches; + + for (var i=0; i < changedTouches.length; i++) + { + var touchEvent = changedTouches[i]; + var touchData = this.touchs[touchEvent.identifier]; + touchData.originalEvent = event || window.event; + + // update the touch position + touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); + touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + } + + var length = this.interactiveItems.length; + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + if(item.touchmove)item.touchmove(touchData); + } +} + +/** + * Is called when a touch is started on the renderer element + * + * @method onTouchStart + * @param event {Event} The DOM event of a touch starting on the renderer view + * @private + */ +PIXI.InteractionManager.prototype.onTouchStart = function(event) +{ + var rect = this.interactionDOMElement.getBoundingClientRect(); + + var changedTouches = event.changedTouches; + for (var i=0; i < changedTouches.length; i++) + { + var touchEvent = changedTouches[i]; + + var touchData = this.pool.pop(); + if(!touchData)touchData = new PIXI.InteractionData(); + + touchData.originalEvent = event || window.event; + + this.touchs[touchEvent.identifier] = touchData; + touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); + touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + + var length = this.interactiveItems.length; + + for (var j = 0; j < length; j++) + { + var item = this.interactiveItems[j]; + + if(item.touchstart || item.tap) + { + item.__hit = this.hitTest(item, touchData); + + if(item.__hit) + { + //call the function! + if(item.touchstart)item.touchstart(touchData); + item.__isDown = true; + item.__touchData = touchData; + + if(!item.interactiveChildren)break; + } + } + } + } +} + +/** + * Is called when a touch is ended on the renderer element + * + * @method onTouchEnd + * @param event {Event} The DOM event of a touch ending on the renderer view + * @private + */ +PIXI.InteractionManager.prototype.onTouchEnd = function(event) +{ + //this.mouse.originalEvent = event || window.event; //IE uses window.event + var rect = this.interactionDOMElement.getBoundingClientRect(); + var changedTouches = event.changedTouches; + + for (var i=0; i < changedTouches.length; i++) + { + var touchEvent = changedTouches[i]; + var touchData = this.touchs[touchEvent.identifier]; + var up = false; + touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); + touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + + var length = this.interactiveItems.length; + for (var j = 0; j < length; j++) + { + var item = this.interactiveItems[j]; + var itemTouchData = item.__touchData; // <-- Here! + item.__hit = this.hitTest(item, touchData); + + if(itemTouchData == touchData) + { + // so this one WAS down... + touchData.originalEvent = event || window.event; + // hitTest?? + + if(item.touchend || item.tap) + { + if(item.__hit && !up) + { + if(item.touchend)item.touchend(touchData); + if(item.__isDown) + { + if(item.tap)item.tap(touchData); + } + + if(!item.interactiveChildren)up = true; + } + else + { + if(item.__isDown) + { + if(item.touchendoutside)item.touchendoutside(touchData); + } + } + + item.__isDown = false; + } + + item.__touchData = null; + + } + else + { + + } + } + // remove the touch.. + this.pool.push(touchData); + this.touchs[touchEvent.identifier] = null; + } +} + +/** + * Holds all information related to an Interaction event + * + * @class InteractionData + * @constructor + */ +PIXI.InteractionData = function() +{ + /** + * This point stores the global coords of where the touch/mouse event happened + * + * @property global + * @type Point + */ + this.global = new PIXI.Point(); + + // this is here for legacy... but will remove + this.local = new PIXI.Point(); + + /** + * The target Sprite that was interacted with + * + * @property target + * @type Sprite + */ + this.target; + + /** + * When passed to an event handler, this will be the original DOM Event that was captured + * + * @property originalEvent + * @type Event + */ + this.originalEvent; +} + +/** + * This will return the local coords of the specified displayObject for this InteractionData + * + * @method getLocalPosition + * @param displayObject {DisplayObject} The DisplayObject that you would like the local coords off + * @return {Point} A point containing the coords of the InteractionData position relative to the DisplayObject + */ +PIXI.InteractionData.prototype.getLocalPosition = function(displayObject) +{ + var worldTransform = displayObject.worldTransform; + var global = this.global; + + // do a cheeky transform to get the mouse coords; + var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], + a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], + id = 1 / (a00 * a11 + a01 * -a10); + // set the mouse coords... + return new PIXI.Point(a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, + a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id) +} + +// constructor +PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * A Stage represents the root of the display tree. Everything connected to the stage is rendered + * + * @class Stage + * @extends DisplayObjectContainer + * @constructor + * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format + * like: 0xFFFFFF for white + */ +PIXI.Stage = function(backgroundColor) +{ + PIXI.DisplayObjectContainer.call( this ); + + /** + * [read-only] Current transform of the object based on world (parent) factors + * + * @property worldTransform + * @type Mat3 + * @readOnly + * @private + */ + this.worldTransform = PIXI.mat3.create(); + + /** + * Whether or not the stage is interactive + * + * @property interactive + * @type Boolean + */ + this.interactive = true; + + /** + * The interaction manage for this stage, manages all interactive activity on the stage + * + * @property interactive + * @type InteractionManager + */ + this.interactionManager = new PIXI.InteractionManager(this); + + /** + * Whether the stage is dirty and needs to have interactions updated + * + * @property dirty + * @type Boolean + * @private + */ + this.dirty = true; + + this.__childrenAdded = []; + this.__childrenRemoved = []; + + //the stage is it's own stage + this.stage = this; + + //optimize hit detection a bit + this.stage.hitArea = new PIXI.Rectangle(0,0,100000, 100000); + + this.setBackgroundColor(backgroundColor); + this.worldVisible = true; +} + +// constructor +PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); +PIXI.Stage.prototype.constructor = PIXI.Stage; + +/** + * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. + * This is useful for when you have other DOM elements ontop of the Canvas element. + * + * @method setInteractionDelegate + * @param domElement {DOMElement} This new domElement which will receive mouse/touch events + */ +PIXI.Stage.prototype.setInteractionDelegate = function(domElement) +{ + this.interactionManager.setTargetDomElement( domElement ); +} + +/* + * Updates the object transform for rendering + * + * @method updateTransform + * @private + */ +PIXI.Stage.prototype.updateTransform = function() +{ + this.worldAlpha = 1; + this.vcount = PIXI.visibleCount; + + for(var i=0,j=this.children.length; i> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; +} + +/** + * A polyfill for Function.prototype.bind + * + * @method bind + */ +if (typeof Function.prototype.bind != 'function') { + Function.prototype.bind = (function () { + var slice = Array.prototype.slice; + return function (thisArg) { + var target = this, boundArgs = slice.call(arguments, 1); + + if (typeof target != 'function') throw new TypeError(); + + function bound() { + var args = boundArgs.concat(slice.call(arguments)); + target.apply(this instanceof bound ? this : thisArg, args); + } + + bound.prototype = (function F(proto) { + proto && (F.prototype = proto); + if (!(this instanceof F)) return new F; + })(target.prototype); + + return bound; + }; + })(); +} + +/** + * A wrapper for ajax requests to be handled cross browser + * + * @class AjaxRequest + * @constructor + */ +var AjaxRequest = PIXI.AjaxRequest = function() +{ + var activexmodes = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Microsoft.XMLHTTP"] //activeX versions to check for in IE + + if (window.ActiveXObject) + { //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken) + for (var i=0; i>>>>>>>>") + console.log("_") + var safe = 0; + var tmp = item.first; + console.log(tmp); + + while(tmp._iNext) + { + safe++; + tmp = tmp._iNext; + console.log(tmp); + // console.log(tmp); + + if(safe > 100) + { + console.log("BREAK") + break + } + } +} + + + + + + +/** + * https://github.com/mrdoob/eventtarget.js/ + * THankS mr DOob! + */ + +/** + * Adds event emitter functionality to a class + * + * @class EventTarget + * @example + * function MyEmitter() { + * PIXI.EventTarget.call(this); //mixes in event target stuff + * } + * + * var em = new MyEmitter(); + * em.emit({ type: 'eventName', data: 'some data' }); + */ +PIXI.EventTarget = function () { + + var listeners = {}; + + this.addEventListener = this.on = function ( type, listener ) { + + + if ( listeners[ type ] === undefined ) { + + listeners[ type ] = []; + + } + + if ( listeners[ type ].indexOf( listener ) === - 1 ) { + + listeners[ type ].push( listener ); + } + + }; + + this.dispatchEvent = this.emit = function ( event ) { + + if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { + + return; + + } + + for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { + + listeners[ event.type ][ i ]( event ); + + } + + }; + + this.removeEventListener = this.off = function ( type, listener ) { + + var index = listeners[ type ].indexOf( listener ); + + if ( index !== - 1 ) { + + listeners[ type ].splice( index, 1 ); + + } + + }; + +}; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * This helper function will automatically detect which renderer you should be using. + * WebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by + * the browser then this function will return a canvas renderer + * + * @method autoDetectRenderer + * @static + * @param width {Number} the width of the renderers view + * @param height {Number} the height of the renderers view + * @param view {Canvas} the canvas to use as a view, optional + * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) + * + * antialias + */ +PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) +{ + if(!width)width = 800; + if(!height)height = 600; + + // BORROWED from Mr Doob (mrdoob.com) + var webgl = ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(); + + //console.log(webgl); + if( webgl ) + { + return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); + } + + return new PIXI.CanvasRenderer(width, height, view, transparent); +}; + + + +/* + PolyK library + url: http://polyk.ivank.net + Released under MIT licence. + + Copyright (c) 2012 Ivan Kuckir + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + This is an amazing lib! + + slightly modified by mat groves (matgroves.com); +*/ + +PIXI.PolyK = {}; + +/** + * Triangulates shapes for webGL graphic fills + * + * @method Triangulate + * @namespace PolyK + * @constructor + */ +PIXI.PolyK.Triangulate = function(p) +{ + var sign = true; + + var n = p.length>>1; + if(n<3) return []; + var tgs = []; + var avl = []; + for(var i=0; i 3) + { + var i0 = avl[(i+0)%al]; + var i1 = avl[(i+1)%al]; + var i2 = avl[(i+2)%al]; + + var ax = p[2*i0], ay = p[2*i0+1]; + var bx = p[2*i1], by = p[2*i1+1]; + var cx = p[2*i2], cy = p[2*i2+1]; + + var earFound = false; + if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) + { + earFound = true; + for(var j=0; j 3*al) + { + // need to flip flip reverse it! + // reset! + if(sign) + { + var tgs = []; + avl = []; + for(var i=0; i= 0) && (v >= 0) && (u + v < 1); +} + +/** + * Checks if a shape is convex + * + * @class _convex + * @namespace PolyK + * @private + */ +PIXI.PolyK._convex = function(ax, ay, bx, by, cx, cy, sign) +{ + return ((ay-by)*(cx-bx) + (bx-ax)*(cy-by) >= 0) == sign; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/* + * the default suoer fast shader! + */ + +PIXI.shaderFragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", + "gl_FragColor = gl_FragColor * vColor;", + "}" +]; + +PIXI.shaderVertexSrc = [ + "attribute vec2 aVertexPosition;", + "attribute vec2 aTextureCoord;", + "attribute float aColor;", + + "uniform vec2 projectionVector;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "void main(void) {", + "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", + "vTextureCoord = aTextureCoord;", + "vColor = aColor;", + "}" +]; + +/* + * the triangle strip shader.. + */ + +PIXI.stripShaderFragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float alpha;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", + "gl_FragColor = gl_FragColor * alpha;", + "}" +]; + + +PIXI.stripShaderVertexSrc = [ + "attribute vec2 aVertexPosition;", + "attribute vec2 aTextureCoord;", + "attribute float aColor;", + "uniform mat3 translationMatrix;", + "uniform vec2 projectionVector;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "void main(void) {", + "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", + "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", + "vTextureCoord = aTextureCoord;", + "vColor = aColor;", + "}" +]; + +/* + * primitive shader.. + */ + +PIXI.primitiveShaderFragmentSrc = [ + "precision mediump float;", + "varying vec4 vColor;", + "void main(void) {", + "gl_FragColor = vColor;", + "}" +]; + +PIXI.primitiveShaderVertexSrc = [ + "attribute vec2 aVertexPosition;", + "attribute vec4 aColor;", + "uniform mat3 translationMatrix;", + "uniform vec2 projectionVector;", + "uniform float alpha;", + "varying vec4 vColor;", + "void main(void) {", + "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", + "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", + "vColor = aColor * alpha;", + "}" +]; + +PIXI.shaderStack = []; + +PIXI.initPrimitiveShader = function() +{ + var gl = PIXI.gl; + + var shaderProgram = PIXI.compileProgram(PIXI.primitiveShaderVertexSrc, PIXI.primitiveShaderFragmentSrc) + + gl.useProgram(shaderProgram); + + shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); + shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); + + shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); + shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); + + + //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(shaderProgram.colorAttribute); +//gl.enableVertexAttribArray(program.textureCoordAttribute); + + shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); + + PIXI.primitiveProgram = shaderProgram; + + +} + +PIXI.initDefaultShader = function() +{ + PIXI.defaultShader = new PIXI.PixiShader(); + PIXI.defaultShader.init(); + PIXI.activateShader(PIXI.defaultShader); + /* + PIXI.shaderStack.push(PIXI.defaultShader); + PIXI.current*/ +} + +PIXI.initDefaultStripShader = function() +{ + var gl = this.gl; + var shaderProgram = PIXI.compileProgram(PIXI.stripShaderVertexSrc, PIXI.stripShaderFragmentSrc) + + gl.useProgram(shaderProgram); + + shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); + shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); + shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); + shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); + shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); + + shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); + shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); + shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); + + PIXI.stripShaderProgram = shaderProgram; +} + +PIXI.CompileVertexShader = function(gl, shaderSrc) +{ + return PIXI._CompileShader(gl, shaderSrc, gl.VERTEX_SHADER); +} + +PIXI.CompileFragmentShader = function(gl, shaderSrc) +{ + return PIXI._CompileShader(gl, shaderSrc, gl.FRAGMENT_SHADER); +} + +PIXI._CompileShader = function(gl, shaderSrc, shaderType) +{ + var src = shaderSrc.join("\n"); + var shader = gl.createShader(shaderType); + gl.shaderSource(shader, src); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + alert(gl.getShaderInfoLog(shader)); + return null; + } + + return shader; +} + + +PIXI.compileProgram = function(vertexSrc, fragmentSrc) +{ + var gl = PIXI.gl; + var fragmentShader = PIXI.CompileFragmentShader(gl, fragmentSrc); + var vertexShader = PIXI.CompileVertexShader(gl, vertexSrc); + + var shaderProgram = gl.createProgram(); + + gl.attachShader(shaderProgram, vertexShader); + gl.attachShader(shaderProgram, fragmentShader); + gl.linkProgram(shaderProgram); + + if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { + alert("Could not initialise shaders"); + } + + return shaderProgram; +} + +PIXI.activateShader = function(shader) +{ + PIXI.shaderStack.push(shader); + + //console.log(">>>") + var gl = PIXI.gl; + + var shaderProgram = shader.program; + + // map uniforms.. + gl.useProgram(shaderProgram); + + gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + gl.enableVertexAttribArray(shaderProgram.colorAttribute); + gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); + + shader.syncUniforms(); + + PIXI.currentShader = shaderProgram; +} + + +PIXI.popShader = function() +{ + var gl = PIXI.gl; + // activate last program.. + var lastProgram = PIXI.shaderStack.pop(); + + var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; + + gl.useProgram(shaderProgram); + + PIXI.currentShader = shaderProgram; +} + +PIXI.activatePrimitiveShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.primitiveProgram); + + //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); + gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + + //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); +} + +PIXI.deactivatePrimitiveShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.currentShader); + + gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.PixiShader = function() +{ + // the webGL program.. + this.program; + + this.fragmentSrc = [ + "precision lowp float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", + "}" + ]; + +} + +PIXI.PixiShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get the default shader bits! + program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); + program.colorAttribute = gl.getAttribLocation(program, "aColor"); + program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); + + program.projectionVector = gl.getUniformLocation(program, "projectionVector"); + program.samplerUniform = gl.getUniformLocation(program, "uSampler"); + + // add those custom shaders! + for (var key in this.uniforms) + { + // get the uniform locations.. + program[key] = gl.getUniformLocation(program, key); + } + + this.program = program; +} + +PIXI.PixiShader.prototype.syncUniforms = function() +{ + var gl = PIXI.gl; + + for (var key in this.uniforms) + { + //var + var type = this.uniforms[key].type; + + // need to grow this! + if(type == "f") + { + gl.uniform1f(this.program[key], this.uniforms[key].value); + } + else if(type == "mat4") + { + gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); + } + } + +} + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * A set of functions used by the webGL renderer to draw the primitive graphics data + * + * @class CanvasGraphics + */ +PIXI.WebGLGraphics = function() +{ + +} + +/** + * Renders the graphics object + * + * @static + * @private + * @method renderGraphics + * @param graphics {Graphics} + * @param projection {Object} + */ +PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) +{ + var gl = PIXI.gl; + + if(!graphics._webGL)graphics._webGL = {points:[], indices:[], lastIndex:0, + buffer:gl.createBuffer(), + indexBuffer:gl.createBuffer()}; + + if(graphics.dirty) + { + graphics.dirty = false; + + if(graphics.clearDirty) + { + graphics.clearDirty = false; + + graphics._webGL.lastIndex = 0; + graphics._webGL.points = []; + graphics._webGL.indices = []; + + } + + PIXI.WebGLGraphics.updateGraphics(graphics); + } + + + PIXI.activatePrimitiveShader(); + + // This could be speeded up fo sure! + var m = PIXI.mat3.clone(graphics.worldTransform); + + PIXI.mat3.transpose(m); + + // set the matrix transform for the + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + + gl.uniformMatrix3fv(PIXI.primitiveProgram.translationMatrix, false, m); + + gl.uniform2f(PIXI.primitiveProgram.projectionVector, projection.x, projection.y); + + gl.uniform1f(PIXI.primitiveProgram.alpha, graphics.worldAlpha); + + gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); + + // WHY DOES THIS LINE NEED TO BE THERE??? + //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + // its not even used.. but need to be set or it breaks? + // only on pc though.. + + gl.vertexAttribPointer(PIXI.primitiveProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 4 * 6, 0); + gl.vertexAttribPointer(PIXI.primitiveProgram.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4); + + // set the index buffer! + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); + + gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); + + PIXI.deactivatePrimitiveShader(); + + // return to default shader... +// PIXI.activateShader(PIXI.defaultShader); +} + +/** + * Updates the graphics object + * + * @static + * @private + * @method updateGraphics + * @param graphics {Graphics} + */ +PIXI.WebGLGraphics.updateGraphics = function(graphics) +{ + for (var i=graphics._webGL.lastIndex; i < graphics.graphicsData.length; i++) + { + var data = graphics.graphicsData[i]; + + if(data.type == PIXI.Graphics.POLY) + { + if(data.fill) + { + if(data.points.length>3) + PIXI.WebGLGraphics.buildPoly(data, graphics._webGL); + } + + if(data.lineWidth > 0) + { + PIXI.WebGLGraphics.buildLine(data, graphics._webGL); + } + } + else if(data.type == PIXI.Graphics.RECT) + { + PIXI.WebGLGraphics.buildRectangle(data, graphics._webGL); + } + else if(data.type == PIXI.Graphics.CIRC || data.type == PIXI.Graphics.ELIP) + { + PIXI.WebGLGraphics.buildCircle(data, graphics._webGL); + } + }; + + graphics._webGL.lastIndex = graphics.graphicsData.length; + + var gl = PIXI.gl; + + graphics._webGL.glPoints = new Float32Array(graphics._webGL.points); + + gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); + gl.bufferData(gl.ARRAY_BUFFER, graphics._webGL.glPoints, gl.STATIC_DRAW); + + graphics._webGL.glIndicies = new Uint16Array(graphics._webGL.indices); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.glIndicies, gl.STATIC_DRAW); +} + +/** + * Builds a rectangle to draw + * + * @static + * @private + * @method buildRectangle + * @param graphics {Graphics} + * @param webGLData {Object} + */ +PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData) +{ + // --- // + // need to convert points to a nice regular data + // + var rectData = graphicsData.points; + var x = rectData[0]; + var y = rectData[1]; + var width = rectData[2]; + var height = rectData[3]; + + + if(graphicsData.fill) + { + var color = HEXtoRGB(graphicsData.fillColor); + var alpha = graphicsData.fillAlpha; + + var r = color[0] * alpha; + var g = color[1] * alpha; + var b = color[2] * alpha; + + var verts = webGLData.points; + var indices = webGLData.indices; + + var vertPos = verts.length/6; + + // start + verts.push(x, y); + verts.push(r, g, b, alpha); + + verts.push(x + width, y); + verts.push(r, g, b, alpha); + + verts.push(x , y + height); + verts.push(r, g, b, alpha); + + verts.push(x + width, y + height); + verts.push(r, g, b, alpha); + + // insert 2 dead triangles.. + indices.push(vertPos, vertPos, vertPos+1, vertPos+2, vertPos+3, vertPos+3) + } + + if(graphicsData.lineWidth) + { + graphicsData.points = [x, y, + x + width, y, + x + width, y + height, + x, y + height, + x, y]; + + PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); + } + +} + +/** + * Builds a circle to draw + * + * @static + * @private + * @method buildCircle + * @param graphics {Graphics} + * @param webGLData {Object} + */ +PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData) +{ + // --- // + // need to convert points to a nice regular data + // + var rectData = graphicsData.points; + var x = rectData[0]; + var y = rectData[1]; + var width = rectData[2]; + var height = rectData[3]; + + var totalSegs = 40; + var seg = (Math.PI * 2) / totalSegs ; + + if(graphicsData.fill) + { + var color = HEXtoRGB(graphicsData.fillColor); + var alpha = graphicsData.fillAlpha; + + var r = color[0] * alpha; + var g = color[1] * alpha; + var b = color[2] * alpha; + + var verts = webGLData.points; + var indices = webGLData.indices; + + var vecPos = verts.length/6; + + indices.push(vecPos); + + for (var i=0; i < totalSegs + 1 ; i++) + { + verts.push(x,y, r, g, b, alpha); + + verts.push(x + Math.sin(seg * i) * width, + y + Math.cos(seg * i) * height, + r, g, b, alpha); + + indices.push(vecPos++, vecPos++); + }; + + indices.push(vecPos-1); + } + + if(graphicsData.lineWidth) + { + graphicsData.points = []; + + for (var i=0; i < totalSegs + 1; i++) + { + graphicsData.points.push(x + Math.sin(seg * i) * width, + y + Math.cos(seg * i) * height) + }; + + PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); + } + +} + +/** + * Builds a line to draw + * + * @static + * @private + * @method buildLine + * @param graphics {Graphics} + * @param webGLData {Object} + */ +PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) +{ + // TODO OPTIMISE! + + var wrap = true; + var points = graphicsData.points; + if(points.length == 0)return; + + // get first and last point.. figure out the middle! + var firstPoint = new PIXI.Point( points[0], points[1] ); + var lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); + + // if the first point is the last point - goona have issues :) + if(firstPoint.x == lastPoint.x && firstPoint.y == lastPoint.y) + { + points.pop(); + points.pop(); + + lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); + + var midPointX = lastPoint.x + (firstPoint.x - lastPoint.x) *0.5; + var midPointY = lastPoint.y + (firstPoint.y - lastPoint.y) *0.5; + + points.unshift(midPointX, midPointY); + points.push(midPointX, midPointY) + } + + var verts = webGLData.points; + var indices = webGLData.indices; + var length = points.length / 2; + var indexCount = points.length; + var indexStart = verts.length/6; + + // DRAW the Line + var width = graphicsData.lineWidth / 2; + + // sort color + var color = HEXtoRGB(graphicsData.lineColor); + var alpha = graphicsData.lineAlpha; + var r = color[0] * alpha; + var g = color[1] * alpha; + var b = color[2] * alpha; + + var p1x, p1y, p2x, p2y, p3x, p3y; + var perpx, perpy, perp2x, perp2y, perp3x, perp3y; + var ipx, ipy; + var a1, b1, c1, a2, b2, c2; + var denom, pdist, dist; + + p1x = points[0]; + p1y = points[1]; + + p2x = points[2]; + p2y = points[3]; + + perpx = -(p1y - p2y); + perpy = p1x - p2x; + + dist = Math.sqrt(perpx*perpx + perpy*perpy); + + perpx /= dist; + perpy /= dist; + perpx *= width; + perpy *= width; + + // start + verts.push(p1x - perpx , p1y - perpy, + r, g, b, alpha); + + verts.push(p1x + perpx , p1y + perpy, + r, g, b, alpha); + + for (var i = 1; i < length-1; i++) + { + p1x = points[(i-1)*2]; + p1y = points[(i-1)*2 + 1]; + + p2x = points[(i)*2] + p2y = points[(i)*2 + 1] + + p3x = points[(i+1)*2]; + p3y = points[(i+1)*2 + 1]; + + perpx = -(p1y - p2y); + perpy = p1x - p2x; + + dist = Math.sqrt(perpx*perpx + perpy*perpy); + perpx /= dist; + perpy /= dist; + perpx *= width; + perpy *= width; + + perp2x = -(p2y - p3y); + perp2y = p2x - p3x; + + dist = Math.sqrt(perp2x*perp2x + perp2y*perp2y); + perp2x /= dist; + perp2y /= dist; + perp2x *= width; + perp2y *= width; + + a1 = (-perpy + p1y) - (-perpy + p2y); + b1 = (-perpx + p2x) - (-perpx + p1x); + c1 = (-perpx + p1x) * (-perpy + p2y) - (-perpx + p2x) * (-perpy + p1y); + a2 = (-perp2y + p3y) - (-perp2y + p2y); + b2 = (-perp2x + p2x) - (-perp2x + p3x); + c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y); + + denom = a1*b2 - a2*b1; + + if (denom == 0) { + denom+=1; + } + + px = (b1*c2 - b2*c1)/denom; + py = (a2*c1 - a1*c2)/denom; + + pdist = (px -p2x) * (px -p2x) + (py -p2y) + (py -p2y); + + if(pdist > 140 * 140) + { + perp3x = perpx - perp2x; + perp3y = perpy - perp2y; + + dist = Math.sqrt(perp3x*perp3x + perp3y*perp3y); + perp3x /= dist; + perp3y /= dist; + perp3x *= width; + perp3y *= width; + + verts.push(p2x - perp3x, p2y -perp3y); + verts.push(r, g, b, alpha); + + verts.push(p2x + perp3x, p2y +perp3y); + verts.push(r, g, b, alpha); + + verts.push(p2x - perp3x, p2y -perp3y); + verts.push(r, g, b, alpha); + + indexCount++; + } + else + { + verts.push(px , py); + verts.push(r, g, b, alpha); + + verts.push(p2x - (px-p2x), p2y - (py - p2y)); + verts.push(r, g, b, alpha); + } + } + + p1x = points[(length-2)*2] + p1y = points[(length-2)*2 + 1] + + p2x = points[(length-1)*2] + p2y = points[(length-1)*2 + 1] + + perpx = -(p1y - p2y) + perpy = p1x - p2x; + + dist = Math.sqrt(perpx*perpx + perpy*perpy); + perpx /= dist; + perpy /= dist; + perpx *= width; + perpy *= width; + + verts.push(p2x - perpx , p2y - perpy) + verts.push(r, g, b, alpha); + + verts.push(p2x + perpx , p2y + perpy) + verts.push(r, g, b, alpha); + + indices.push(indexStart); + + for (var i=0; i < indexCount; i++) + { + indices.push(indexStart++); + }; + + indices.push(indexStart-1); +} + +/** + * Builds a polygon to draw + * + * @static + * @private + * @method buildPoly + * @param graphics {Graphics} + * @param webGLData {Object} + */ +PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData) +{ + var points = graphicsData.points; + if(points.length < 6)return; + + // get first and last point.. figure out the middle! + var verts = webGLData.points; + var indices = webGLData.indices; + + var length = points.length / 2; + + // sort color + var color = HEXtoRGB(graphicsData.fillColor); + var alpha = graphicsData.fillAlpha; + var r = color[0] * alpha; + var g = color[1] * alpha; + var b = color[2] * alpha; + + var triangles = PIXI.PolyK.Triangulate(points); + + var vertPos = verts.length / 6; + + for (var i=0; i < triangles.length; i+=3) + { + indices.push(triangles[i] + vertPos); + indices.push(triangles[i] + vertPos); + indices.push(triangles[i+1] + vertPos); + indices.push(triangles[i+2] +vertPos); + indices.push(triangles[i+2] + vertPos); + }; + + for (var i = 0; i < length; i++) + { + verts.push(points[i * 2], points[i * 2 + 1], + r, g, b, alpha); + }; +} + +function HEXtoRGB(hex) { + return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; +} + + + + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI._defaultFrame = new PIXI.Rectangle(0,0,1,1); + +// an instance of the gl context.. +// only one at the moment :/ +PIXI.gl; + +/** + * the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer + * should be used for browsers support webGL. This Render works by automatically managing webGLBatchs. + * So no need for Sprite Batch's or Sprite Cloud's + * Dont forget to add the view to your DOM or you will not see anything :) + * + * @class WebGLRenderer + * @constructor + * @param width=0 {Number} the width of the canvas view + * @param height=0 {Number} the height of the canvas view + * @param view {Canvas} the canvas to use as a view, optional + * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) + * + */ +PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) +{ + // do a catch.. only 1 webGL renderer.. + + this.transparent = !!transparent; + + this.width = width || 800; + this.height = height || 600; + + this.view = view || document.createElement( 'canvas' ); + this.view.width = this.width; + this.view.height = this.height; + + // deal with losing context.. + var scope = this; + this.view.addEventListener('webglcontextlost', function(event) { scope.handleContextLost(event); }, false) + this.view.addEventListener('webglcontextrestored', function(event) { scope.handleContextRestored(event); }, false) + + this.batchs = []; + + try + { + PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { + alpha: this.transparent, + antialias:!!antialias, // SPEED UP?? + premultipliedAlpha:false, + stencil:true + }); + } + catch (e) + { + throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); + } + + PIXI.initDefaultShader(); + PIXI.initPrimitiveShader(); + PIXI.initDefaultStripShader(); + + +// PIXI.activateDefaultShader(); + + var gl = this.gl; + PIXI.WebGLRenderer.gl = gl; + + this.batch = new PIXI.WebGLBatch(gl); + gl.disable(gl.DEPTH_TEST); + gl.disable(gl.CULL_FACE); + + gl.enable(gl.BLEND); + gl.colorMask(true, true, true, this.transparent); + + PIXI.projection = new PIXI.Point(400, 300); + + this.resize(this.width, this.height); + this.contextLost = false; + + PIXI.activateShader(PIXI.defaultShader); + + this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); + +} + +// constructor +PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; + +/** + * Gets a new WebGLBatch from the pool + * + * @static + * @method getBatch + * @return {WebGLBatch} + * @private + */ +PIXI.WebGLRenderer.getBatch = function() +{ + if(PIXI._batchs.length == 0) + { + return new PIXI.WebGLBatch(PIXI.WebGLRenderer.gl); + } + else + { + return PIXI._batchs.pop(); + } +} + +/** + * Puts a batch back into the pool + * + * @static + * @method returnBatch + * @param batch {WebGLBatch} The batch to return + * @private + */ +PIXI.WebGLRenderer.returnBatch = function(batch) +{ + batch.clean(); + PIXI._batchs.push(batch); +} + +/** + * Renders the stage to its webGL view + * + * @method render + * @param stage {Stage} the Stage element to be rendered + */ +PIXI.WebGLRenderer.prototype.render = function(stage) +{ + if(this.contextLost)return; + + + // if rendering a new stage clear the batchs.. + if(this.__stage !== stage) + { + // TODO make this work + // dont think this is needed any more? + this.__stage = stage; + this.stageRenderGroup.setRenderable(stage); + } + + // TODO not needed now... + // update children if need be + // best to remove first! + /*for (var i=0; i < stage.__childrenRemoved.length; i++) + { + var group = stage.__childrenRemoved[i].__renderGroup + if(group)group.removeDisplayObject(stage.__childrenRemoved[i]); + }*/ + + // update any textures + PIXI.WebGLRenderer.updateTextures(); + + // update the scene graph + PIXI.visibleCount++; + stage.updateTransform(); + + var gl = this.gl; + + // -- Does this need to be set every frame? -- // + gl.colorMask(true, true, true, this.transparent); + gl.viewport(0, 0, this.width, this.height); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); + gl.clear(gl.COLOR_BUFFER_BIT); + + // HACK TO TEST + + this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; + this.stageRenderGroup.render(PIXI.projection); + + // interaction + // run interaction! + if(stage.interactive) + { + //need to add some events! + if(!stage._interactiveEventsAdded) + { + stage._interactiveEventsAdded = true; + stage.interactionManager.setTarget(this); + } + } + + // after rendering lets confirm all frames that have been uodated.. + if(PIXI.Texture.frameUpdates.length > 0) + { + for (var i=0; i < PIXI.Texture.frameUpdates.length; i++) + { + PIXI.Texture.frameUpdates[i].updateFrame = false; + }; + + PIXI.Texture.frameUpdates = []; + } +} + +/** + * Updates the textures loaded into this webgl renderer + * + * @static + * @method updateTextures + * @private + */ +PIXI.WebGLRenderer.updateTextures = function() +{ + //TODO break this out into a texture manager... + for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); + for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); + PIXI.texturesToUpdate = []; + PIXI.texturesToDestroy = []; +} + +/** + * Updates a loaded webgl texture + * + * @static + * @method updateTexture + * @param texture {Texture} The texture to update + * @private + */ +PIXI.WebGLRenderer.updateTexture = function(texture) +{ + //TODO break this out into a texture manager... + var gl = PIXI.gl; + + if(!texture._glTexture) + { + texture._glTexture = gl.createTexture(); + } + + if(texture.hasLoaded) + { + gl.bindTexture(gl.TEXTURE_2D, texture._glTexture); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); + + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + + // reguler... + + if(!texture._powerOf2) + { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + else + { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); + } + + gl.bindTexture(gl.TEXTURE_2D, null); + } +} + +/** + * Destroys a loaded webgl texture + * + * @method destroyTexture + * @param texture {Texture} The texture to update + * @private + */ +PIXI.WebGLRenderer.destroyTexture = function(texture) +{ + //TODO break this out into a texture manager... + var gl = PIXI.gl; + + if(texture._glTexture) + { + texture._glTexture = gl.createTexture(); + gl.deleteTexture(gl.TEXTURE_2D, texture._glTexture); + } +} + +/** + * resizes the webGL view to the specified width and height + * + * @method resize + * @param width {Number} the new width of the webGL view + * @param height {Number} the new height of the webGL view + */ +PIXI.WebGLRenderer.prototype.resize = function(width, height) +{ + this.width = width; + this.height = height; + + this.view.width = width; + this.view.height = height; + + this.gl.viewport(0, 0, this.width, this.height); + + //var projectionMatrix = this.projectionMatrix; + + PIXI.projection.x = this.width/2; + PIXI.projection.y = this.height/2; + +// projectionMatrix[0] = 2/this.width; +// projectionMatrix[5] = -2/this.height; +// projectionMatrix[12] = -1; +// projectionMatrix[13] = 1; +} + +/** + * Handles a lost webgl context + * + * @method handleContextLost + * @param event {Event} + * @private + */ +PIXI.WebGLRenderer.prototype.handleContextLost = function(event) +{ + event.preventDefault(); + this.contextLost = true; +} + +/** + * Handles a restored webgl context + * + * @method handleContextRestored + * @param event {Event} + * @private + */ +PIXI.WebGLRenderer.prototype.handleContextRestored = function(event) +{ + this.gl = this.view.getContext("experimental-webgl", { + alpha: true + }); + + this.initShaders(); + + for(var key in PIXI.TextureCache) + { + var texture = PIXI.TextureCache[key].baseTexture; + texture._glTexture = null; + PIXI.WebGLRenderer.updateTexture(texture); + }; + + for (var i=0; i < this.batchs.length; i++) + { + this.batchs[i].restoreLostContext(this.gl)// + this.batchs[i].dirty = true; + }; + + PIXI._restoreBatchs(this.gl); + + this.contextLost = false; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI._batchs = []; + +/** + * @private + */ +PIXI._getBatch = function(gl) +{ + if(PIXI._batchs.length == 0) + { + return new PIXI.WebGLBatch(gl); + } + else + { + return PIXI._batchs.pop(); + } +} + +/** + * @private + */ +PIXI._returnBatch = function(batch) +{ + batch.clean(); + PIXI._batchs.push(batch); +} + +/** + * @private + */ +PIXI._restoreBatchs = function(gl) +{ + for (var i=0; i < PIXI._batchs.length; i++) + { + PIXI._batchs[i].restoreLostContext(gl); + }; +} + +/** + * A WebGLBatch Enables a group of sprites to be drawn using the same settings. + * if a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch. + * All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites + * in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled + * automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster + * the webGL renderer will run. + * + * @class WebGLBatch + * @constructor + * @param gl {WebGLContext} an instance of the webGL context + */ +PIXI.WebGLBatch = function(gl) +{ + this.gl = gl; + + this.size = 0; + + this.vertexBuffer = gl.createBuffer(); + this.indexBuffer = gl.createBuffer(); + this.uvBuffer = gl.createBuffer(); + this.colorBuffer = gl.createBuffer(); + this.blendMode = PIXI.blendModes.NORMAL; + this.dynamicSize = 1; +} + +// constructor +PIXI.WebGLBatch.prototype.constructor = PIXI.WebGLBatch; + +/** + * Cleans the batch so that is can be returned to an object pool and reused + * + * @method clean + */ +PIXI.WebGLBatch.prototype.clean = function() +{ + this.verticies = []; + this.uvs = []; + this.indices = []; + this.colors = []; + this.dynamicSize = 1; + this.texture = null; + this.last = null; + this.size = 0; + this.head; + this.tail; +} + +/** + * Recreates the buffers in the event of a context loss + * + * @method restoreLostContext + * @param gl {WebGLContext} + */ +PIXI.WebGLBatch.prototype.restoreLostContext = function(gl) +{ + this.gl = gl; + this.vertexBuffer = gl.createBuffer(); + this.indexBuffer = gl.createBuffer(); + this.uvBuffer = gl.createBuffer(); + this.colorBuffer = gl.createBuffer(); +} + +/** + * inits the batch's texture and blend mode based if the supplied sprite + * + * @method init + * @param sprite {Sprite} the first sprite to be added to the batch. Only sprites with + * the same base texture and blend mode will be allowed to be added to this batch + */ +PIXI.WebGLBatch.prototype.init = function(sprite) +{ + sprite.batch = this; + this.dirty = true; + this.blendMode = sprite.blendMode; + this.texture = sprite.texture.baseTexture; + this.head = sprite; + this.tail = sprite; + this.size = 1; + + this.growBatch(); +} + +/** + * inserts a sprite before the specified sprite + * + * @method insertBefore + * @param sprite {Sprite} the sprite to be added + * @param nextSprite {nextSprite} the first sprite will be inserted before this sprite + */ +PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) +{ + this.size++; + + sprite.batch = this; + this.dirty = true; + var tempPrev = nextSprite.__prev; + nextSprite.__prev = sprite; + sprite.__next = nextSprite; + + if(tempPrev) + { + sprite.__prev = tempPrev; + tempPrev.__next = sprite; + } + else + { + this.head = sprite; + } +} + +/** + * inserts a sprite after the specified sprite + * + * @method insertAfter + * @param sprite {Sprite} the sprite to be added + * @param previousSprite {Sprite} the first sprite will be inserted after this sprite + */ +PIXI.WebGLBatch.prototype.insertAfter = function(sprite, previousSprite) +{ + this.size++; + + sprite.batch = this; + this.dirty = true; + + var tempNext = previousSprite.__next; + previousSprite.__next = sprite; + sprite.__prev = previousSprite; + + if(tempNext) + { + sprite.__next = tempNext; + tempNext.__prev = sprite; + } + else + { + this.tail = sprite + } +} + +/** + * removes a sprite from the batch + * + * @method remove + * @param sprite {Sprite} the sprite to be removed + */ +PIXI.WebGLBatch.prototype.remove = function(sprite) +{ + this.size--; + + if(this.size == 0) + { + sprite.batch = null; + sprite.__prev = null; + sprite.__next = null; + return; + } + + if(sprite.__prev) + { + sprite.__prev.__next = sprite.__next; + } + else + { + this.head = sprite.__next; + this.head.__prev = null; + } + + if(sprite.__next) + { + sprite.__next.__prev = sprite.__prev; + } + else + { + this.tail = sprite.__prev; + this.tail.__next = null + } + + sprite.batch = null; + sprite.__next = null; + sprite.__prev = null; + this.dirty = true; +} + +/** + * Splits the batch into two with the specified sprite being the start of the new batch. + * + * @method split + * @param sprite {Sprite} the sprite that indicates where the batch should be split + * @return {WebGLBatch} the new batch + */ +PIXI.WebGLBatch.prototype.split = function(sprite) +{ + this.dirty = true; + + var batch = new PIXI.WebGLBatch(this.gl); + batch.init(sprite); + batch.texture = this.texture; + batch.tail = this.tail; + + this.tail = sprite.__prev; + this.tail.__next = null; + + sprite.__prev = null; + // return a splite batch! + + // TODO this size is wrong! + // need to recalculate :/ problem with a linked list! + // unless it gets calculated in the "clean"? + + // need to loop through items as there is no way to know the length on a linked list :/ + var tempSize = 0; + while(sprite) + { + tempSize++; + sprite.batch = batch; + sprite = sprite.__next; + } + + batch.size = tempSize; + this.size -= tempSize; + + return batch; +} + +/** + * Merges two batchs together + * + * @method merge + * @param batch {WebGLBatch} the batch that will be merged + */ +PIXI.WebGLBatch.prototype.merge = function(batch) +{ + this.dirty = true; + + this.tail.__next = batch.head; + batch.head.__prev = this.tail; + + this.size += batch.size; + + this.tail = batch.tail; + + var sprite = batch.head; + while(sprite) + { + sprite.batch = this; + sprite = sprite.__next; + } +} + +/** + * Grows the size of the batch. As the elements in the batch cannot have a dynamic size this + * function is used to increase the size of the batch. It also creates a little extra room so + * that the batch does not need to be resized every time a sprite is added + * + * @method growBatch + */ +PIXI.WebGLBatch.prototype.growBatch = function() +{ + var gl = this.gl; + if( this.size == 1) + { + this.dynamicSize = 1; + } + else + { + this.dynamicSize = this.size * 1.5 + } + // grow verts + this.verticies = new Float32Array(this.dynamicSize * 8); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); + + this.uvs = new Float32Array( this.dynamicSize * 8 ); + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); + + this.dirtyUVS = true; + + this.colors = new Float32Array( this.dynamicSize * 4 ); + gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); + + this.dirtyColors = true; + + this.indices = new Uint16Array(this.dynamicSize * 6); + var length = this.indices.length/6; + + for (var i=0; i < length; i++) + { + var index2 = i * 6; + var index3 = i * 4; + this.indices[index2 + 0] = index3 + 0; + this.indices[index2 + 1] = index3 + 1; + this.indices[index2 + 2] = index3 + 2; + this.indices[index2 + 3] = index3 + 0; + this.indices[index2 + 4] = index3 + 2; + this.indices[index2 + 5] = index3 + 3; + }; + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); +} + +/** + * Refresh's all the data in the batch and sync's it with the webGL buffers + * + * @method refresh + */ +PIXI.WebGLBatch.prototype.refresh = function() +{ + var gl = this.gl; + + if (this.dynamicSize < this.size) + { + this.growBatch(); + } + + var indexRun = 0; + var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index; + var a, b, c, d, tx, ty; + + var displayObject = this.head; + + while(displayObject) + { + index = indexRun * 8; + + var texture = displayObject.texture; + + var frame = texture.frame; + var tw = texture.baseTexture.width; + var th = texture.baseTexture.height; + + this.uvs[index + 0] = frame.x / tw; + this.uvs[index +1] = frame.y / th; + + this.uvs[index +2] = (frame.x + frame.width) / tw; + this.uvs[index +3] = frame.y / th; + + this.uvs[index +4] = (frame.x + frame.width) / tw; + this.uvs[index +5] = (frame.y + frame.height) / th; + + this.uvs[index +6] = frame.x / tw; + this.uvs[index +7] = (frame.y + frame.height) / th; + + displayObject.updateFrame = false; + + colorIndex = indexRun * 4; + this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; + + displayObject = displayObject.__next; + + indexRun ++; + } + + this.dirtyUVS = true; + this.dirtyColors = true; +} + +/** + * Updates all the relevant geometry and uploads the data to the GPU + * + * @method update + */ +PIXI.WebGLBatch.prototype.update = function() +{ + var gl = this.gl; + var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index, index2, index3 + + var a, b, c, d, tx, ty; + + var indexRun = 0; + + var displayObject = this.head; + + while(displayObject) + { + if(displayObject.vcount === PIXI.visibleCount) + { + width = displayObject.texture.frame.width; + height = displayObject.texture.frame.height; + + // TODO trim?? + aX = displayObject.anchor.x;// - displayObject.texture.trim.x + aY = displayObject.anchor.y; //- displayObject.texture.trim.y + w0 = width * (1-aX); + w1 = width * -aX; + + h0 = height * (1-aY); + h1 = height * -aY; + + index = indexRun * 8; + + worldTransform = displayObject.worldTransform; + + a = worldTransform[0]; + b = worldTransform[3]; + c = worldTransform[1]; + d = worldTransform[4]; + tx = worldTransform[2]; + ty = worldTransform[5]; + + this.verticies[index + 0 ] = a * w1 + c * h1 + tx; + this.verticies[index + 1 ] = d * h1 + b * w1 + ty; + + this.verticies[index + 2 ] = a * w0 + c * h1 + tx; + this.verticies[index + 3 ] = d * h1 + b * w0 + ty; + + this.verticies[index + 4 ] = a * w0 + c * h0 + tx; + this.verticies[index + 5 ] = d * h0 + b * w0 + ty; + + this.verticies[index + 6] = a * w1 + c * h0 + tx; + this.verticies[index + 7] = d * h0 + b * w1 + ty; + + if(displayObject.updateFrame || displayObject.texture.updateFrame) + { + this.dirtyUVS = true; + + var texture = displayObject.texture; + + var frame = texture.frame; + var tw = texture.baseTexture.width; + var th = texture.baseTexture.height; + + this.uvs[index + 0] = frame.x / tw; + this.uvs[index +1] = frame.y / th; + + this.uvs[index +2] = (frame.x + frame.width) / tw; + this.uvs[index +3] = frame.y / th; + + this.uvs[index +4] = (frame.x + frame.width) / tw; + this.uvs[index +5] = (frame.y + frame.height) / th; + + this.uvs[index +6] = frame.x / tw; + this.uvs[index +7] = (frame.y + frame.height) / th; + + displayObject.updateFrame = false; + } + + // TODO this probably could do with some optimisation.... + if(displayObject.cacheAlpha != displayObject.worldAlpha) + { + displayObject.cacheAlpha = displayObject.worldAlpha; + + var colorIndex = indexRun * 4; + this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; + this.dirtyColors = true; + } + } + else + { + index = indexRun * 8; + + this.verticies[index + 0 ] = 0; + this.verticies[index + 1 ] = 0; + + this.verticies[index + 2 ] = 0; + this.verticies[index + 3 ] = 0; + + this.verticies[index + 4 ] = 0; + this.verticies[index + 5 ] = 0; + + this.verticies[index + 6] = 0; + this.verticies[index + 7] = 0; + } + + indexRun++; + displayObject = displayObject.__next; + } +} + +/** + * Draws the batch to the frame buffer + * + * @method render + */ +PIXI.WebGLBatch.prototype.render = function(start, end) +{ + start = start || 0; + + if(end == undefined)end = this.size; + + if(this.dirty) + { + this.refresh(); + this.dirty = false; + } + + if (this.size == 0)return; + + this.update(); + var gl = this.gl; + + //TODO optimize this! + + var shaderProgram = PIXI.currentShader; + + //gl.useProgram(shaderProgram); + + // update the verts.. + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + // ok.. + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) + gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + // update the uvs + var isDefault = (shaderProgram == PIXI.shaderProgram) + + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); + + if(this.dirtyUVS) + { + this.dirtyUVS = false; + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvs); + } + + gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, this.texture._glTexture); + + // update color! + gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); + + if(this.dirtyColors) + { + this.dirtyColors = false; + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.colors); + } + + gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); + // dont need to upload! + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + + var len = end - start; + + // DRAW THAT this! + gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * A WebGLBatch Enables a group of sprites to be drawn using the same settings. + * if a group of sprites all have the same baseTexture and blendMode then they can be + * grouped into a batch. All the sprites in a batch can then be drawn in one go by the + * GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch + * even if the batch only contains one sprite. Batching is handled automatically by the + * webGL renderer. A good tip is: the smaller the number of batchs there are, the faster + * the webGL renderer will run. + * + * @class WebGLBatch + * @contructor + * @param gl {WebGLContext} An instance of the webGL context + */ +PIXI.WebGLRenderGroup = function(gl) +{ + this.gl = gl; + this.root; + + this.backgroundColor; + this.batchs = []; + this.toRemove = []; +} + +// constructor +PIXI.WebGLRenderGroup.prototype.constructor = PIXI.WebGLRenderGroup; + +/** + * Add a display object to the webgl renderer + * + * @method setRenderable + * @param displayObject {DisplayObject} + * @private + */ +PIXI.WebGLRenderGroup.prototype.setRenderable = function(displayObject) +{ + // has this changed?? + if(this.root)this.removeDisplayObjectAndChildren(this.root); + + displayObject.worldVisible = displayObject.visible; + + // soooooo // + // to check if any batchs exist already?? + + // TODO what if its already has an object? should remove it + this.root = displayObject; + this.addDisplayObjectAndChildren(displayObject); +} + +/** + * Renders the stage to its webgl view + * + * @method render + * @param projection {Object} + */ +PIXI.WebGLRenderGroup.prototype.render = function(projection) +{ + PIXI.WebGLRenderer.updateTextures(); + + var gl = this.gl; + + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + // will render all the elements in the group + var renderable; + for (var i=0; i < this.batchs.length; i++) + { + + renderable = this.batchs[i]; + if(renderable instanceof PIXI.WebGLBatch) + { + this.batchs[i].render(); + continue; + } + + // non sprite batch.. + var worldVisible = renderable.vcount === PIXI.visibleCount; + + if(renderable instanceof PIXI.TilingSprite) + { + if(worldVisible)this.renderTilingSprite(renderable, projection); + } + else if(renderable instanceof PIXI.Strip) + { + if(worldVisible)this.renderStrip(renderable, projection); + } + else if(renderable instanceof PIXI.Graphics) + { + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); + } + else if(renderable instanceof PIXI.FilterBlock) + { + this.handleFilterBlock(renderable, projection); + } + } + +} + +/** + * Renders a specific displayObject + * + * @method renderSpecific + * @param displayObject {DisplayObject} + * @param projection {Object} + * @private + */ +PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection) +{ + PIXI.WebGLRenderer.updateTextures(); + + var gl = this.gl; + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + + // to do! + // render part of the scene... + + var startIndex; + var startBatchIndex; + + var endIndex; + var endBatchIndex; + + /* + * LOOK FOR THE NEXT SPRITE + * This part looks for the closest next sprite that can go into a batch + * it keeps looking until it finds a sprite or gets to the end of the display + * scene graph + */ + var nextRenderable = displayObject.first; + while(nextRenderable._iNext) + { + nextRenderable = nextRenderable._iNext; + if(nextRenderable.renderable && nextRenderable.__renderGroup)break; + } + var startBatch = nextRenderable.batch; + + if(nextRenderable instanceof PIXI.Sprite) + { + startBatch = nextRenderable.batch; + + var head = startBatch.head; + var next = head; + + // ok now we have the batch.. need to find the start index! + if(head == nextRenderable) + { + startIndex = 0; + } + else + { + startIndex = 1; + + while(head.__next != nextRenderable) + { + startIndex++; + head = head.__next; + } + } + } + else + { + startBatch = nextRenderable; + } + + // Get the LAST renderable object + var lastRenderable = displayObject; + var endBatch; + var lastItem = displayObject; + while(lastItem.children.length > 0) + { + lastItem = lastItem.children[lastItem.children.length-1]; + if(lastItem.renderable)lastRenderable = lastItem.last; + } + + if(lastRenderable instanceof PIXI.Sprite) + { + endBatch = lastRenderable.batch; + + var head = endBatch.head; + + if(head == lastRenderable) + { + endIndex = 0; + } + else + { + endIndex = 1; + + while(head.__next != lastRenderable) + { + endIndex++; + head = head.__next; + } + } + } + else + { + endBatch = lastRenderable; + } + + // TODO - need to fold this up a bit! + + if(startBatch == endBatch) + { + if(startBatch instanceof PIXI.WebGLBatch) + { + startBatch.render(startIndex, endIndex+1); + } + else + { + this.renderSpecial(startBatch, projection); + } + return; + } + + // now we have first and last! + startBatchIndex = this.batchs.indexOf(startBatch); + endBatchIndex = this.batchs.indexOf(endBatch); + + // DO the first batch + if(startBatch instanceof PIXI.WebGLBatch) + { + startBatch.render(startIndex); + } + else + { + this.renderSpecial(startBatch, projection); + } + + // DO the middle batchs.. + for (var i=startBatchIndex+1; i < endBatchIndex; i++) + { + renderable = this.batchs[i]; + + if(renderable instanceof PIXI.WebGLBatch) + { + this.batchs[i].render(); + } + else + { + this.renderSpecial(renderable, projection); + } + } + + // DO the last batch.. + if(endBatch instanceof PIXI.WebGLBatch) + { + endBatch.render(0, endIndex+1); + } + else + { + this.renderSpecial(endBatch, projection); + } +} + +/** + * Renders a specific renderable + * + * @method renderSpecial + * @param renderable {DisplayObject} + * @param projection {Object} + * @private + */ +PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) +{ + var sta = PIXI.shaderStack.length; + + var worldVisible = renderable.vcount === PIXI.visibleCount + + if(renderable instanceof PIXI.TilingSprite) + { + if(worldVisible)this.renderTilingSprite(renderable, projection); + } + else if(renderable instanceof PIXI.Strip) + { + if(worldVisible)this.renderStrip(renderable, projection); + } + else if(renderable instanceof PIXI.CustomRenderable) + { + if(worldVisible) renderable.renderWebGL(this, projection); + } + else if(renderable instanceof PIXI.Graphics) + { + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); + } + else if(renderable instanceof PIXI.FilterBlock) + { + this.handleFilterBlock(renderable, projection); + } +} + +PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) +{ + /* + * for now only masks are supported.. + */ + var gl = PIXI.gl; + + if(renderable.open) + { + if(renderable.data instanceof Array) + { + var filter = renderable.data[0]; + + if(!filter.shader) + { + var shader = new PIXI.PixiShader(); + + shader.fragmentSrc = filter.fragmentSrc; + shader.uniforms = filter.uniforms; + shader.init(); + + filter.shader = shader + } + + PIXI.activateShader(filter.shader); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } + else + { + gl.enable(gl.STENCIL_TEST); + + gl.colorMask(false, false, false, false); + gl.stencilFunc(gl.ALWAYS,1,0xff); + gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); + PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.NOTEQUAL,0,0xff); + gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); + } + } + else + { + if(renderable.data instanceof Array) + { + PIXI.popShader(); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } + else + { + gl.disable(gl.STENCIL_TEST); + } + } +} + +/** + * Updates a webgl texture + * + * @method updateTexture + * @param displayObject {DisplayObject} + * @private + */ +PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject) +{ + + // TODO definitely can optimse this function.. + + this.removeObject(displayObject); + + /* + * LOOK FOR THE PREVIOUS RENDERABLE + * This part looks for the closest previous sprite that can go into a batch + * It keeps going back until it finds a sprite or the stage + */ + var previousRenderable = displayObject.first; + while(previousRenderable != this.root) + { + previousRenderable = previousRenderable._iPrev; + if(previousRenderable.renderable && previousRenderable.__renderGroup)break; + } + + /* + * LOOK FOR THE NEXT SPRITE + * This part looks for the closest next sprite that can go into a batch + * it keeps looking until it finds a sprite or gets to the end of the display + * scene graph + */ + var nextRenderable = displayObject.last; + while(nextRenderable._iNext) + { + nextRenderable = nextRenderable._iNext; + if(nextRenderable.renderable && nextRenderable.__renderGroup)break; + } + + this.insertObject(displayObject, previousRenderable, nextRenderable); +} + +/** + * Adds filter blocks + * + * @method addFilterBlocks + * @param start {FilterBlock} + * @param end {FilterBlock} + * @private + */ +PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) +{ + start.__renderGroup = this; + end.__renderGroup = this; + /* + * LOOK FOR THE PREVIOUS RENDERABLE + * This part looks for the closest previous sprite that can go into a batch + * It keeps going back until it finds a sprite or the stage + */ + var previousRenderable = start; + while(previousRenderable != this.root.first) + { + previousRenderable = previousRenderable._iPrev; + if(previousRenderable.renderable && previousRenderable.__renderGroup)break; + } + this.insertAfter(start, previousRenderable); + + /* + * LOOK FOR THE NEXT SPRITE + * This part looks for the closest next sprite that can go into a batch + * it keeps looking until it finds a sprite or gets to the end of the display + * scene graph + */ + var previousRenderable2 = end; + while(previousRenderable2 != this.root.first) + { + previousRenderable2 = previousRenderable2._iPrev; + if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; + } + this.insertAfter(end, previousRenderable2); +} + +/** + * Remove filter blocks + * + * @method removeFilterBlocks + * @param start {FilterBlock} + * @param end {FilterBlock} + * @private + */ +PIXI.WebGLRenderGroup.prototype.removeFilterBlocks = function(start, end) +{ + this.removeObject(start); + this.removeObject(end); +} + +/** + * Adds a display object and children to the webgl context + * + * @method addDisplayObjectAndChildren + * @param displayObject {DisplayObject} + * @private + */ +PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayObject) +{ + if(displayObject.__renderGroup)displayObject.__renderGroup.removeDisplayObjectAndChildren(displayObject); + + /* + * LOOK FOR THE PREVIOUS RENDERABLE + * This part looks for the closest previous sprite that can go into a batch + * It keeps going back until it finds a sprite or the stage + */ + + var previousRenderable = displayObject.first; + while(previousRenderable != this.root.first) + { + previousRenderable = previousRenderable._iPrev; + if(previousRenderable.renderable && previousRenderable.__renderGroup)break; + } + + /* + * LOOK FOR THE NEXT SPRITE + * This part looks for the closest next sprite that can go into a batch + * it keeps looking until it finds a sprite or gets to the end of the display + * scene graph + */ + var nextRenderable = displayObject.last; + while(nextRenderable._iNext) + { + nextRenderable = nextRenderable._iNext; + if(nextRenderable.renderable && nextRenderable.__renderGroup)break; + } + + // one the display object hits this. we can break the loop + + var tempObject = displayObject.first; + var testObject = displayObject.last._iNext; + do + { + tempObject.__renderGroup = this; + + if(tempObject.renderable) + { + + this.insertObject(tempObject, previousRenderable, nextRenderable); + previousRenderable = tempObject; + } + + tempObject = tempObject._iNext; + } + while(tempObject != testObject) +} + +/** + * Removes a display object and children to the webgl context + * + * @method removeDisplayObjectAndChildren + * @param displayObject {DisplayObject} + * @private + */ +PIXI.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren = function(displayObject) +{ + if(displayObject.__renderGroup != this)return; + +// var displayObject = displayObject.first; + var lastObject = displayObject.last; + do + { + displayObject.__renderGroup = null; + if(displayObject.renderable)this.removeObject(displayObject); + displayObject = displayObject._iNext; + } + while(displayObject) +} + +/** + * Inserts a displayObject into the linked list + * + * @method insertObject + * @param displayObject {DisplayObject} + * @param previousObject {DisplayObject} + * @param nextObject {DisplayObject} + * @private + */ +PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousObject, nextObject) +{ + // while looping below THE OBJECT MAY NOT HAVE BEEN ADDED + var previousSprite = previousObject; + var nextSprite = nextObject; + + /* + * so now we have the next renderable and the previous renderable + * + */ + if(displayObject instanceof PIXI.Sprite) + { + var previousBatch + var nextBatch + + if(previousSprite instanceof PIXI.Sprite) + { + previousBatch = previousSprite.batch; + if(previousBatch) + { + if(previousBatch.texture == displayObject.texture.baseTexture && previousBatch.blendMode == displayObject.blendMode) + { + previousBatch.insertAfter(displayObject, previousSprite); + return; + } + } + } + else + { + // TODO reword! + previousBatch = previousSprite; + } + + if(nextSprite) + { + if(nextSprite instanceof PIXI.Sprite) + { + nextBatch = nextSprite.batch; + + //batch may not exist if item was added to the display list but not to the webGL + if(nextBatch) + { + if(nextBatch.texture == displayObject.texture.baseTexture && nextBatch.blendMode == displayObject.blendMode) + { + nextBatch.insertBefore(displayObject, nextSprite); + return; + } + else + { + if(nextBatch == previousBatch) + { + // THERE IS A SPLIT IN THIS BATCH! // + var splitBatch = previousBatch.split(nextSprite); + // COOL! + // add it back into the array + /* + * OOPS! + * seems the new sprite is in the middle of a batch + * lets split it.. + */ + var batch = PIXI.WebGLRenderer.getBatch(); + + var index = this.batchs.indexOf( previousBatch ); + batch.init(displayObject); + this.batchs.splice(index+1, 0, batch, splitBatch); + + return; + } + } + } + } + else + { + // TODO re-word! + + nextBatch = nextSprite; + } + } + + /* + * looks like it does not belong to any batch! + * but is also not intersecting one.. + * time to create anew one! + */ + + var batch = PIXI.WebGLRenderer.getBatch(); + batch.init(displayObject); + + if(previousBatch) // if this is invalid it means + { + var index = this.batchs.indexOf( previousBatch ); + this.batchs.splice(index+1, 0, batch); + } + else + { + this.batchs.push(batch); + } + + return; + } + else if(displayObject instanceof PIXI.TilingSprite) + { + + // add to a batch!! + this.initTilingSprite(displayObject); + // this.batchs.push(displayObject); + + } + else if(displayObject instanceof PIXI.Strip) + { + // add to a batch!! + this.initStrip(displayObject); + // this.batchs.push(displayObject); + } + else if(displayObject)// instanceof PIXI.Graphics) + { + //displayObject.initWebGL(this); + + // add to a batch!! + //this.initStrip(displayObject); + //this.batchs.push(displayObject); + } + + this.insertAfter(displayObject, previousSprite); + + // insert and SPLIT! + +} + +/** + * Inserts a displayObject into the linked list + * + * @method insertAfter + * @param item {DisplayObject} + * @param displayObject {DisplayObject} The object to insert + * @private + */ +PIXI.WebGLRenderGroup.prototype.insertAfter = function(item, displayObject) +{ + if(displayObject instanceof PIXI.Sprite) + { + var previousBatch = displayObject.batch; + + if(previousBatch) + { + // so this object is in a batch! + + // is it not? need to split the batch + if(previousBatch.tail == displayObject) + { + // is it tail? insert in to batchs + var index = this.batchs.indexOf( previousBatch ); + this.batchs.splice(index+1, 0, item); + } + else + { + // TODO MODIFY ADD / REMOVE CHILD TO ACCOUNT FOR FILTERS (also get prev and next) // + + // THERE IS A SPLIT IN THIS BATCH! // + var splitBatch = previousBatch.split(displayObject.__next); + + // COOL! + // add it back into the array + /* + * OOPS! + * seems the new sprite is in the middle of a batch + * lets split it.. + */ + var index = this.batchs.indexOf( previousBatch ); + this.batchs.splice(index+1, 0, item, splitBatch); + } + } + else + { + this.batchs.push(item); + } + } + else + { + var index = this.batchs.indexOf( displayObject ); + this.batchs.splice(index+1, 0, item); + } +} + +/** + * Removes a displayObject from the linked list + * + * @method removeObject + * @param displayObject {DisplayObject} The object to remove + * @private + */ +PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) +{ + // loop through children.. + // display object // + + // add a child from the render group.. + // remove it and all its children! + //displayObject.cacheVisible = false;//displayObject.visible; + + /* + * removing is a lot quicker.. + * + */ + var batchToRemove; + + if(displayObject instanceof PIXI.Sprite) + { + // should always have a batch! + var batch = displayObject.batch; + if(!batch)return; // this means the display list has been altered befre rendering + + batch.remove(displayObject); + + if(batch.size==0) + { + batchToRemove = batch; + } + } + else + { + batchToRemove = displayObject; + } + + /* + * Looks like there is somthing that needs removing! + */ + if(batchToRemove) + { + var index = this.batchs.indexOf( batchToRemove ); + if(index == -1)return;// this means it was added then removed before rendered + + // ok so.. check to see if you adjacent batchs should be joined. + // TODO may optimise? + if(index == 0 || index == this.batchs.length-1) + { + // wha - eva! just get of the empty batch! + this.batchs.splice(index, 1); + if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); + + return; + } + + if(this.batchs[index-1] instanceof PIXI.WebGLBatch && this.batchs[index+1] instanceof PIXI.WebGLBatch) + { + if(this.batchs[index-1].texture == this.batchs[index+1].texture && this.batchs[index-1].blendMode == this.batchs[index+1].blendMode) + { + //console.log("MERGE") + this.batchs[index-1].merge(this.batchs[index+1]); + + if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); + PIXI.WebGLRenderer.returnBatch(this.batchs[index+1]); + this.batchs.splice(index, 2); + return; + } + } + + this.batchs.splice(index, 1); + if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); + } +} + + +/** + * Initializes a tiling sprite + * + * @method initTilingSprite + * @param sprite {TilingSprite} The tiling sprite to initialize + * @private + */ +PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) +{ + var gl = this.gl; + + // make the texture tilable.. + + sprite.verticies = new Float32Array([0, 0, + sprite.width, 0, + sprite.width, sprite.height, + 0, sprite.height]); + + sprite.uvs = new Float32Array([0, 0, + 1, 0, + 1, 1, + 0, 1]); + + sprite.colors = new Float32Array([1,1,1,1]); + + sprite.indices = new Uint16Array([0, 1, 3,2])//, 2]); + + sprite._vertexBuffer = gl.createBuffer(); + sprite._indexBuffer = gl.createBuffer(); + sprite._uvBuffer = gl.createBuffer(); + sprite._colorBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, sprite._vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, sprite.verticies, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, sprite.uvs, gl.DYNAMIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, sprite._colorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, sprite.colors, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sprite._indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sprite.indices, gl.STATIC_DRAW); + +// return ( (x > 0) && ((x & (x - 1)) == 0) ); + + if(sprite.texture.baseTexture._glTexture) + { + gl.bindTexture(gl.TEXTURE_2D, sprite.texture.baseTexture._glTexture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); + sprite.texture.baseTexture._powerOf2 = true; + } + else + { + sprite.texture.baseTexture._powerOf2 = true; + } +} + +/** + * Renders a Strip + * + * @method renderStrip + * @param strip {Strip} The strip to render + * @param projection {Object} + * @private + */ +PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) +{ + var gl = this.gl; + var shaderProgram = PIXI.stripShaderProgram; + + + gl.useProgram(shaderProgram); + + var m = PIXI.mat3.clone(strip.worldTransform); + + PIXI.mat3.transpose(m); + + // set the matrix transform for the + gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); + gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); + +/* + if(strip.blendMode == PIXI.blendModes.NORMAL) + { + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + } + else + { + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR); + } + */ + + + if(!strip.dirty) + { + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); + gl.bufferSubData(gl.ARRAY_BUFFER, 0, strip.verticies) + gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + + // update the uvs + gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); + gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); + gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); + + // dont need to upload! + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); + } + else + { + strip.dirty = false; + gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.STATIC_DRAW) + gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + + // update the uvs + gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW) + gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW) + gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); + + // dont need to upload! + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); + + } + + gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); + + gl.useProgram(PIXI.currentProgram); +} + +/** + * Renders a TilingSprite + * + * @method renderTilingSprite + * @param sprite {TilingSprite} The tiling sprite to render + * @param projectionMatrix {Object} + * @private + */ +PIXI.WebGLRenderGroup.prototype.renderTilingSprite = function(sprite, projectionMatrix) +{ + var gl = this.gl; + var shaderProgram = PIXI.shaderProgram; + + var tilePosition = sprite.tilePosition; + var tileScale = sprite.tileScale; + + var offsetX = tilePosition.x/sprite.texture.baseTexture.width; + var offsetY = tilePosition.y/sprite.texture.baseTexture.height; + + var scaleX = (sprite.width / sprite.texture.baseTexture.width) / tileScale.x; + var scaleY = (sprite.height / sprite.texture.baseTexture.height) / tileScale.y; + + sprite.uvs[0] = 0 - offsetX; + sprite.uvs[1] = 0 - offsetY; + + sprite.uvs[2] = (1 * scaleX) -offsetX; + sprite.uvs[3] = 0 - offsetY; + + sprite.uvs[4] = (1 *scaleX) - offsetX; + sprite.uvs[5] = (1 *scaleY) - offsetY; + + sprite.uvs[6] = 0 - offsetX; + sprite.uvs[7] = (1 *scaleY) - offsetY; + + gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); + gl.bufferSubData(gl.ARRAY_BUFFER, 0, sprite.uvs) + + this.renderStrip(sprite, projectionMatrix); +} + +/** + * Initializes a strip to be rendered + * + * @method initStrip + * @param strip {Strip} The strip to initialize + * @private + */ +PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) +{ + // build the strip! + var gl = this.gl; + var shaderProgram = this.shaderProgram; + + strip._vertexBuffer = gl.createBuffer(); + strip._indexBuffer = gl.createBuffer(); + strip._uvBuffer = gl.createBuffer(); + strip._colorBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.DYNAMIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW); + + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); +} + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * the CanvasRenderer draws the stage and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. + * Dont forget to add the view to your DOM or you will not see anything :) + * + * @class CanvasRenderer + * @constructor + * @param width=0 {Number} the width of the canvas view + * @param height=0 {Number} the height of the canvas view + * @param view {Canvas} the canvas to use as a view, optional + * @param transparent=false {Boolean} the transparency of the render view, default false + */ +PIXI.CanvasRenderer = function(width, height, view, transparent) +{ + this.transparent = transparent; + + /** + * The width of the canvas view + * + * @property width + * @type Number + * @default 800 + */ + this.width = width || 800; + + /** + * The height of the canvas view + * + * @property height + * @type Number + * @default 600 + */ + this.height = height || 600; + + /** + * The canvas element that the everything is drawn to + * + * @property view + * @type Canvas + */ + this.view = view || document.createElement( 'canvas' ); + + /** + * The canvas context that the everything is drawn to + * @property context + * @type Canvas 2d Context + */ + this.context = this.view.getContext("2d"); + + this.refresh = true; + // hack to enable some hardware acceleration! + //this.view.style["transform"] = "translatez(0)"; + + this.view.width = this.width; + this.view.height = this.height; + this.count = 0; +} + +// constructor +PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; + +/** + * Renders the stage to its canvas view + * + * @method render + * @param stage {Stage} the Stage element to be rendered + */ +PIXI.CanvasRenderer.prototype.render = function(stage) +{ + + //stage.__childrenAdded = []; + //stage.__childrenRemoved = []; + + // update textures if need be + PIXI.texturesToUpdate = []; + PIXI.texturesToDestroy = []; + + PIXI.visibleCount++; + stage.updateTransform(); + + // update the background color + if(this.view.style.backgroundColor!=stage.backgroundColorString && !this.transparent)this.view.style.backgroundColor = stage.backgroundColorString; + + this.context.setTransform(1,0,0,1,0,0); + this.context.clearRect(0, 0, this.width, this.height) + this.renderDisplayObject(stage); + //as + + // run interaction! + if(stage.interactive) + { + //need to add some events! + if(!stage._interactiveEventsAdded) + { + stage._interactiveEventsAdded = true; + stage.interactionManager.setTarget(this); + } + } + + // remove frame updates.. + if(PIXI.Texture.frameUpdates.length > 0) + { + PIXI.Texture.frameUpdates = []; + } + + +} + +/** + * resizes the canvas view to the specified width and height + * + * @method resize + * @param width {Number} the new width of the canvas view + * @param height {Number} the new height of the canvas view + */ +PIXI.CanvasRenderer.prototype.resize = function(width, height) +{ + this.width = width; + this.height = height; + + this.view.width = width; + this.view.height = height; +} + +/** + * Renders a display object + * + * @method renderDisplayObject + * @param displayObject {DisplayObject} The displayObject to render + * @private + */ +PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) +{ + // no loger recurrsive! + var transform; + var context = this.context; + + context.globalCompositeOperation = 'source-over'; + + // one the display object hits this. we can break the loop + var testObject = displayObject.last._iNext; + displayObject = displayObject.first; + + do + { + transform = displayObject.worldTransform; + + if(!displayObject.visible) + { + displayObject = displayObject.last._iNext; + continue; + } + + if(!displayObject.renderable) + { + displayObject = displayObject._iNext; + continue; + } + + if(displayObject instanceof PIXI.Sprite) + { + + var frame = displayObject.texture.frame; + + if(frame && frame.width && frame.height) + { + context.globalAlpha = displayObject.worldAlpha; + + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); + + context.drawImage(displayObject.texture.baseTexture.source, + frame.x, + frame.y, + frame.width, + frame.height, + (displayObject.anchor.x) * -frame.width, + (displayObject.anchor.y) * -frame.height, + frame.width, + frame.height); + } + } + else if(displayObject instanceof PIXI.Strip) + { + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) + this.renderStrip(displayObject); + } + else if(displayObject instanceof PIXI.TilingSprite) + { + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) + this.renderTilingSprite(displayObject); + } + else if(displayObject instanceof PIXI.CustomRenderable) + { + displayObject.renderCanvas(this); + } + else if(displayObject instanceof PIXI.Graphics) + { + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) + PIXI.CanvasGraphics.renderGraphics(displayObject, context); + } + else if(displayObject instanceof PIXI.FilterBlock) + { + if(PIXI.FilterBlock.data instanceof PIXI.Graphics) + { + if(displayObject.open) + { + context.save(); + + var cacheAlpha = displayObject.mask.alpha; + var maskTransform = displayObject.mask.worldTransform; + + context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) + + displayObject.mask.worldAlpha = 0.5; + + context.worldAlpha = 0; + + PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); + context.clip(); + + displayObject.mask.worldAlpha = cacheAlpha; + } + else + { + context.restore(); + } + } + else + { + // only masks supported right now! + } + } + // count++ + displayObject = displayObject._iNext; + + + } + while(displayObject != testObject) + + +} + +/** + * Renders a flat strip + * + * @method renderStripFlat + * @param strip {Strip} The Strip to render + * @private + */ +PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip) +{ + var context = this.context; + var verticies = strip.verticies; + var uvs = strip.uvs; + + var length = verticies.length/2; + this.count++; + + context.beginPath(); + for (var i=1; i < length-2; i++) + { + + // draw some triangles! + var index = i*2; + + var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; + var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + + }; + + context.fillStyle = "#FF0000"; + context.fill(); + context.closePath(); +} + +/** + * Renders a tiling sprite + * + * @method renderTilingSprite + * @param sprite {TilingSprite} The tilingsprite to render + * @private + */ +PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) +{ + var context = this.context; + + context.globalAlpha = sprite.worldAlpha; + + if(!sprite.__tilePattern) sprite.__tilePattern = context.createPattern(sprite.texture.baseTexture.source, "repeat"); + + context.beginPath(); + + var tilePosition = sprite.tilePosition; + var tileScale = sprite.tileScale; + + // offset + context.scale(tileScale.x,tileScale.y); + context.translate(tilePosition.x, tilePosition.y); + + context.fillStyle = sprite.__tilePattern; + context.fillRect(-tilePosition.x,-tilePosition.y,sprite.width / tileScale.x, sprite.height / tileScale.y); + + context.scale(1/tileScale.x, 1/tileScale.y); + context.translate(-tilePosition.x, -tilePosition.y); + + context.closePath(); +} + +/** + * Renders a strip + * + * @method renderStrip + * @param strip {Strip} The Strip to render + * @private + */ +PIXI.CanvasRenderer.prototype.renderStrip = function(strip) +{ + var context = this.context; + + // draw triangles!! + var verticies = strip.verticies; + var uvs = strip.uvs; + + var length = verticies.length/2; + this.count++; + for (var i=1; i < length-2; i++) + { + + // draw some triangles! + var index = i*2; + + var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; + var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; + + var u0 = uvs[index] * strip.texture.width, u1 = uvs[index+2] * strip.texture.width, u2 = uvs[index+4]* strip.texture.width; + var v0 = uvs[index+1]* strip.texture.height, v1 = uvs[index+3] * strip.texture.height, v2 = uvs[index+5]* strip.texture.height; + + + 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 delta_a = x0*v1 + v0*x2 + x1*v2 - v1*x2 - v0*x1 - x0*v2; + var delta_b = u0*x1 + x0*u2 + u1*x2 - x1*u2 - x0*u1 - u0*x2; + var delta_c = u0*v1*x2 + v0*x1*u2 + x0*u1*v2 - x0*v1*u2 - v0*u1*x2 - u0*x1*v2; + var delta_d = y0*v1 + v0*y2 + y1*v2 - v1*y2 - v0*y1 - y0*v2; + var delta_e = u0*y1 + y0*u2 + u1*y2 - y1*u2 - y0*u1 - u0*y2; + var delta_f = u0*v1*y2 + v0*y1*u2 + y0*u1*v2 - y0*v1*u2 - v0*u1*y2 - u0*y1*v2; + + + + + context.transform(delta_a/delta, delta_d/delta, + delta_b/delta, delta_e/delta, + delta_c/delta, delta_f/delta); + + context.drawImage(strip.texture.baseTexture.source, 0, 0); + context.restore(); + }; + +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * A set of functions used by the canvas renderer to draw the primitive graphics data + * + * @class CanvasGraphics + */ +PIXI.CanvasGraphics = function() +{ + +} + + +/* + * Renders the graphics object + * + * @static + * @private + * @method renderGraphics + * @param graphics {Graphics} + * @param context {Context2D} + */ +PIXI.CanvasGraphics.renderGraphics = function(graphics, context) +{ + var worldAlpha = graphics.worldAlpha; + + for (var i=0; i < graphics.graphicsData.length; i++) + { + var data = graphics.graphicsData[i]; + var points = data.points; + + context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); + + context.lineWidth = data.lineWidth; + + if(data.type == PIXI.Graphics.POLY) + { + context.beginPath(); + + context.moveTo(points[0], points[1]); + + for (var j=1; j < points.length/2; j++) + { + context.lineTo(points[j * 2], points[j * 2 + 1]); + } + + // if the first and last point are the same close the path - much neater :) + if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) + { + context.closePath(); + } + + if(data.fill) + { + context.globalAlpha = data.fillAlpha * worldAlpha; + context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); + context.fill(); + } + if(data.lineWidth) + { + context.globalAlpha = data.lineAlpha * worldAlpha; + context.stroke(); + } + } + else if(data.type == PIXI.Graphics.RECT) + { + + if(data.fillColor || data.fillColor === 0) + { + context.globalAlpha = data.fillAlpha * worldAlpha; + context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); + context.fillRect(points[0], points[1], points[2], points[3]); + + } + if(data.lineWidth) + { + context.globalAlpha = data.lineAlpha * worldAlpha; + context.strokeRect(points[0], points[1], points[2], points[3]); + } + + } + else if(data.type == PIXI.Graphics.CIRC) + { + // TODO - need to be Undefined! + context.beginPath(); + context.arc(points[0], points[1], points[2],0,2*Math.PI); + context.closePath(); + + if(data.fill) + { + context.globalAlpha = data.fillAlpha * worldAlpha; + context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); + context.fill(); + } + if(data.lineWidth) + { + context.globalAlpha = data.lineAlpha * worldAlpha; + context.stroke(); + } + } + else if(data.type == PIXI.Graphics.ELIP) + { + + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas + + var elipseData = data.points; + + var w = elipseData[2] * 2; + var h = elipseData[3] * 2; + + var x = elipseData[0] - w/2; + var y = elipseData[1] - h/2; + + context.beginPath(); + + var kappa = .5522848, + ox = (w / 2) * kappa, // control point offset horizontal + oy = (h / 2) * kappa, // control point offset vertical + xe = x + w, // x-end + ye = y + h, // y-end + xm = x + w / 2, // x-middle + ym = y + h / 2; // y-middle + + context.moveTo(x, ym); + context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); + context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); + context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); + context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); + + context.closePath(); + + if(data.fill) + { + context.globalAlpha = data.fillAlpha * worldAlpha; + context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); + context.fill(); + } + if(data.lineWidth) + { + context.globalAlpha = data.lineAlpha * worldAlpha; + context.stroke(); + } + } + + }; +} + +/* + * Renders a graphics mask + * + * @static + * @private + * @method renderGraphicsMask + * @param graphics {Graphics} + * @param context {Context2D} + */ +PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) +{ + var worldAlpha = graphics.worldAlpha; + + var len = graphics.graphicsData.length; + if(len > 1) + { + len = 1; + console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") + } + + for (var i=0; i < 1; i++) + { + var data = graphics.graphicsData[i]; + var points = data.points; + + if(data.type == PIXI.Graphics.POLY) + { + context.beginPath(); + context.moveTo(points[0], points[1]); + + for (var j=1; j < points.length/2; j++) + { + context.lineTo(points[j * 2], points[j * 2 + 1]); + } + + // if the first and last point are the same close the path - much neater :) + if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) + { + context.closePath(); + } + + } + else if(data.type == PIXI.Graphics.RECT) + { + context.beginPath(); + context.rect(points[0], points[1], points[2], points[3]); + context.closePath(); + } + else if(data.type == PIXI.Graphics.CIRC) + { + // TODO - need to be Undefined! + context.beginPath(); + context.arc(points[0], points[1], points[2],0,2*Math.PI); + context.closePath(); + } + else if(data.type == PIXI.Graphics.ELIP) + { + + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas + var elipseData = data.points; + + var w = elipseData[2] * 2; + var h = elipseData[3] * 2; + + var x = elipseData[0] - w/2; + var y = elipseData[1] - h/2; + + context.beginPath(); + + var kappa = .5522848, + ox = (w / 2) * kappa, // control point offset horizontal + oy = (h / 2) * kappa, // control point offset vertical + xe = x + w, // x-end + ye = y + h, // y-end + xm = x + w / 2, // x-middle + ym = y + h / 2; // y-middle + + context.moveTo(x, ym); + context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); + context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); + context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); + context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); + context.closePath(); + } + + + }; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. + * It is important to know that with the webGL renderer only simple polys can be filled at this stage + * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png + * + * @class Graphics + * @extends DisplayObjectContainer + * @constructor + */ +PIXI.Graphics = function() +{ + PIXI.DisplayObjectContainer.call( this ); + + this.renderable = true; + + /** + * The alpha of the fill of this graphics object + * + * @property fillAlpha + * @type Number + */ + this.fillAlpha = 1; + + /** + * The width of any lines drawn + * + * @property lineWidth + * @type Number + */ + this.lineWidth = 0; + + /** + * The color of any lines drawn + * + * @property lineColor + * @type String + */ + this.lineColor = "black"; + + /** + * Graphics data + * + * @property graphicsData + * @type Array + * @private + */ + this.graphicsData = []; + + /** + * Current path + * + * @property currentPath + * @type Object + * @private + */ + this.currentPath = {points:[]}; +} + +// constructor +PIXI.Graphics.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); +PIXI.Graphics.prototype.constructor = PIXI.Graphics; + +/** + * Specifies a line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method. + * + * @method lineStyle + * @param lineWidth {Number} width of the line to draw, will update the object's stored style + * @param color {Number} color of the line to draw, will update the object's stored style + * @param alpha {Number} alpha of the line to draw, will update the object's stored style + */ +PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) +{ + if(this.currentPath.points.length == 0)this.graphicsData.pop(); + + this.lineWidth = lineWidth || 0; + this.lineColor = color || 0; + this.lineAlpha = (alpha == undefined) ? 1 : alpha; + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; + + this.graphicsData.push(this.currentPath); +} + +/** + * Moves the current drawing position to (x, y). + * + * @method moveTo + * @param x {Number} the X coord to move to + * @param y {Number} the Y coord to move to + */ +PIXI.Graphics.prototype.moveTo = function(x, y) +{ + if(this.currentPath.points.length == 0)this.graphicsData.pop(); + + this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; + + this.currentPath.points.push(x, y); + + this.graphicsData.push(this.currentPath); +} + +/** + * Draws a line using the current line style from the current drawing position to (x, y); + * the current drawing position is then set to (x, y). + * + * @method lineTo + * @param x {Number} the X coord to draw to + * @param y {Number} the Y coord to draw to + */ +PIXI.Graphics.prototype.lineTo = function(x, y) +{ + this.currentPath.points.push(x, y); + this.dirty = true; +} + +/** + * Specifies a simple one-color fill that subsequent calls to other Graphics methods + * (such as lineTo() or drawCircle()) use when drawing. + * + * @method beginFill + * @param color {uint} the color of the fill + * @param alpha {Number} the alpha + */ +PIXI.Graphics.prototype.beginFill = function(color, alpha) +{ + this.filling = true; + this.fillColor = color || 0; + this.fillAlpha = (alpha == undefined) ? 1 : alpha; +} + +/** + * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. + * + * @method endFill + */ +PIXI.Graphics.prototype.endFill = function() +{ + this.filling = false; + this.fillColor = null; + this.fillAlpha = 1; +} + +/** + * @method drawRect + * + * @param x {Number} The X coord of the top-left of the rectangle + * @param y {Number} The Y coord of the top-left of the rectangle + * @param width {Number} The width of the rectangle + * @param height {Number} The height of the rectangle + */ +PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) +{ + if(this.currentPath.points.length == 0)this.graphicsData.pop(); + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + points:[x, y, width, height], type:PIXI.Graphics.RECT}; + + this.graphicsData.push(this.currentPath); + this.dirty = true; +} + +/** + * Draws a circle. + * + * @method drawCircle + * @param x {Number} The X coord of the center of the circle + * @param y {Number} The Y coord of the center of the circle + * @param radius {Number} The radius of the circle + */ +PIXI.Graphics.prototype.drawCircle = function( x, y, radius) +{ + if(this.currentPath.points.length == 0)this.graphicsData.pop(); + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; + + this.graphicsData.push(this.currentPath); + this.dirty = true; +} + +/** + * Draws an elipse. + * + * @method drawElipse + * @param x {Number} + * @param y {Number} + * @param width {Number} + * @param height {Number} + */ +PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) +{ + if(this.currentPath.points.length == 0)this.graphicsData.pop(); + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + points:[x, y, width, height], type:PIXI.Graphics.ELIP}; + + this.graphicsData.push(this.currentPath); + this.dirty = true; +} + +/** + * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. + * + * @method clear + */ +PIXI.Graphics.prototype.clear = function() +{ + this.lineWidth = 0; + this.filling = false; + + this.dirty = true; + this.clearDirty = true; + this.graphicsData = []; +} + +// SOME TYPES: +PIXI.Graphics.POLY = 0; +PIXI.Graphics.RECT = 1; +PIXI.Graphics.CIRC = 2; +PIXI.Graphics.ELIP = 3; + +/** + * @author Mat Groves http://matgroves.com/ + */ + +PIXI.Strip = function(texture, width, height) +{ + PIXI.DisplayObjectContainer.call( this ); + this.texture = texture; + this.blendMode = PIXI.blendModes.NORMAL; + + try + { + this.uvs = new Float32Array([0, 1, + 1, 1, + 1, 0, 0,1]); + + this.verticies = new Float32Array([0, 0, + 0,0, + 0,0, 0, + 0, 0]); + + this.colors = new Float32Array([1, 1, 1, 1]); + + this.indices = new Uint16Array([0, 1, 2, 3]); + } + catch(error) + { + this.uvs = [0, 1, + 1, 1, + 1, 0, 0,1]; + + this.verticies = [0, 0, + 0,0, + 0,0, 0, + 0, 0]; + + this.colors = [1, 1, 1, 1]; + + this.indices = [0, 1, 2, 3]; + } + + + /* + this.uvs = new Float32Array() + this.verticies = new Float32Array() + this.colors = new Float32Array() + this.indices = new Uint16Array() +*/ + this.width = width; + this.height = height; + + // load the texture! + if(texture.baseTexture.hasLoaded) + { + this.width = this.texture.frame.width; + this.height = this.texture.frame.height; + this.updateFrame = true; + } + else + { + this.onTextureUpdateBind = this.onTextureUpdate.bind(this); + this.texture.addEventListener( 'update', this.onTextureUpdateBind ); + } + + this.renderable = true; +} + +// constructor +PIXI.Strip.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); +PIXI.Strip.prototype.constructor = PIXI.Strip; + +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; +} + +PIXI.Strip.prototype.onTextureUpdate = function(event) +{ + this.updateFrame = true; +} +// some helper functions.. + + +/** + * @author Mat Groves http://matgroves.com/ + */ + + +PIXI.Rope = function(texture, points) +{ + PIXI.Strip.call( this, texture ); + this.points = points; + + try + { + this.verticies = new Float32Array( points.length * 4); + this.uvs = new Float32Array( points.length * 4); + this.colors = new Float32Array( points.length * 2); + this.indices = new Uint16Array( points.length * 2); + } + catch(error) + { + this.verticies = verticies + + this.uvs = uvs + this.colors = colors + this.indices = indices + } + + this.refresh(); +} + + +// constructor +PIXI.Rope.prototype = Object.create( PIXI.Strip.prototype ); +PIXI.Rope.prototype.constructor = PIXI.Rope; + +PIXI.Rope.prototype.refresh = function() +{ + var points = this.points; + if(points.length < 1)return; + + var uvs = this.uvs + var indices = this.indices; + var colors = this.colors; + + var lastPoint = points[0]; + var nextPoint; + var perp = {x:0, y:0}; + var point = points[0]; + + this.count-=0.2; + + + uvs[0] = 0 + uvs[1] = 1 + uvs[2] = 0 + uvs[3] = 1 + + colors[0] = 1; + colors[1] = 1; + + indices[0] = 0; + indices[1] = 1; + + var total = points.length; + + for (var i = 1; i < total; i++) + { + + var point = points[i]; + var index = i * 4; + // time to do some smart drawing! + var 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; + } +} + +PIXI.Rope.prototype.updateTransform = function() +{ + + var points = this.points; + if(points.length < 1)return; + + var verticies = this.verticies + + var lastPoint = points[0]; + var nextPoint; + var perp = {x:0, y:0}; + var point = points[0]; + + this.count-=0.2; + + verticies[0] = point.x + perp.x + verticies[1] = point.y + perp.y //+ 200 + verticies[2] = point.x - perp.x + verticies[3] = point.y - perp.y//+200 + // time to do some smart drawing! + + var total = points.length; + + for (var i = 1; i < total; i++) + { + + var point = points[i]; + var 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; + + var ratio = (1 - (i / (total-1))) * 10; + if(ratio > 1)ratio = 1; + + var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); + var 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; + + verticies[index] = point.x + perp.x + verticies[index+1] = point.y + perp.y + verticies[index+2] = point.x - perp.x + verticies[index+3] = point.y - perp.y + + lastPoint = point; + } + + PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); +} + +PIXI.Rope.prototype.setTexture = function(texture) +{ + // stop current texture + this.texture = texture; + this.updateFrame = true; +} + + + + + +/** + * @author Mat Groves http://matgroves.com/ + */ + +/** + * A tiling sprite is a fast way of rendering a tiling image + * + * @class TilingSprite + * @extends DisplayObjectContainer + * @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.DisplayObjectContainer.call( this ); + + /** + * The texture that the sprite is using + * + * @property texture + * @type Texture + */ + this.texture = texture; + + /** + * The width of the tiling sprite + * + * @property width + * @type Number + */ + this.width = width; + + /** + * The height of the tiling sprite + * + * @property height + * @type Number + */ + this.height = height; + + /** + * The scaling of the image that is being tiled + * + * @property tileScale + * @type Point + */ + this.tileScale = 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); + + this.renderable = true; + + this.blendMode = PIXI.blendModes.NORMAL +} + +// constructor +PIXI.TilingSprite.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); +PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite; + +/** + * Sets the texture of the tiling sprite + * + * @method setTexture + * @param texture {Texture} The PIXI texture that is displayed by the sprite + */ +PIXI.TilingSprite.prototype.setTexture = function(texture) +{ + //TODO SET THE TEXTURES + //TODO VISIBILITY + + // stop current texture + this.texture = texture; + this.updateFrame = true; +} + +/** + * When the texture is updated, this event will fire to update the frame + * + * @method onTextureUpdate + * @param event + * @private + */ +PIXI.TilingSprite.prototype.onTextureUpdate = function(event) +{ + this.updateFrame = true; +} + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi + * + * Awesome JS run time provided by EsotericSoftware + * https://github.com/EsotericSoftware/spine-runtimes + * + */ + +/** + * 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)) { + continue; + } + var spriteName = attachment.rendererObject.name; + var sprite = this.createSprite(slot, attachment.rendererObject); + slot.currentSprite = sprite; + slot.currentSpriteName = spriteName; + slotContainer.addChild(sprite); + } +}; + +PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); +PIXI.Spine.prototype.constructor = PIXI.Spine; + +/* + * Updates the object transform for rendering + * + * @method updateTransform + * @private + */ +PIXI.Spine.prototype.updateTransform = function () { + this.lastTime = this.lastTime || Date.now(); + var timeDelta = (Date.now() - this.lastTime) * 0.001; + this.lastTime = Date.now(); + this.state.update(timeDelta); + 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 instanceof spine.RegionAttachment)) { + slotContainer.visible = false; + continue; + } + + 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.rendererObject); + slotContainer.addChild(sprite); + } + slot.currentSprite = slot.sprites[spriteName]; + slot.currentSpriteName = spriteName; + } + } + slotContainer.visible = true; + + 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 * Math.PI / 180); + } + + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); +}; + + +PIXI.Spine.prototype.createSprite = function (slot, descriptor) { + var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; + var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); + sprite.scale = descriptor.scale; + sprite.rotation = descriptor.rotation; + sprite.anchor.x = sprite.anchor.y = 0.5; + + slot.sprites = slot.sprites || {}; + slot.sprites[descriptor.name] = sprite; + return sprite; +}; + +/* + * Awesome JS run time provided by EsotericSoftware + * + * https://github.com/EsotericSoftware/spine-runtimes + * + */ + +var spine = {}; + +spine.BoneData = function (name, parent) { + this.name = name; + this.parent = parent; +}; +spine.BoneData.prototype = { + length: 0, + x: 0, y: 0, + rotation: 0, + scaleX: 1, scaleY: 1 +}; + +spine.SlotData = function (name, boneData) { + this.name = name; + this.boneData = boneData; +}; +spine.SlotData.prototype = { + r: 1, g: 1, b: 1, a: 1, + attachmentName: null +}; + +spine.Bone = function (boneData, parent) { + this.data = boneData; + this.parent = parent; + this.setToSetupPose(); +}; +spine.Bone.yDown = false; +spine.Bone.prototype = { + x: 0, y: 0, + rotation: 0, + scaleX: 1, scaleY: 1, + m00: 0, m01: 0, worldX: 0, // a b x + m10: 0, m11: 0, worldY: 0, // c d y + worldRotation: 0, + worldScaleX: 1, worldScaleY: 1, + updateWorldTransform: function (flipX, flipY) { + var parent = this.parent; + if (parent != null) { + this.worldX = this.x * parent.m00 + this.y * parent.m01 + parent.worldX; + this.worldY = this.x * parent.m10 + this.y * parent.m11 + parent.worldY; + this.worldScaleX = parent.worldScaleX * this.scaleX; + this.worldScaleY = parent.worldScaleY * this.scaleY; + this.worldRotation = parent.worldRotation + this.rotation; + } else { + this.worldX = this.x; + this.worldY = this.y; + this.worldScaleX = this.scaleX; + this.worldScaleY = this.scaleY; + this.worldRotation = this.rotation; + } + var radians = this.worldRotation * Math.PI / 180; + var cos = Math.cos(radians); + var sin = Math.sin(radians); + this.m00 = cos * this.worldScaleX; + this.m10 = sin * this.worldScaleX; + this.m01 = -sin * this.worldScaleY; + this.m11 = cos * this.worldScaleY; + if (flipX) { + this.m00 = -this.m00; + this.m01 = -this.m01; + } + if (flipY) { + this.m10 = -this.m10; + this.m11 = -this.m11; + } + if (spine.Bone.yDown) { + this.m10 = -this.m10; + this.m11 = -this.m11; + } + }, + setToSetupPose: function () { + var data = this.data; + this.x = data.x; + this.y = data.y; + this.rotation = data.rotation; + this.scaleX = data.scaleX; + this.scaleY = data.scaleY; + } +}; + +spine.Slot = function (slotData, skeleton, bone) { + this.data = slotData; + this.skeleton = skeleton; + this.bone = bone; + this.setToSetupPose(); +}; +spine.Slot.prototype = { + r: 1, g: 1, b: 1, a: 1, + _attachmentTime: 0, + attachment: null, + setAttachment: function (attachment) { + this.attachment = attachment; + this._attachmentTime = this.skeleton.time; + }, + setAttachmentTime: function (time) { + this._attachmentTime = this.skeleton.time - time; + }, + getAttachmentTime: function () { + return this.skeleton.time - this._attachmentTime; + }, + setToSetupPose: function () { + var data = this.data; + this.r = data.r; + this.g = data.g; + this.b = data.b; + this.a = data.a; + + var slotDatas = this.skeleton.data.slots; + for (var i = 0, n = slotDatas.length; i < n; i++) { + if (slotDatas[i] == data) { + this.setAttachment(!data.attachmentName ? null : this.skeleton.getAttachmentBySlotIndex(i, data.attachmentName)); + break; + } + } + } +}; + +spine.Skin = function (name) { + this.name = name; + this.attachments = {}; +}; +spine.Skin.prototype = { + addAttachment: function (slotIndex, name, attachment) { + this.attachments[slotIndex + ":" + name] = attachment; + }, + getAttachment: function (slotIndex, name) { + return this.attachments[slotIndex + ":" + name]; + }, + _attachAll: function (skeleton, oldSkin) { + for (var key in oldSkin.attachments) { + var colon = key.indexOf(":"); + var slotIndex = parseInt(key.substring(0, colon)); + var name = key.substring(colon + 1); + var slot = skeleton.slots[slotIndex]; + if (slot.attachment && slot.attachment.name == name) { + var attachment = this.getAttachment(slotIndex, name); + if (attachment) slot.setAttachment(attachment); + } + } + } +}; + +spine.Animation = function (name, timelines, duration) { + this.name = name; + this.timelines = timelines; + this.duration = duration; +}; +spine.Animation.prototype = { + apply: function (skeleton, time, loop) { + if (loop && this.duration != 0) time %= this.duration; + var timelines = this.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, time, 1); + }, + mix: function (skeleton, time, loop, alpha) { + if (loop && this.duration != 0) time %= this.duration; + var timelines = this.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, time, alpha); + } +}; + +spine.binarySearch = function (values, target, step) { + var low = 0; + var high = Math.floor(values.length / step) - 2; + if (high == 0) return step; + var current = high >>> 1; + while (true) { + if (values[(current + 1) * step] <= target) + low = current + 1; + else + high = current; + if (low == high) return (low + 1) * step; + current = (low + high) >>> 1; + } +}; +spine.linearSearch = function (values, target, step) { + for (var i = 0, last = values.length - step; i <= last; i += step) + if (values[i] > target) return i; + return -1; +}; + +spine.Curves = function (frameCount) { + this.curves = []; // dfx, dfy, ddfx, ddfy, dddfx, dddfy, ... + this.curves.length = (frameCount - 1) * 6; +}; +spine.Curves.prototype = { + setLinear: function (frameIndex) { + this.curves[frameIndex * 6] = 0/*LINEAR*/; + }, + setStepped: function (frameIndex) { + this.curves[frameIndex * 6] = -1/*STEPPED*/; + }, + /** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next. + * cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of + * the difference between the keyframe's values. */ + setCurve: function (frameIndex, cx1, cy1, cx2, cy2) { + var subdiv_step = 1 / 10/*BEZIER_SEGMENTS*/; + var subdiv_step2 = subdiv_step * subdiv_step; + var subdiv_step3 = subdiv_step2 * subdiv_step; + var pre1 = 3 * subdiv_step; + var pre2 = 3 * subdiv_step2; + var pre4 = 6 * subdiv_step2; + var pre5 = 6 * subdiv_step3; + var tmp1x = -cx1 * 2 + cx2; + var tmp1y = -cy1 * 2 + cy2; + var tmp2x = (cx1 - cx2) * 3 + 1; + var tmp2y = (cy1 - cy2) * 3 + 1; + var i = frameIndex * 6; + var curves = this.curves; + curves[i] = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; + curves[i + 1] = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; + curves[i + 2] = tmp1x * pre4 + tmp2x * pre5; + curves[i + 3] = tmp1y * pre4 + tmp2y * pre5; + curves[i + 4] = tmp2x * pre5; + curves[i + 5] = tmp2y * pre5; + }, + getCurvePercent: function (frameIndex, percent) { + percent = percent < 0 ? 0 : (percent > 1 ? 1 : percent); + var curveIndex = frameIndex * 6; + var curves = this.curves; + var dfx = curves[curveIndex]; + if (!dfx/*LINEAR*/) return percent; + if (dfx == -1/*STEPPED*/) return 0; + var dfy = curves[curveIndex + 1]; + var ddfx = curves[curveIndex + 2]; + var ddfy = curves[curveIndex + 3]; + var dddfx = curves[curveIndex + 4]; + var dddfy = curves[curveIndex + 5]; + var x = dfx, y = dfy; + var i = 10/*BEZIER_SEGMENTS*/ - 2; + while (true) { + if (x >= percent) { + var lastX = x - dfx; + var lastY = y - dfy; + return lastY + (y - lastY) * (percent - lastX) / (x - lastX); + } + if (i == 0) break; + i--; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + x += dfx; + y += dfy; + } + return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1. + } +}; + +spine.RotateTimeline = function (frameCount) { + this.curves = new spine.Curves(frameCount); + this.frames = []; // time, angle, ... + this.frames.length = frameCount * 2; +}; +spine.RotateTimeline.prototype = { + boneIndex: 0, + getFrameCount: function () { + return this.frames.length / 2; + }, + setFrame: function (frameIndex, time, angle) { + frameIndex *= 2; + this.frames[frameIndex] = time; + this.frames[frameIndex + 1] = angle; + }, + apply: function (skeleton, time, alpha) { + var frames = this.frames; + if (time < frames[0]) return; // Time is before first frame. + + var bone = skeleton.bones[this.boneIndex]; + + if (time >= frames[frames.length - 2]) { // Time is after last frame. + var amount = bone.data.rotation + frames[frames.length - 1] - bone.rotation; + while (amount > 180) + amount -= 360; + while (amount < -180) + amount += 360; + bone.rotation += amount * alpha; + return; + } + + // Interpolate between the last frame and the current frame. + var frameIndex = spine.binarySearch(frames, time, 2); + var lastFrameValue = frames[frameIndex - 1]; + var frameTime = frames[frameIndex]; + var percent = 1 - (time - frameTime) / (frames[frameIndex - 2/*LAST_FRAME_TIME*/] - frameTime); + percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent); + + var amount = frames[frameIndex + 1/*FRAME_VALUE*/] - lastFrameValue; + while (amount > 180) + amount -= 360; + while (amount < -180) + amount += 360; + amount = bone.data.rotation + (lastFrameValue + amount * percent) - bone.rotation; + while (amount > 180) + amount -= 360; + while (amount < -180) + amount += 360; + bone.rotation += amount * alpha; + } +}; + +spine.TranslateTimeline = function (frameCount) { + this.curves = new spine.Curves(frameCount); + this.frames = []; // time, x, y, ... + this.frames.length = frameCount * 3; +}; +spine.TranslateTimeline.prototype = { + boneIndex: 0, + getFrameCount: function () { + return this.frames.length / 3; + }, + setFrame: function (frameIndex, time, x, y) { + frameIndex *= 3; + this.frames[frameIndex] = time; + this.frames[frameIndex + 1] = x; + this.frames[frameIndex + 2] = y; + }, + apply: function (skeleton, time, alpha) { + var frames = this.frames; + if (time < frames[0]) return; // Time is before first frame. + + var bone = skeleton.bones[this.boneIndex]; + + if (time >= frames[frames.length - 3]) { // Time is after last frame. + bone.x += (bone.data.x + frames[frames.length - 2] - bone.x) * alpha; + bone.y += (bone.data.y + frames[frames.length - 1] - bone.y) * alpha; + return; + } + + // Interpolate between the last frame and the current frame. + var frameIndex = spine.binarySearch(frames, time, 3); + var lastFrameX = frames[frameIndex - 2]; + var lastFrameY = frames[frameIndex - 1]; + var frameTime = frames[frameIndex]; + var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); + percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); + + bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; + bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; + } +}; + +spine.ScaleTimeline = function (frameCount) { + this.curves = new spine.Curves(frameCount); + this.frames = []; // time, x, y, ... + this.frames.length = frameCount * 3; +}; +spine.ScaleTimeline.prototype = { + boneIndex: 0, + getFrameCount: function () { + return this.frames.length / 3; + }, + setFrame: function (frameIndex, time, x, y) { + frameIndex *= 3; + this.frames[frameIndex] = time; + this.frames[frameIndex + 1] = x; + this.frames[frameIndex + 2] = y; + }, + apply: function (skeleton, time, alpha) { + var frames = this.frames; + if (time < frames[0]) return; // Time is before first frame. + + var bone = skeleton.bones[this.boneIndex]; + + if (time >= frames[frames.length - 3]) { // Time is after last frame. + bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; + return; + } + + // Interpolate between the last frame and the current frame. + var frameIndex = spine.binarySearch(frames, time, 3); + var lastFrameX = frames[frameIndex - 2]; + var lastFrameY = frames[frameIndex - 1]; + var frameTime = frames[frameIndex]; + var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); + percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); + + bone.scaleX += (bone.data.scaleX - 1 + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - 1 + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.scaleY) * alpha; + } +}; + +spine.ColorTimeline = function (frameCount) { + this.curves = new spine.Curves(frameCount); + this.frames = []; // time, r, g, b, a, ... + this.frames.length = frameCount * 5; +}; +spine.ColorTimeline.prototype = { + slotIndex: 0, + getFrameCount: function () { + return this.frames.length / 2; + }, + setFrame: function (frameIndex, time, x, y) { + frameIndex *= 5; + this.frames[frameIndex] = time; + this.frames[frameIndex + 1] = r; + this.frames[frameIndex + 2] = g; + this.frames[frameIndex + 3] = b; + this.frames[frameIndex + 4] = a; + }, + apply: function (skeleton, time, alpha) { + var frames = this.frames; + if (time < frames[0]) return; // Time is before first frame. + + var slot = skeleton.slots[this.slotIndex]; + + if (time >= frames[frames.length - 5]) { // Time is after last frame. + var i = frames.length - 1; + slot.r = frames[i - 3]; + slot.g = frames[i - 2]; + slot.b = frames[i - 1]; + slot.a = frames[i]; + return; + } + + // Interpolate between the last frame and the current frame. + var frameIndex = spine.binarySearch(frames, time, 5); + var lastFrameR = frames[frameIndex - 4]; + var lastFrameG = frames[frameIndex - 3]; + var lastFrameB = frames[frameIndex - 2]; + var lastFrameA = frames[frameIndex - 1]; + var frameTime = frames[frameIndex]; + var percent = 1 - (time - frameTime) / (frames[frameIndex - 5/*LAST_FRAME_TIME*/] - frameTime); + percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent); + + var r = lastFrameR + (frames[frameIndex + 1/*FRAME_R*/] - lastFrameR) * percent; + var g = lastFrameG + (frames[frameIndex + 2/*FRAME_G*/] - lastFrameG) * percent; + var b = lastFrameB + (frames[frameIndex + 3/*FRAME_B*/] - lastFrameB) * percent; + var a = lastFrameA + (frames[frameIndex + 4/*FRAME_A*/] - lastFrameA) * percent; + if (alpha < 1) { + slot.r += (r - slot.r) * alpha; + slot.g += (g - slot.g) * alpha; + slot.b += (b - slot.b) * alpha; + slot.a += (a - slot.a) * alpha; + } else { + slot.r = r; + slot.g = g; + slot.b = b; + slot.a = a; + } + } +}; + +spine.AttachmentTimeline = function (frameCount) { + this.curves = new spine.Curves(frameCount); + this.frames = []; // time, ... + this.frames.length = frameCount; + this.attachmentNames = []; // time, ... + this.attachmentNames.length = frameCount; +}; +spine.AttachmentTimeline.prototype = { + slotIndex: 0, + getFrameCount: function () { + return this.frames.length; + }, + setFrame: function (frameIndex, time, attachmentName) { + this.frames[frameIndex] = time; + this.attachmentNames[frameIndex] = attachmentName; + }, + apply: function (skeleton, time, alpha) { + var frames = this.frames; + if (time < frames[0]) return; // Time is before first frame. + + var frameIndex; + if (time >= frames[frames.length - 1]) // Time is after last frame. + frameIndex = frames.length - 1; + else + frameIndex = spine.binarySearch(frames, time, 1) - 1; + + var attachmentName = this.attachmentNames[frameIndex]; + skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); + } +}; + +spine.SkeletonData = function () { + this.bones = []; + this.slots = []; + this.skins = []; + this.animations = []; +}; +spine.SkeletonData.prototype = { + defaultSkin: null, + /** @return May be null. */ + findBone: function (boneName) { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].name == boneName) return bones[i]; + return null; + }, + /** @return -1 if the bone was not found. */ + findBoneIndex: function (boneName) { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].name == boneName) return i; + return -1; + }, + /** @return May be null. */ + findSlot: function (slotName) { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + if (slots[i].name == slotName) return slot[i]; + } + return null; + }, + /** @return -1 if the bone was not found. */ + findSlotIndex: function (slotName) { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].name == slotName) return i; + return -1; + }, + /** @return May be null. */ + findSkin: function (skinName) { + var skins = this.skins; + for (var i = 0, n = skins.length; i < n; i++) + if (skins[i].name == skinName) return skins[i]; + return null; + }, + /** @return May be null. */ + findAnimation: function (animationName) { + var animations = this.animations; + for (var i = 0, n = animations.length; i < n; i++) + if (animations[i].name == animationName) return animations[i]; + return null; + } +}; + +spine.Skeleton = function (skeletonData) { + this.data = skeletonData; + + this.bones = []; + for (var i = 0, n = skeletonData.bones.length; i < n; i++) { + var boneData = skeletonData.bones[i]; + var parent = !boneData.parent ? null : this.bones[skeletonData.bones.indexOf(boneData.parent)]; + this.bones.push(new spine.Bone(boneData, parent)); + } + + this.slots = []; + this.drawOrder = []; + for (var i = 0, n = skeletonData.slots.length; i < n; i++) { + var slotData = skeletonData.slots[i]; + var bone = this.bones[skeletonData.bones.indexOf(slotData.boneData)]; + var slot = new spine.Slot(slotData, this, bone); + this.slots.push(slot); + this.drawOrder.push(slot); + } +}; +spine.Skeleton.prototype = { + x: 0, y: 0, + skin: null, + r: 1, g: 1, b: 1, a: 1, + time: 0, + flipX: false, flipY: false, + /** Updates the world transform for each bone. */ + updateWorldTransform: function () { + var flipX = this.flipX; + var flipY = this.flipY; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + bones[i].updateWorldTransform(flipX, flipY); + }, + /** Sets the bones and slots to their setup pose values. */ + setToSetupPose: function () { + this.setBonesToSetupPose(); + this.setSlotsToSetupPose(); + }, + setBonesToSetupPose: function () { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + bones[i].setToSetupPose(); + }, + setSlotsToSetupPose: function () { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + slots[i].setToSetupPose(i); + }, + /** @return May return null. */ + getRootBone: function () { + return this.bones.length == 0 ? null : this.bones[0]; + }, + /** @return May be null. */ + findBone: function (boneName) { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].data.name == boneName) return bones[i]; + return null; + }, + /** @return -1 if the bone was not found. */ + findBoneIndex: function (boneName) { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].data.name == boneName) return i; + return -1; + }, + /** @return May be null. */ + findSlot: function (slotName) { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].data.name == slotName) return slots[i]; + return null; + }, + /** @return -1 if the bone was not found. */ + findSlotIndex: function (slotName) { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].data.name == slotName) return i; + return -1; + }, + setSkinByName: function (skinName) { + var skin = this.data.findSkin(skinName); + if (!skin) throw "Skin not found: " + skinName; + this.setSkin(skin); + }, + /** Sets the skin used to look up attachments not found in the {@link SkeletonData#getDefaultSkin() default skin}. Attachments + * from the new skin are attached if the corresponding attachment from the old skin was attached. + * @param newSkin May be null. */ + setSkin: function (newSkin) { + if (this.skin && newSkin) newSkin._attachAll(this, this.skin); + this.skin = newSkin; + }, + /** @return May be null. */ + getAttachmentBySlotName: function (slotName, attachmentName) { + return this.getAttachmentBySlotIndex(this.data.findSlotIndex(slotName), attachmentName); + }, + /** @return May be null. */ + getAttachmentBySlotIndex: function (slotIndex, attachmentName) { + if (this.skin) { + var attachment = this.skin.getAttachment(slotIndex, attachmentName); + if (attachment) return attachment; + } + if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); + return null; + }, + /** @param attachmentName May be null. */ + setAttachment: function (slotName, attachmentName) { + var slots = this.slots; + for (var i = 0, n = slots.size; i < n; i++) { + var slot = slots[i]; + if (slot.data.name == slotName) { + var attachment = null; + if (attachmentName) { + attachment = this.getAttachment(i, attachmentName); + if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; + } + slot.setAttachment(attachment); + return; + } + } + throw "Slot not found: " + slotName; + }, + update: function (delta) { + time += delta; + } +}; + +spine.AttachmentType = { + region: 0 +}; + +spine.RegionAttachment = function () { + this.offset = []; + this.offset.length = 8; + this.uvs = []; + this.uvs.length = 8; +}; +spine.RegionAttachment.prototype = { + x: 0, y: 0, + rotation: 0, + scaleX: 1, scaleY: 1, + width: 0, height: 0, + rendererObject: null, + regionOffsetX: 0, regionOffsetY: 0, + regionWidth: 0, regionHeight: 0, + regionOriginalWidth: 0, regionOriginalHeight: 0, + setUVs: function (u, v, u2, v2, rotate) { + var uvs = this.uvs; + if (rotate) { + uvs[2/*X2*/] = u; + uvs[3/*Y2*/] = v2; + uvs[4/*X3*/] = u; + uvs[5/*Y3*/] = v; + uvs[6/*X4*/] = u2; + uvs[7/*Y4*/] = v; + uvs[0/*X1*/] = u2; + uvs[1/*Y1*/] = v2; + } else { + uvs[0/*X1*/] = u; + uvs[1/*Y1*/] = v2; + uvs[2/*X2*/] = u; + uvs[3/*Y2*/] = v; + uvs[4/*X3*/] = u2; + uvs[5/*Y3*/] = v; + uvs[6/*X4*/] = u2; + uvs[7/*Y4*/] = v2; + } + }, + updateOffset: function () { + var regionScaleX = this.width / this.regionOriginalWidth * this.scaleX; + var regionScaleY = this.height / this.regionOriginalHeight * this.scaleY; + var localX = -this.width / 2 * this.scaleX + this.regionOffsetX * regionScaleX; + var localY = -this.height / 2 * this.scaleY + this.regionOffsetY * regionScaleY; + var localX2 = localX + this.regionWidth * regionScaleX; + var localY2 = localY + this.regionHeight * regionScaleY; + var radians = this.rotation * Math.PI / 180; + var cos = Math.cos(radians); + var sin = Math.sin(radians); + var localXCos = localX * cos + this.x; + var localXSin = localX * sin; + var localYCos = localY * cos + this.y; + var localYSin = localY * sin; + var localX2Cos = localX2 * cos + this.x; + var localX2Sin = localX2 * sin; + var localY2Cos = localY2 * cos + this.y; + var localY2Sin = localY2 * sin; + var offset = this.offset; + offset[0/*X1*/] = localXCos - localYSin; + offset[1/*Y1*/] = localYCos + localXSin; + offset[2/*X2*/] = localXCos - localY2Sin; + offset[3/*Y2*/] = localY2Cos + localXSin; + offset[4/*X3*/] = localX2Cos - localY2Sin; + offset[5/*Y3*/] = localY2Cos + localX2Sin; + offset[6/*X4*/] = localX2Cos - localYSin; + offset[7/*Y4*/] = localYCos + localX2Sin; + }, + computeVertices: function (x, y, bone, vertices) { + x += bone.worldX; + y += bone.worldY; + var m00 = bone.m00; + var m01 = bone.m01; + var m10 = bone.m10; + var m11 = bone.m11; + var offset = this.offset; + vertices[0/*X1*/] = offset[0/*X1*/] * m00 + offset[1/*Y1*/] * m01 + x; + vertices[1/*Y1*/] = offset[0/*X1*/] * m10 + offset[1/*Y1*/] * m11 + y; + vertices[2/*X2*/] = offset[2/*X2*/] * m00 + offset[3/*Y2*/] * m01 + x; + vertices[3/*Y2*/] = offset[2/*X2*/] * m10 + offset[3/*Y2*/] * m11 + y; + vertices[4/*X3*/] = offset[4/*X3*/] * m00 + offset[5/*X3*/] * m01 + x; + vertices[5/*X3*/] = offset[4/*X3*/] * m10 + offset[5/*X3*/] * m11 + y; + vertices[6/*X4*/] = offset[6/*X4*/] * m00 + offset[7/*Y4*/] * m01 + x; + vertices[7/*Y4*/] = offset[6/*X4*/] * m10 + offset[7/*Y4*/] * m11 + y; + } +} + +spine.AnimationStateData = function (skeletonData) { + this.skeletonData = skeletonData; + this.animationToMixTime = {}; +}; +spine.AnimationStateData.prototype = { + defaultMix: 0, + setMixByName: function (fromName, toName, duration) { + var from = this.skeletonData.findAnimation(fromName); + if (!from) throw "Animation not found: " + fromName; + var to = this.skeletonData.findAnimation(toName); + if (!to) throw "Animation not found: " + toName; + this.setMix(from, to, duration); + }, + setMix: function (from, to, duration) { + this.animationToMixTime[from.name + ":" + to.name] = duration; + }, + getMix: function (from, to) { + var time = this.animationToMixTime[from.name + ":" + to.name]; + return time ? time : this.defaultMix; + } +}; + +spine.AnimationState = function (stateData) { + this.data = stateData; + this.queue = []; +}; +spine.AnimationState.prototype = { + current: null, + previous: null, + currentTime: 0, + previousTime: 0, + currentLoop: false, + previousLoop: false, + mixTime: 0, + mixDuration: 0, + update: function (delta) { + this.currentTime += delta; + this.previousTime += delta; + this.mixTime += delta; + + if (this.queue.length > 0) { + var entry = this.queue[0]; + if (this.currentTime >= entry.delay) { + this._setAnimation(entry.animation, entry.loop); + this.queue.shift(); + } + } + }, + apply: function (skeleton) { + if (!this.current) return; + if (this.previous) { + this.previous.apply(skeleton, this.previousTime, this.previousLoop); + var alpha = this.mixTime / this.mixDuration; + if (alpha >= 1) { + alpha = 1; + this.previous = null; + } + this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); + } else + this.current.apply(skeleton, this.currentTime, this.currentLoop); + }, + clearAnimation: function () { + this.previous = null; + this.current = null; + this.queue.length = 0; + }, + _setAnimation: function (animation, loop) { + this.previous = null; + if (animation && this.current) { + this.mixDuration = this.data.getMix(this.current, animation); + if (this.mixDuration > 0) { + this.mixTime = 0; + this.previous = this.current; + this.previousTime = this.currentTime; + this.previousLoop = this.currentLoop; + } + } + this.current = animation; + this.currentLoop = loop; + this.currentTime = 0; + }, + /** @see #setAnimation(Animation, Boolean) */ + setAnimationByName: function (animationName, loop) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) throw "Animation not found: " + animationName; + this.setAnimation(animation, loop); + }, + /** Set the current animation. Any queued animations are cleared and the current animation time is set to 0. + * @param animation May be null. */ + setAnimation: function (animation, loop) { + this.queue.length = 0; + this._setAnimation(animation, loop); + }, + /** @see #addAnimation(Animation, Boolean, Number) */ + addAnimationByName: function (animationName, loop, delay) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) throw "Animation not found: " + animationName; + this.addAnimation(animation, loop, delay); + }, + /** Adds an animation to be played delay seconds after the current or last queued animation. + * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */ + addAnimation: function (animation, loop, delay) { + var entry = {}; + entry.animation = animation; + entry.loop = loop; + + if (!delay || delay <= 0) { + var previousAnimation = this.queue.length == 0 ? this.current : this.queue[this.queue.length - 1].animation; + if (previousAnimation != null) + delay = previousAnimation.duration - this.data.getMix(previousAnimation, animation) + (delay || 0); + else + delay = 0; + } + entry.delay = delay; + + this.queue.push(entry); + }, + /** Returns true if no animation is set or if the current time is greater than the animation duration, regardless of looping. */ + isComplete: function () { + return !this.current || this.currentTime >= this.current.duration; + } +}; + +spine.SkeletonJson = function (attachmentLoader) { + this.attachmentLoader = attachmentLoader; +}; +spine.SkeletonJson.prototype = { + scale: 1, + readSkeletonData: function (root) { + var skeletonData = new spine.SkeletonData(); + + // Bones. + var bones = root["bones"]; + for (var i = 0, n = bones.length; i < n; i++) { + var boneMap = bones[i]; + var parent = null; + if (boneMap["parent"]) { + parent = skeletonData.findBone(boneMap["parent"]); + if (!parent) throw "Parent bone not found: " + boneMap["parent"]; + } + var boneData = new spine.BoneData(boneMap["name"], parent); + boneData.length = (boneMap["length"] || 0) * this.scale; + boneData.x = (boneMap["x"] || 0) * this.scale; + boneData.y = (boneMap["y"] || 0) * this.scale; + boneData.rotation = (boneMap["rotation"] || 0); + boneData.scaleX = boneMap["scaleX"] || 1; + boneData.scaleY = boneMap["scaleY"] || 1; + skeletonData.bones.push(boneData); + } + + // Slots. + var slots = root["slots"]; + for (var i = 0, n = slots.length; i < n; i++) { + var slotMap = slots[i]; + var boneData = skeletonData.findBone(slotMap["bone"]); + if (!boneData) throw "Slot bone not found: " + slotMap["bone"]; + var slotData = new spine.SlotData(slotMap["name"], boneData); + + var color = slotMap["color"]; + if (color) { + slotData.r = spine.SkeletonJson.toColor(color, 0); + slotData.g = spine.SkeletonJson.toColor(color, 1); + slotData.b = spine.SkeletonJson.toColor(color, 2); + slotData.a = spine.SkeletonJson.toColor(color, 3); + } + + slotData.attachmentName = slotMap["attachment"]; + + skeletonData.slots.push(slotData); + } + + // Skins. + var skins = root["skins"]; + for (var skinName in skins) { + if (!skins.hasOwnProperty(skinName)) continue; + var skinMap = skins[skinName]; + var skin = new spine.Skin(skinName); + for (var slotName in skinMap) { + if (!skinMap.hasOwnProperty(slotName)) continue; + var slotIndex = skeletonData.findSlotIndex(slotName); + var slotEntry = skinMap[slotName]; + for (var attachmentName in slotEntry) { + if (!slotEntry.hasOwnProperty(attachmentName)) continue; + var attachment = this.readAttachment(skin, attachmentName, slotEntry[attachmentName]); + if (attachment != null) skin.addAttachment(slotIndex, attachmentName, attachment); + } + } + skeletonData.skins.push(skin); + if (skin.name == "default") skeletonData.defaultSkin = skin; + } + + // Animations. + var animations = root["animations"]; + for (var animationName in animations) { + if (!animations.hasOwnProperty(animationName)) continue; + this.readAnimation(animationName, animations[animationName], skeletonData); + } + + return skeletonData; + }, + readAttachment: function (skin, name, map) { + name = map["name"] || name; + + var type = spine.AttachmentType[map["type"] || "region"]; + + if (type == spine.AttachmentType.region) { + var attachment = new spine.RegionAttachment(); + attachment.x = (map["x"] || 0) * this.scale; + attachment.y = (map["y"] || 0) * this.scale; + attachment.scaleX = map["scaleX"] || 1; + attachment.scaleY = map["scaleY"] || 1; + attachment.rotation = map["rotation"] || 0; + attachment.width = (map["width"] || 32) * this.scale; + attachment.height = (map["height"] || 32) * this.scale; + attachment.updateOffset(); + + attachment.rendererObject = {}; + attachment.rendererObject.name = name; + attachment.rendererObject.scale = {}; + attachment.rendererObject.scale.x = attachment.scaleX; + attachment.rendererObject.scale.y = attachment.scaleY; + attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; + return attachment; + } + + throw "Unknown attachment type: " + type; + }, + + readAnimation: function (name, map, skeletonData) { + var timelines = []; + var duration = 0; + + var bones = map["bones"]; + for (var boneName in bones) { + if (!bones.hasOwnProperty(boneName)) continue; + var boneIndex = skeletonData.findBoneIndex(boneName); + if (boneIndex == -1) throw "Bone not found: " + boneName; + var boneMap = bones[boneName]; + + for (var timelineName in boneMap) { + if (!boneMap.hasOwnProperty(timelineName)) continue; + var values = boneMap[timelineName]; + if (timelineName == "rotate") { + var timeline = new spine.RotateTimeline(values.length); + timeline.boneIndex = boneIndex; + + var frameIndex = 0; + for (var i = 0, n = values.length; i < n; i++) { + var valueMap = values[i]; + timeline.setFrame(frameIndex, valueMap["time"], valueMap["angle"]); + spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 2 - 2]); + + } else if (timelineName == "translate" || timelineName == "scale") { + var timeline; + var timelineScale = 1; + if (timelineName == "scale") + timeline = new spine.ScaleTimeline(values.length); + else { + timeline = new spine.TranslateTimeline(values.length); + timelineScale = this.scale; + } + timeline.boneIndex = boneIndex; + + var frameIndex = 0; + for (var i = 0, n = values.length; i < n; i++) { + var valueMap = values[i]; + var x = (valueMap["x"] || 0) * timelineScale; + var y = (valueMap["y"] || 0) * timelineScale; + timeline.setFrame(frameIndex, valueMap["time"], x, y); + spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); + + } else + throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; + } + } + var slots = map["slots"]; + for (var slotName in slots) { + if (!slots.hasOwnProperty(slotName)) continue; + var slotMap = slots[slotName]; + var slotIndex = skeletonData.findSlotIndex(slotName); + + for (var timelineName in slotMap) { + if (!slotMap.hasOwnProperty(timelineName)) continue; + var values = slotMap[timelineName]; + if (timelineName == "color") { + var timeline = new spine.ColorTimeline(values.length); + timeline.slotIndex = slotIndex; + + var frameIndex = 0; + for (var i = 0, n = values.length; i < n; i++) { + var valueMap = values[i]; + var color = valueMap["color"]; + var r = spine.SkeletonJson.toColor(color, 0); + var g = spine.SkeletonJson.toColor(color, 1); + var b = spine.SkeletonJson.toColor(color, 2); + var a = spine.SkeletonJson.toColor(color, 3); + timeline.setFrame(frameIndex, valueMap["time"], r, g, b, a); + spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 5 - 5]); + + } else if (timelineName == "attachment") { + var timeline = new spine.AttachmentTimeline(values.length); + timeline.slotIndex = slotIndex; + + var frameIndex = 0; + for (var i = 0, n = values.length; i < n; i++) { + var valueMap = values[i]; + timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + + } else + throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; + } + } + skeletonData.animations.push(new spine.Animation(name, timelines, duration)); + } +}; +spine.SkeletonJson.readCurve = function (timeline, frameIndex, valueMap) { + var curve = valueMap["curve"]; + if (!curve) return; + if (curve == "stepped") + timeline.curves.setStepped(frameIndex); + else if (curve instanceof Array) + timeline.curves.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); +}; +spine.SkeletonJson.toColor = function (hexString, colorIndex) { + if (hexString.length != 8) throw "Color hexidecimal length must be 8, recieved: " + hexString; + return parseInt(hexString.substring(colorIndex * 2, 2), 16) / 255; +}; + +spine.Atlas = function (atlasText, textureLoader) { + this.textureLoader = textureLoader; + this.pages = []; + this.regions = []; + + var reader = new spine.AtlasReader(atlasText); + var tuple = []; + tuple.length = 4; + var page = null; + while (true) { + var line = reader.readLine(); + if (line == null) break; + line = reader.trim(line); + if (line.length == 0) + page = null; + else if (!page) { + page = new spine.AtlasPage(); + page.name = line; + + page.format = spine.Atlas.Format[reader.readValue()]; + + reader.readTuple(tuple); + page.minFilter = spine.Atlas.TextureFilter[tuple[0]]; + page.magFilter = spine.Atlas.TextureFilter[tuple[1]]; + + var direction = reader.readValue(); + page.uWrap = spine.Atlas.TextureWrap.clampToEdge; + page.vWrap = spine.Atlas.TextureWrap.clampToEdge; + if (direction == "x") + page.uWrap = spine.Atlas.TextureWrap.repeat; + else if (direction == "y") + page.vWrap = spine.Atlas.TextureWrap.repeat; + else if (direction == "xy") + page.uWrap = page.vWrap = spine.Atlas.TextureWrap.repeat; + + textureLoader.load(page, line); + + this.pages.push(page); + + } else { + var region = new spine.AtlasRegion(); + region.name = line; + region.page = page; + + region.rotate = reader.readValue() == "true"; + + reader.readTuple(tuple); + var x = parseInt(tuple[0]); + var y = parseInt(tuple[1]); + + reader.readTuple(tuple); + var width = parseInt(tuple[0]); + var height = parseInt(tuple[1]); + + region.u = x / page.width; + region.v = y / page.height; + if (region.rotate) { + region.u2 = (x + height) / page.width; + region.v2 = (y + width) / page.height; + } else { + region.u2 = (x + width) / page.width; + region.v2 = (y + height) / page.height; + } + region.x = x; + region.y = y; + region.width = Math.abs(width); + region.height = Math.abs(height); + + if (reader.readTuple(tuple) == 4) { // split is optional + region.splits = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; + + if (reader.readTuple(tuple) == 4) { // pad is optional, but only present with splits + region.pads = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; + + reader.readTuple(tuple); + } + } + + region.originalWidth = parseInt(tuple[0]); + region.originalHeight = parseInt(tuple[1]); + + reader.readTuple(tuple); + region.offsetX = parseInt(tuple[0]); + region.offsetY = parseInt(tuple[1]); + + region.index = parseInt(reader.readValue()); + + this.regions.push(region); + } + } +}; +spine.Atlas.prototype = { + findRegion: function (name) { + var regions = this.regions; + for (var i = 0, n = regions.length; i < n; i++) + if (regions[i].name == name) return regions[i]; + return null; + }, + dispose: function () { + var pages = this.pages; + for (var i = 0, n = pages.length; i < n; i++) + this.textureLoader.unload(pages[i].rendererObject); + }, + updateUVs: function (page) { + var regions = this.regions; + for (var i = 0, n = regions.length; i < n; i++) { + var region = regions[i]; + if (region.page != page) continue; + region.u = region.x / page.width; + region.v = region.y / page.height; + if (region.rotate) { + region.u2 = (region.x + region.height) / page.width; + region.v2 = (region.y + region.width) / page.height; + } else { + region.u2 = (region.x + region.width) / page.width; + region.v2 = (region.y + region.height) / page.height; + } + } + } +}; + +spine.Atlas.Format = { + alpha: 0, + intensity: 1, + luminanceAlpha: 2, + rgb565: 3, + rgba4444: 4, + rgb888: 5, + rgba8888: 6 +}; + +spine.Atlas.TextureFilter = { + nearest: 0, + linear: 1, + mipMap: 2, + mipMapNearestNearest: 3, + mipMapLinearNearest: 4, + mipMapNearestLinear: 5, + mipMapLinearLinear: 6 +}; + +spine.Atlas.TextureWrap = { + mirroredRepeat: 0, + clampToEdge: 1, + repeat: 2 +}; + +spine.AtlasPage = function () {}; +spine.AtlasPage.prototype = { + name: null, + format: null, + minFilter: null, + magFilter: null, + uWrap: null, + vWrap: null, + rendererObject: null, + width: 0, + height: 0 +}; + +spine.AtlasRegion = function () {}; +spine.AtlasRegion.prototype = { + page: null, + name: null, + x: 0, y: 0, + width: 0, height: 0, + u: 0, v: 0, u2: 0, v2: 0, + offsetX: 0, offsetY: 0, + originalWidth: 0, originalHeight: 0, + index: 0, + rotate: false, + splits: null, + pads: null, +}; + +spine.AtlasReader = function (text) { + this.lines = text.split(/\r\n|\r|\n/); +}; +spine.AtlasReader.prototype = { + index: 0, + trim: function (value) { + return value.replace(/^\s+|\s+$/g, ""); + }, + readLine: function () { + if (this.index >= this.lines.length) return null; + return this.lines[this.index++]; + }, + readValue: function () { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) throw "Invalid line: " + line; + return this.trim(line.substring(colon + 1)); + }, + /** Returns the number of tuple values read (2 or 4). */ + readTuple: function (tuple) { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) throw "Invalid line: " + line; + var i = 0, lastMatch= colon + 1; + for (; i < 3; i++) { + var comma = line.indexOf(",", lastMatch); + if (comma == -1) { + if (i == 0) throw "Invalid line: " + line; + break; + } + tuple[i] = this.trim(line.substr(lastMatch, comma - lastMatch)); + lastMatch = comma + 1; + } + tuple[i] = this.trim(line.substring(lastMatch)); + return i + 1; + } +} + +spine.AtlasAttachmentLoader = function (atlas) { + this.atlas = atlas; +} +spine.AtlasAttachmentLoader.prototype = { + newAttachment: function (skin, type, name) { + switch (type) { + case spine.AttachmentType.region: + var region = this.atlas.findRegion(name); + if (!region) throw "Region not found in atlas: " + name + " (" + type + ")"; + var attachment = new spine.RegionAttachment(name); + attachment.rendererObject = region; + attachment.setUVs(region.u, region.v, region.u2, region.v2, region.rotate); + attachment.regionOffsetX = region.offsetX; + attachment.regionOffsetY = region.offsetY; + attachment.regionWidth = region.width; + attachment.regionHeight = region.height; + attachment.regionOriginalWidth = region.originalWidth; + attachment.regionOriginalHeight = region.originalHeight; + return attachment; + } + throw "Unknown attachment type: " + type; + } +} + +PIXI.AnimCache = {}; +spine.Bone.yDown = true; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * This object is one that will allow you to specify custom rendering functions based on render type + * + * @class CustomRenderable + * @extends DisplayObject + * @constructor + */ +PIXI.CustomRenderable = function() +{ + PIXI.DisplayObject.call( this ); + +} + +// constructor +PIXI.CustomRenderable.prototype = Object.create( PIXI.DisplayObject.prototype ); +PIXI.CustomRenderable.prototype.constructor = PIXI.CustomRenderable; + +/** + * If this object is being rendered by a CanvasRenderer it will call this callback + * + * @method renderCanvas + * @param renderer {CanvasRenderer} The renderer instance + */ +PIXI.CustomRenderable.prototype.renderCanvas = function(renderer) +{ + // override! +} + +/** + * If this object is being rendered by a WebGLRenderer it will call this callback to initialize + * + * @method initWebGL + * @param renderer {WebGLRenderer} The renderer instance + */ +PIXI.CustomRenderable.prototype.initWebGL = function(renderer) +{ + // override! +} + +/** + * If this object is being rendered by a WebGLRenderer it will call this callback + * + * @method renderWebGL + * @param renderer {WebGLRenderer} The renderer instance + */ +PIXI.CustomRenderable.prototype.renderWebGL = function(renderGroup, projectionMatrix) +{ + // not sure if both needed? but ya have for now! + // override! +} + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.BaseTextureCache = {}; +PIXI.texturesToUpdate = []; +PIXI.texturesToDestroy = []; + +/** + * A texture stores the information that represents an image. All textures have a base texture + * + * @class BaseTexture + * @uses EventTarget + * @constructor + * @param source {String} the source object (image or canvas) + */ +PIXI.BaseTexture = function(source) +{ + PIXI.EventTarget.call( this ); + + /** + * [read-only] The width of the base texture set when the image has loaded + * + * @property width + * @type Number + * @readOnly + */ + this.width = 100; + + /** + * [read-only] The height of the base texture set when the image has loaded + * + * @property height + * @type Number + * @readOnly + */ + this.height = 100; + + /** + * [read-only] Describes if the base texture has loaded or not + * + * @property hasLoaded + * @type Boolean + * @readOnly + */ + this.hasLoaded = false; + + /** + * The source that is loaded to create the texture + * + * @property source + * @type Image + */ + this.source = source; + + if(!source)return; + + if(this.source instanceof Image || this.source instanceof HTMLImageElement) + { + if(this.source.complete) + { + this.hasLoaded = true; + this.width = this.source.width; + this.height = this.source.height; + + PIXI.texturesToUpdate.push(this); + } + else + { + + var scope = this; + this.source.onload = function(){ + + scope.hasLoaded = true; + scope.width = scope.source.width; + scope.height = scope.source.height; + + // add it to somewhere... + PIXI.texturesToUpdate.push(scope); + scope.dispatchEvent( { type: 'loaded', content: scope } ); + } + // this.image.src = imageUrl; + } + } + else + { + this.hasLoaded = true; + this.width = this.source.width; + this.height = this.source.height; + + PIXI.texturesToUpdate.push(this); + } + + this._powerOf2 = false; +} + +PIXI.BaseTexture.prototype.constructor = PIXI.BaseTexture; + +/** + * Destroys this base texture + * + * @method destroy + */ +PIXI.BaseTexture.prototype.destroy = function() +{ + if(this.source instanceof Image) + { + this.source.src = null; + } + this.source = null; + PIXI.texturesToDestroy.push(this); +} + +/** + * Helper function that returns a base texture based on an image url + * If the image is not in the base texture cache it will be created and loaded + * + * @static + * @method fromImage + * @param imageUrl {String} The image url of the texture + * @return BaseTexture + */ +PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) +{ + var baseTexture = PIXI.BaseTextureCache[imageUrl]; + if(!baseTexture) + { + // new Image() breaks tex loading in some versions of Chrome. + // See https://code.google.com/p/chromium/issues/detail?id=238071 + var image = new Image();//document.createElement('img'); + if (crossorigin) + { + image.crossOrigin = ''; + } + image.src = imageUrl; + baseTexture = new PIXI.BaseTexture(image); + PIXI.BaseTextureCache[imageUrl] = baseTexture; + } + + return baseTexture; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.TextureCache = {}; +PIXI.FrameCache = {}; + +/** + * A texture stores the information that represents an image or part of an image. It cannot be added + * to the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used + * + * @class Texture + * @uses EventTarget + * @constructor + * @param baseTexture {BaseTexture} The base texture source to create the texture from + * @param frame {Rectangle} The rectangle frame of the texture to show + */ +PIXI.Texture = function(baseTexture, frame) +{ + PIXI.EventTarget.call( this ); + + if(!frame) + { + this.noFrame = true; + frame = new PIXI.Rectangle(0,0,1,1); + } + + if(baseTexture instanceof PIXI.Texture) + baseTexture = baseTexture.baseTexture; + + /** + * The base texture of this texture + * + * @property baseTexture + * @type BaseTexture + */ + this.baseTexture = baseTexture; + + /** + * The frame specifies the region of the base texture that this texture uses + * + * @property frame + * @type Rectangle + */ + this.frame = frame; + + /** + * The trim point + * + * @property trim + * @type Point + */ + this.trim = new PIXI.Point(); + + this.scope = this; + + if(baseTexture.hasLoaded) + { + if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); + //console.log(frame) + + this.setFrame(frame); + } + else + { + var scope = this; + baseTexture.addEventListener( 'loaded', function(){ scope.onBaseTextureLoaded()} ); + } +} + +PIXI.Texture.prototype.constructor = PIXI.Texture; + +/** + * Called when the base texture is loaded + * + * @method onBaseTextureLoaded + * @param event + * @private + */ +PIXI.Texture.prototype.onBaseTextureLoaded = function(event) +{ + var baseTexture = this.baseTexture; + baseTexture.removeEventListener( 'loaded', this.onLoaded ); + + if(this.noFrame)this.frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); + this.noFrame = false; + this.width = this.frame.width; + this.height = this.frame.height; + + this.scope.dispatchEvent( { type: 'update', content: this } ); +} + +/** + * Destroys this texture + * + * @method destroy + * @param destroyBase {Boolean} Whether to destroy the base texture as well + */ +PIXI.Texture.prototype.destroy = function(destroyBase) +{ + if(destroyBase)this.baseTexture.destroy(); +} + +/** + * Specifies the rectangle region of the baseTexture + * + * @method setFrame + * @param frame {Rectangle} The frame of the texture to set it to + */ +PIXI.Texture.prototype.setFrame = function(frame) +{ + this.frame = frame; + this.width = frame.width; + this.height = frame.height; + + if(frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height) + { + throw new Error("Texture Error: frame does not fit inside the base Texture dimensions " + this); + } + + this.updateFrame = true; + + PIXI.Texture.frameUpdates.push(this); + //this.dispatchEvent( { type: 'update', content: this } ); +} + +/** + * Helper function that returns a texture based on an image url + * If the image is not in the texture cache it will be created and loaded + * + * @static + * @method fromImage + * @param imageUrl {String} The image url of the texture + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin + * @return Texture + */ +PIXI.Texture.fromImage = function(imageUrl, crossorigin) +{ + var texture = PIXI.TextureCache[imageUrl]; + + if(!texture) + { + texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); + PIXI.TextureCache[imageUrl] = texture; + } + + return texture; +} + +/** + * Helper function that returns a texture based on a frame id + * If the frame id is not in the texture cache an error will be thrown + * + * @static + * @method fromFrame + * @param frameId {String} The frame id of the texture + * @return Texture + */ +PIXI.Texture.fromFrame = function(frameId) +{ + var texture = PIXI.TextureCache[frameId]; + if(!texture)throw new Error("The frameId '"+ frameId +"' does not exist in the texture cache " + this); + return texture; +} + +/** + * Helper function that returns a texture based on a canvas element + * If the canvas is not in the texture cache it will be created and loaded + * + * @static + * @method fromCanvas + * @param canvas {Canvas} The canvas element source of the texture + * @return Texture + */ +PIXI.Texture.fromCanvas = function(canvas) +{ + var baseTexture = new PIXI.BaseTexture(canvas); + return new PIXI.Texture(baseTexture); +} + + +/** + * Adds a texture to the textureCache. + * + * @static + * @method addTextureToCache + * @param texture {Texture} + * @param id {String} the id that the texture will be stored against. + */ +PIXI.Texture.addTextureToCache = function(texture, id) +{ + PIXI.TextureCache[id] = texture; +} + +/** + * Remove a texture from the textureCache. + * + * @static + * @method removeTextureFromCache + * @param id {String} the id of the texture to be removed + * @return {Texture} the texture that was removed + */ +PIXI.Texture.removeTextureFromCache = function(id) +{ + var texture = PIXI.TextureCache[id] + PIXI.TextureCache[id] = null; + return texture; +} + +// this is more for webGL.. it contains updated frames.. +PIXI.Texture.frameUpdates = []; + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + A RenderTexture is a special texture that allows any pixi displayObject to be rendered to it. + + __Hint__: All DisplayObjects (exmpl. Sprites) that renders on RenderTexture should be preloaded. + Otherwise black rectangles will be drawn instead. + + RenderTexture takes snapshot of DisplayObject passed to render method. If DisplayObject is passed to render method, position and rotation of it will be ignored. For example: + + var renderTexture = new PIXI.RenderTexture(800, 600); + var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); + sprite.position.x = 800/2; + sprite.position.y = 600/2; + sprite.anchor.x = 0.5; + sprite.anchor.y = 0.5; + renderTexture.render(sprite); + + Sprite in this case will be rendered to 0,0 position. To render this sprite at center DisplayObjectContainer should be used: + + var doc = new PIXI.DisplayObjectContainer(); + doc.addChild(sprite); + renderTexture.render(doc); // Renders to center of renderTexture + + @class RenderTexture + @extends Texture + @constructor + @param width {Number} The width of the render texture + @param height {Number} The height of the render texture + */ +PIXI.RenderTexture = function(width, height) +{ + PIXI.EventTarget.call( this ); + + this.width = width || 100; + this.height = height || 100; + + this.indetityMatrix = PIXI.mat3.create(); + + this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); + + if(PIXI.gl) + { + this.initWebGL(); + } + else + { + this.initCanvas(); + } +} + +PIXI.RenderTexture.prototype = Object.create( PIXI.Texture.prototype ); +PIXI.RenderTexture.prototype.constructor = PIXI.RenderTexture; + +/** + * Initializes the webgl data for this texture + * + * @method initWebGL + * @private + */ +PIXI.RenderTexture.prototype.initWebGL = function() +{ + var gl = PIXI.gl; + this.glFramebuffer = gl.createFramebuffer(); + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); + + this.glFramebuffer.width = this.width; + this.glFramebuffer.height = this.height; + + this.baseTexture = new PIXI.BaseTexture(); + + this.baseTexture.width = this.width; + this.baseTexture.height = this.height; + + this.baseTexture._glTexture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); + + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + + this.baseTexture.isRender = true; + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.baseTexture._glTexture, 0); + + // create a projection matrix.. + this.projection = new PIXI.Point(this.width/2 , this.height/2); + + // set the correct render function.. + this.render = this.renderWebGL; + + +} + + +PIXI.RenderTexture.prototype.resize = function(width, height) +{ + + this.width = width; + this.height = height; + + if(PIXI.gl) + { + this.projection.x = this.width/2 + this.projection.y = this.height/2; + + var gl = PIXI.gl; + gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + } + else + { + + this.frame.width = this.width + this.frame.height = this.height; + this.renderer.resize(this.width, this.height); + } +} + +/** + * Initializes the canvas data for this texture + * + * @method initCanvas + * @private + */ +PIXI.RenderTexture.prototype.initCanvas = function() +{ + this.renderer = new PIXI.CanvasRenderer(this.width, this.height, null, 0); + + this.baseTexture = new PIXI.BaseTexture(this.renderer.view); + this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); + + this.render = this.renderCanvas; +} + +/** + * This function will draw the display object to the texture. + * + * @method renderWebGL + * @param displayObject {DisplayObject} The display object to render this texture on + * @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn + * @private + */ +PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, clear) +{ + var gl = PIXI.gl; + + // enable the alpha color mask.. + gl.colorMask(true, true, true, true); + + gl.viewport(0, 0, this.width, this.height); + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); + + if(clear) + { + gl.clearColor(0,0,0, 0); + gl.clear(gl.COLOR_BUFFER_BIT); + } + + // THIS WILL MESS WITH HIT TESTING! + var children = displayObject.children; + + //TODO -? create a new one??? dont think so! + var originalWorldTransform = displayObject.worldTransform; + displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; + // modify to flip... + displayObject.worldTransform[4] = -1; + displayObject.worldTransform[5] = this.projection.y * 2; + + + if(position) + { + displayObject.worldTransform[2] = position.x; + displayObject.worldTransform[5] -= position.y; + } + + PIXI.visibleCount++; + displayObject.vcount = PIXI.visibleCount; + + for(var i=0,j=children.length; i} assetURLs an array of image/sprite sheet urls that you would like loaded + * supported. Supported image formats include "jpeg", "jpg", "png", "gif". Supported + * sprite sheet data formats only include "JSON" at this time. Supported bitmap font + * data formats include "xml" and "fnt". + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin + */ +PIXI.AssetLoader = function(assetURLs, crossorigin) +{ + PIXI.EventTarget.call(this); + + /** + * The array of asset URLs that are going to be loaded + * + * @property assetURLs + * @type Array + */ + this.assetURLs = assetURLs; + + /** + * Whether the requests should be treated as cross origin + * + * @property crossorigin + * @type Boolean + */ + this.crossorigin = crossorigin; + + /** + * Maps file extension to loader types + * + * @property loadersByType + * @type Object + */ + this.loadersByType = { + "jpg": PIXI.ImageLoader, + "jpeg": PIXI.ImageLoader, + "png": PIXI.ImageLoader, + "gif": PIXI.ImageLoader, + "json": PIXI.JsonLoader, + "anim": PIXI.SpineLoader, + "xml": PIXI.BitmapFontLoader, + "fnt": PIXI.BitmapFontLoader + }; + + +}; + +/** + * Fired when an item has loaded + * @event onProgress + */ + +/** + * Fired when all the assets have loaded + * @event onComplete + */ + +// constructor +PIXI.AssetLoader.prototype.constructor = PIXI.AssetLoader; + +/** + * Starts loading the assets sequentially + * + * @method load + */ +PIXI.AssetLoader.prototype.load = function() +{ + var scope = this; + + this.loadCount = this.assetURLs.length; + + for (var i=0; i < this.assetURLs.length; i++) + { + var fileName = this.assetURLs[i]; + var fileType = fileName.split(".").pop().toLowerCase(); + + var loaderClass = this.loadersByType[fileType]; + if(!loaderClass) + throw new Error(fileType + " is an unsupported file type"); + + var loader = new loaderClass(fileName, this.crossorigin); + + loader.addEventListener("loaded", function() + { + scope.onAssetLoaded(); + }); + loader.load(); + } +}; + +/** + * Invoked after each file is loaded + * + * @method onAssetLoaded + * @private + */ +PIXI.AssetLoader.prototype.onAssetLoaded = function() +{ + this.loadCount--; + this.dispatchEvent({type: "onProgress", content: this}); + if(this.onProgress) this.onProgress(); + + if(this.loadCount == 0) + { + this.dispatchEvent({type: "onComplete", content: this}); + if(this.onComplete) this.onComplete(); + } +}; + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * The json file loader is used to load in JSON data and parsing it + * When loaded this class will dispatch a "loaded" event + * If load failed this class will dispatch a "error" event + * + * @class JsonLoader + * @uses EventTarget + * @constructor + * @param url {String} The url of the JSON file + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin + */ +PIXI.JsonLoader = function (url, crossorigin) { + PIXI.EventTarget.call(this); + + /** + * The url of the bitmap font data + * + * @property url + * @type String + */ + this.url = url; + + /** + * Whether the requests should be treated as cross origin + * + * @property crossorigin + * @type Boolean + */ + this.crossorigin = crossorigin; + + /** + * [read-only] The base url of the bitmap font data + * + * @property baseUrl + * @type String + * @readOnly + */ + this.baseUrl = url.replace(/[^\/]*$/, ""); + + /** + * [read-only] Whether the data has loaded yet + * + * @property loaded + * @type Boolean + * @readOnly + */ + this.loaded = false; + +}; + +// constructor +PIXI.JsonLoader.prototype.constructor = PIXI.JsonLoader; + +/** + * Loads the JSON data + * + * @method load + */ +PIXI.JsonLoader.prototype.load = function () { + this.ajaxRequest = new AjaxRequest(); + var scope = this; + this.ajaxRequest.onreadystatechange = function () { + scope.onJSONLoaded(); + }; + + this.ajaxRequest.open("GET", this.url, true); + if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/json"); + this.ajaxRequest.send(null); +}; + +/** + * Invoke when JSON file is loaded + * + * @method onJSONLoaded + * @private + */ +PIXI.JsonLoader.prototype.onJSONLoaded = function () { + if (this.ajaxRequest.readyState == 4) { + if (this.ajaxRequest.status == 200 || window.location.href.indexOf("http") == -1) { + this.json = JSON.parse(this.ajaxRequest.responseText); + + if(this.json.frames) + { + // sprite sheet + var scope = this; + var textureUrl = this.baseUrl + this.json.meta.image; + var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); + var frameData = this.json.frames; + + this.texture = image.texture.baseTexture; + image.addEventListener("loaded", function (event) { + scope.onLoaded(); + }); + + for (var i in frameData) { + var rect = frameData[i].frame; + if (rect) { + PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { + x: rect.x, + y: rect.y, + width: rect.w, + height: rect.h + }); + if (frameData[i].trimmed) { + //var realSize = frameData[i].spriteSourceSize; + PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; + PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) + // calculate the offset! + } + } + } + + image.load(); + + } + else if(this.json.bones) + { + // spine animation + var spineJsonParser = new spine.SkeletonJson(); + var skeletonData = spineJsonParser.readSkeletonData(this.json); + PIXI.AnimCache[this.url] = skeletonData; + this.onLoaded(); + } + else + { + this.onLoaded(); + } + } + else + { + this.onError(); + } + } +}; + +/** + * Invoke when json file loaded + * + * @method onLoaded + * @private + */ +PIXI.JsonLoader.prototype.onLoaded = function () { + this.loaded = true; + this.dispatchEvent({ + type: "loaded", + content: this + }); +}; + +/** + * Invoke when error occured + * + * @method onError + * @private + */ +PIXI.JsonLoader.prototype.onError = function () { + this.dispatchEvent({ + type: "error", + content: this + }); +}; +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * The sprite sheet loader is used to load in JSON sprite sheet data + * To generate the data you can use http://www.codeandweb.com/texturepacker and publish the "JSON" format + * There is a free version so thats nice, although the paid version is great value for money. + * It is highly recommended to use Sprite sheets (also know as texture atlas") as it means sprite"s can be batched and drawn together for highly increased rendering speed. + * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() + * This loader will also load the image file that the Spritesheet points to as well as the data. + * When loaded this class will dispatch a "loaded" event + * + * @class SpriteSheetLoader + * @uses EventTarget + * @constructor + * @param url {String} The url of the sprite sheet JSON file + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin + */ + +PIXI.SpriteSheetLoader = function (url, crossorigin) { + /* + * i use texture packer to load the assets.. + * http://www.codeandweb.com/texturepacker + * make sure to set the format as "JSON" + */ + PIXI.EventTarget.call(this); + + /** + * The url of the bitmap font data + * + * @property url + * @type String + */ + this.url = url; + + /** + * Whether the requests should be treated as cross origin + * + * @property crossorigin + * @type Boolean + */ + this.crossorigin = crossorigin; + + /** + * [read-only] The base url of the bitmap font data + * + * @property baseUrl + * @type String + * @readOnly + */ + this.baseUrl = url.replace(/[^\/]*$/, ""); + + /** + * The texture being loaded + * + * @property texture + * @type Texture + */ + this.texture = null; + + /** + * The frames of the sprite sheet + * + * @property frames + * @type Object + */ + this.frames = {}; +}; + +// constructor +PIXI.SpriteSheetLoader.prototype.constructor = PIXI.SpriteSheetLoader; + +/** + * This will begin loading the JSON file + * + * @method load + */ +PIXI.SpriteSheetLoader.prototype.load = function () { + var scope = this; + var jsonLoader = new PIXI.JsonLoader(this.url, this.crossorigin); + jsonLoader.addEventListener("loaded", function (event) { + scope.json = event.content.json; + scope.onJSONLoaded(); + }); + jsonLoader.load(); +}; + +/** + * Invoke when JSON file is loaded + * + * @method onJSONLoaded + * @private + */ +PIXI.SpriteSheetLoader.prototype.onJSONLoaded = function () { + var scope = this; + var textureUrl = this.baseUrl + this.json.meta.image; + var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); + var frameData = this.json.frames; + + this.texture = image.texture.baseTexture; + image.addEventListener("loaded", function (event) { + scope.onLoaded(); + }); + + for (var i in frameData) { + var rect = frameData[i].frame; + if (rect) { + PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { + x: rect.x, + y: rect.y, + width: rect.w, + height: rect.h + }); + if (frameData[i].trimmed) { + //var realSize = frameData[i].spriteSourceSize; + PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; + PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) + // calculate the offset! + } + } + } + + image.load(); +}; +/** + * Invoke when all files are loaded (json and texture) + * + * @method onLoaded + * @private + */ +PIXI.SpriteSheetLoader.prototype.onLoaded = function () { + this.dispatchEvent({ + type: "loaded", + content: this + }); +}; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * The image loader class is responsible for loading images file formats ("jpeg", "jpg", "png" and "gif") + * Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() + * When loaded this class will dispatch a 'loaded' event + * + * @class ImageLoader + * @uses EventTarget + * @constructor + * @param url {String} The url of the image + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin + */ +PIXI.ImageLoader = function(url, crossorigin) +{ + PIXI.EventTarget.call(this); + + /** + * The texture being loaded + * + * @property texture + * @type Texture + */ + this.texture = PIXI.Texture.fromImage(url, crossorigin); + + /** + * if the image is loaded with loadFramedSpriteSheet + * frames will contain the sprite sheet frames + * + */ + this.frames = []; +}; + +// constructor +PIXI.ImageLoader.prototype.constructor = PIXI.ImageLoader; + +/** + * Loads image or takes it from cache + * + * @method load + */ +PIXI.ImageLoader.prototype.load = function() +{ + if(!this.texture.baseTexture.hasLoaded) + { + var scope = this; + this.texture.baseTexture.addEventListener("loaded", function() + { + scope.onLoaded(); + }); + } + else + { + this.onLoaded(); + } +}; + +/** + * Invoked when image file is loaded or it is already cached and ready to use + * + * @method onLoaded + * @private + */ +PIXI.ImageLoader.prototype.onLoaded = function() +{ + this.dispatchEvent({type: "loaded", content: this}); +}; + +/** + * Loads image and split it to uniform sized frames + * + * + * @method loadFramedSpriteSheet + * @param frameWidth {Number} with of each frame + * @param frameHeight {Number} height of each frame + * @param textureName {String} if given, the frames will be cached in - format + */ +PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) +{ + this.frames = []; + var cols = Math.floor(this.texture.width / frameWidth); + var rows = Math.floor(this.texture.height / frameHeight); + + var i=0; + for (var y=0; y x1 && x < x1 + this.width) + if(x >= x1 && x <= x1 + this.width) { var y1 = this.y; - - if(y > y1 && y < y1 + this.height) + + if(y >= y1 && y <= y1 + this.height) { return true; } @@ -165,7 +165,7 @@ PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; * @class Polygon * @constructor * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, - * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arugments passed can be + * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are * Numbers. @@ -232,9 +232,9 @@ PIXI.Polygon.prototype.contains = function(x, y) return inside; } +// constructor PIXI.Polygon.prototype.constructor = PIXI.Polygon; - /** * @author Chad Engler */ @@ -256,7 +256,7 @@ PIXI.Circle = function(x, y, radius) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number @@ -306,6 +306,7 @@ PIXI.Circle.prototype.contains = function(x, y) return (dx + dy <= r2); } +// constructor PIXI.Circle.prototype.constructor = PIXI.Circle; @@ -320,8 +321,8 @@ PIXI.Circle.prototype.constructor = PIXI.Circle; * @constructor * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse - * @param width {Number} The overall height of this ellipse - * @param height {Number} The overall width of this ellipse + * @param width {Number} The overall width of this ellipse + * @param height {Number} The overall height of this ellipse */ PIXI.Ellipse = function(x, y, width, height) { @@ -331,21 +332,21 @@ PIXI.Ellipse = function(x, y, width, height) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number * @default 0 */ this.y = y || 0; - + /** * @property width * @type Number * @default 0 */ this.width = width || 0; - + /** * @property height * @type Number @@ -394,11 +395,11 @@ PIXI.Ellipse.getBounds = function() return new PIXI.Rectangle(this.x, this.y, this.width, this.height); } +// constructor PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; - /* * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV * you both rock! @@ -426,7 +427,7 @@ PIXI.mat3.create = function() matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -442,7 +443,7 @@ PIXI.mat3.identity = function(matrix) matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -469,35 +470,35 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat3.multiply = function (mat, mat2, dest) +PIXI.mat3.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[0], a01 = mat[1], a02 = mat[2], a10 = mat[3], a11 = mat[4], a12 = mat[5], a20 = mat[6], a21 = mat[7], a22 = mat[8], - + b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; - + dest[0] = b00 * a00 + b01 * a10 + b02 * a20; dest[1] = b00 * a01 + b01 * a11 + b02 * a21; dest[2] = b00 * a02 + b01 * a12 + b02 * a22; - + dest[3] = b10 * a00 + b11 * a10 + b12 * a20; dest[4] = b10 * a01 + b11 * a11 + b12 * a21; dest[5] = b10 * a02 + b11 * a12 + b12 * a22; - + dest[6] = b20 * a00 + b21 * a10 + b22 * a20; dest[7] = b20 * a01 + b21 * a11 + b22 * a21; dest[8] = b20 * a02 + b21 * a12 + b22 * a22; - + return dest; } @@ -514,11 +515,11 @@ PIXI.mat3.clone = function(mat) matrix[6] = mat[6]; matrix[7] = mat[7]; matrix[8] = mat[8]; - + return matrix; } -PIXI.mat3.transpose = function (mat, dest) +PIXI.mat3.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values if (!dest || mat === dest) { @@ -546,30 +547,30 @@ PIXI.mat3.transpose = function (mat, dest) return dest; } -PIXI.mat3.toMat4 = function (mat, dest) +PIXI.mat3.toMat4 = function (mat, dest) { if (!dest) { dest = PIXI.mat4.create(); } - + dest[15] = 1; dest[14] = 0; dest[13] = 0; dest[12] = 0; - + dest[11] = 0; dest[10] = mat[8]; dest[9] = mat[7]; dest[8] = mat[6]; - + dest[7] = 0; dest[6] = mat[5]; dest[5] = mat[4]; dest[4] = mat[3]; - + dest[3] = 0; dest[2] = mat[2]; dest[1] = mat[1]; dest[0] = mat[0]; - + return dest; } @@ -597,19 +598,19 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat4.transpose = function (mat, dest) +PIXI.mat4.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) + if (!dest || mat === dest) { var a01 = mat[1], a02 = mat[2], a03 = mat[3], a12 = mat[6], a13 = mat[7], a23 = mat[11]; - + mat[1] = mat[4]; mat[2] = mat[8]; mat[3] = mat[12]; @@ -624,7 +625,7 @@ PIXI.mat4.transpose = function (mat, dest) mat[14] = a23; return mat; } - + dest[0] = mat[0]; dest[1] = mat[4]; dest[2] = mat[8]; @@ -644,18 +645,18 @@ PIXI.mat4.transpose = function (mat, dest) return dest; } -PIXI.mat4.multiply = function (mat, mat2, dest) +PIXI.mat4.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - + // Cache only the current line of the second matrix - var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; + var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; @@ -705,7 +706,6 @@ PIXI.DisplayObject = function() { this.last = this; this.first = this; - /** * The coordinate of the object relative to the local coordinates of the parent. * @@ -779,15 +779,6 @@ PIXI.DisplayObject = function() */ this.renderable = false; - /** - * [read-only] The visibility of the object based on world (parent) factors. - * - * @property worldVisible - * @type Boolean - * @readOnly - */ - this.worldVisible = false; - /** * [read-only] The display object container that contains this display object. * @@ -806,15 +797,6 @@ PIXI.DisplayObject = function() */ this.stage = null; - /** - * [read-only] The index of this object in the parent's `children` array - * - * @property childIndex - * @type Number - * @readOnly - */ - this.childIndex = 0; - /** * [read-only] The multiplied alpha of the displayobject * @@ -953,17 +935,6 @@ PIXI.DisplayObject = function() // constructor PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObject.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - } -});*/ - /** * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default * Instead of using this function you can now simply set the interactive property to true or false @@ -1011,16 +982,57 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { }, set: function(value) { - this._mask = value; - + if(value) { + if(this._mask) + { + value.start = this._mask.start; + value.end = this._mask.end; + } + else + { + this.addFilter(value); + value.renderable = false; + } + } + else + { + this.removeFilter(this._mask); + this._mask.renderable = true; + } + + this._mask = value; + } +}); + +/** + * Sets the filters for the displayObject. Currently there's a few limitations. + * 1: At the moment only one filter can be applied at a time.. + * 2: They cannot be nested. + * 3: There's no padding yet. + * 4: this is a webGL only feature. + * @property filters + * @type Array + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { + get: function() { + return this._filters; + }, + set: function(value) { + + //if(value == ) + if(value) + { + if(this._filters)this.removeFilter(this._filters); this.addFilter(value) } else { - this.removeFilter(); + if(this._filters)this.removeFilter(this._filters); } + + this._filters = value; } }); @@ -1031,19 +1043,21 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { * @param mask {Graphics} the graphics object to use as a filter * @private */ -PIXI.DisplayObject.prototype.addFilter = function(mask) +PIXI.DisplayObject.prototype.addFilter = function(data) { - if(this.filter)return; - this.filter = true; - + //if(this.filter)return; + //this.filter = true; // insert a filter block.. + // TODO Onject pool thease bad boys.. var start = new PIXI.FilterBlock(); var end = new PIXI.FilterBlock(); + data.start = start; + data.end = end; - start.mask = mask; - end.mask = mask; + start.data = data; + end.data = data; start.first = start.last = this; end.first = end.last = this; @@ -1051,9 +1065,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) start.open = true; /* - * * insert start - * */ var childFirst = start @@ -1084,9 +1096,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) // now insert the end filter block.. /* - * * insert end filter - * */ var childFirst = end var childLast = end @@ -1125,8 +1135,6 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) this.__renderGroup.addFilterBlocks(start, end); } - mask.renderable = false; - } /* @@ -1135,13 +1143,14 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) * @method removeFilter * @private */ -PIXI.DisplayObject.prototype.removeFilter = function() +PIXI.DisplayObject.prototype.removeFilter = function(data) { - if(!this.filter)return; - this.filter = false; - + //if(!this.filter)return; + //this.filter = false; + console.log("YUOIO") // modify the list.. - var startBlock = this.first; + var startBlock = data.start; + var nextObject = startBlock._iNext; var previousObject = startBlock._iPrev; @@ -1151,9 +1160,8 @@ PIXI.DisplayObject.prototype.removeFilter = function() this.first = startBlock._iNext; - // remove the end filter - var lastBlock = this.last; + var lastBlock = data.end; var nextObject = lastBlock._iNext; var previousObject = lastBlock._iPrev; @@ -1162,8 +1170,6 @@ PIXI.DisplayObject.prototype.removeFilter = function() previousObject._iNext = nextObject; // this is always true too! -// if(this.last == lastBlock) - //{ var tempLast = lastBlock._iPrev; // need to make sure the parents last is updated too var updateLast = this; @@ -1174,15 +1180,11 @@ PIXI.DisplayObject.prototype.removeFilter = function() if(!updateLast)break; } - var mask = startBlock.mask - mask.renderable = true; - // if webGL... if(this.__renderGroup) { this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); } - //} } /* @@ -1194,7 +1196,7 @@ PIXI.DisplayObject.prototype.removeFilter = function() PIXI.DisplayObject.prototype.updateTransform = function() { // TODO OPTIMIZE THIS!! with dirty - if(this.rotation != this.rotationCache) + if(this.rotation !== this.rotationCache) { this.rotationCache = this.rotation; this._sr = Math.sin(this.rotation); @@ -1236,9 +1238,12 @@ PIXI.DisplayObject.prototype.updateTransform = function() // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); this.worldAlpha = this.alpha * this.parent.worldAlpha; + + this.vcount = PIXI.visibleCount; } +PIXI.visibleCount = 0; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1270,18 +1275,6 @@ PIXI.DisplayObjectContainer = function() PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObjectContainer.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - - } -});*/ - /** * Adds a child to the container. * @@ -1299,11 +1292,10 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) } child.parent = this; - child.childIndex = this.children.length; this.children.push(child); - // updae the stage refference.. + // update the stage refference.. if(this.stage) { @@ -1326,7 +1318,7 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) var previousObject; // this could be wrong if there is a filter?? - if(this.filter) + if(this._filters) { previousObject = this.last._iPrev; } @@ -1338,7 +1330,6 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) nextObject = previousObject._iNext; // always true in this case - //this.last = child.last; // need to make sure the parents last is updated too var updateLast = this; var prevLast = previousObject; @@ -1402,7 +1393,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) } // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject; var previousObject; @@ -1410,7 +1401,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) if(index == this.children.length) { previousObject = this.last; - var updateLast = this;//.parent; + var updateLast = this; var prevLast = this.last; while(updateLast) { @@ -1539,7 +1530,7 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child) { // unlink // // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject = childLast._iNext; @@ -1609,7 +1600,6 @@ PIXI.DisplayObjectContainer.prototype.updateTransform = function() this.children[i].updateTransform(); } } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1739,9 +1729,18 @@ PIXI.Sprite.prototype.setTexture = function(texture) if(this.texture.baseTexture != texture.baseTexture) { this.textureChange = true; + this.texture = texture; + + if(this.__renderGroup) + { + this.__renderGroup.updateTexture(this); + } + } + else + { + this.texture = texture; } - this.texture = texture; this.updateFrame = true; } @@ -1798,7 +1797,6 @@ PIXI.Sprite.fromImage = function(imageId) return new PIXI.Sprite(texture); } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1814,7 +1812,7 @@ PIXI.Sprite.fromImage = function(imageId) PIXI.MovieClip = function(textures) { PIXI.Sprite.call(this, textures[0]); - + /** * The array of textures that make up the animation * @@ -1822,7 +1820,7 @@ PIXI.MovieClip = function(textures) * @type Array */ this.textures = textures; - + /** * The speed that the MovieClip will play at. Higher is faster, lower is slower * @@ -1848,7 +1846,7 @@ PIXI.MovieClip = function(textures) * @type Function */ this.onComplete = null; - + /** * [read-only] The index MovieClips current frame (this may not have to be a whole number) * @@ -1857,8 +1855,8 @@ PIXI.MovieClip = function(textures) * @default 0 * @readOnly */ - this.currentFrame = 0; - + this.currentFrame = 0; + /** * [read-only] Indicates if the MovieClip is currently playing * @@ -1873,6 +1871,23 @@ PIXI.MovieClip = function(textures) PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; +/** +* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures +* assigned to the MovieClip. +* +* @property totalFrames +* @type Number +* @default 0 +* @readOnly +*/ +Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { + get: function() { + + return this.textures.length; + } +}); + + /** * Stops the MovieClip * @@ -1928,11 +1943,13 @@ PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) PIXI.MovieClip.prototype.updateTransform = function() { PIXI.Sprite.prototype.updateTransform.call(this); - + if(!this.playing)return; - + this.currentFrame += this.animationSpeed; + var round = (this.currentFrame + 0.5) | 0; + if(this.loop || round < this.textures.length) { this.setTexture(this.textures[round % this.textures.length]); @@ -1952,14 +1969,49 @@ PIXI.MovieClip.prototype.updateTransform = function() -PIXI.FilterBlock = function(mask) +PIXI.FilterBlock = function() { - this.graphics = mask this.visible = true; this.renderable = true; } +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.ColorMatrixFilter = function() +{ + // set the uniforms + this.uniforms = { + matrix: {type: 'mat4', value: [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1]}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float invert;", + "uniform mat4 matrix;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", + "gl_FragColor = gl_FragColor * vColor;", + "}" + ]; + +} +Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { + get: function() { + return this.uniforms.matrix.value; + }, + set: function(value) { + this.uniforms.matrix.value = value; + } +}); /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1988,7 +2040,7 @@ PIXI.Text = function(text, style) this.setText(text); this.setStyle(style); - + this.updateText(); this.dirty = false; }; @@ -2030,7 +2082,7 @@ PIXI.Text.prototype.setStyle = function(style) * @methos setText * @param {String} text The copy that you would like the text to display */ -PIXI.Sprite.prototype.setText = function(text) +PIXI.Text.prototype.setText = function(text) { this.text = text.toString() || " "; this.dirty = true; @@ -2045,9 +2097,9 @@ PIXI.Sprite.prototype.setText = function(text) PIXI.Text.prototype.updateText = function() { this.context.font = this.style.font; - + var outputText = this.text; - + // word wrap // preserve original text if(this.style.wordWrap)outputText = this.wordWrap(this.text); @@ -2065,7 +2117,7 @@ PIXI.Text.prototype.updateText = function() maxLineWidth = Math.max(maxLineWidth, lineWidth); } this.canvas.width = maxLineWidth + this.style.strokeThickness; - + //calculate text height var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; this.canvas.height = lineHeight * lines.length; @@ -2073,7 +2125,7 @@ PIXI.Text.prototype.updateText = function() //set canvas text styles this.context.fillStyle = this.style.fill; this.context.font = this.style.font; - + this.context.strokeStyle = this.style.stroke; this.context.lineWidth = this.style.strokeThickness; @@ -2083,7 +2135,7 @@ PIXI.Text.prototype.updateText = function() for (i = 0; i < lines.length; i++) { var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); - + if(this.style.align == "right") { linePosition.x += maxLineWidth - lineWidths[i]; @@ -2103,7 +2155,7 @@ PIXI.Text.prototype.updateText = function() this.context.fillText(lines[i], linePosition.x, linePosition.y); } } - + this.updateTexture(); }; @@ -2119,10 +2171,10 @@ PIXI.Text.prototype.updateTexture = function() this.texture.baseTexture.height = this.canvas.height; this.texture.frame.width = this.canvas.width; this.texture.frame.height = this.canvas.height; - + this._width = this.canvas.width; this._height = this.canvas.height; - + PIXI.texturesToUpdate.push(this.texture.baseTexture); }; @@ -2136,10 +2188,10 @@ PIXI.Text.prototype.updateTransform = function() { if(this.dirty) { - this.updateText(); + this.updateText(); this.dirty = false; } - + PIXI.Sprite.prototype.updateTransform.call(this); }; @@ -2151,12 +2203,12 @@ PIXI.Text.prototype.updateTransform = function() * @param fontStyle {Object} * @private */ -PIXI.Text.prototype.determineFontHeight = function(fontStyle) +PIXI.Text.prototype.determineFontHeight = function(fontStyle) { // build a little reference dictionary so if the font style has been used return a // cached version... var result = PIXI.Text.heightCache[fontStyle]; - + if(!result) { var body = document.getElementsByTagName("body")[0]; @@ -2165,13 +2217,13 @@ PIXI.Text.prototype.determineFontHeight = function(fontStyle) dummy.appendChild(dummyText); dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); body.appendChild(dummy); - + result = dummy.offsetHeight; PIXI.Text.heightCache[fontStyle] = result; - + body.removeChild(dummy); } - + return result; }; @@ -2191,7 +2243,7 @@ PIXI.Text.prototype.wordWrap = function(text) if(p == start) { return 1; } - + if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) { if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) @@ -2208,7 +2260,7 @@ PIXI.Text.prototype.wordWrap = function(text) return arguments.callee(ctx, text, start, p, wrapWidth); } }; - + var lineWrap = function(ctx, text, wrapWidth) { if(ctx.measureText(text).width <= wrapWidth || text.length < 1) @@ -2218,14 +2270,14 @@ PIXI.Text.prototype.wordWrap = function(text) var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); }; - + var result = ""; var lines = text.split("\n"); for (var i = 0; i < lines.length; i++) { result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; } - + return result; }; @@ -2241,7 +2293,7 @@ PIXI.Text.prototype.destroy = function(destroyTexture) { this.texture.destroy(); } - + }; PIXI.Text.heightCache = {}; @@ -2252,7 +2304,7 @@ PIXI.Text.heightCache = {}; /** * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" - * You can generate the fnt files using + * You can generate the fnt files using * http://www.angelcode.com/products/bmfont/ for windows or * http://www.bmglyph.com/ for mac. * @@ -2342,7 +2394,7 @@ PIXI.BitmapText.prototype.updateText = function() prevCharCode = null; continue; } - + var charData = data.chars[charCode]; if(!charData) continue; @@ -2405,7 +2457,7 @@ PIXI.BitmapText.prototype.updateTransform = function() this.dirty = false; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); }; @@ -2414,10 +2466,8 @@ PIXI.BitmapText.fonts = {}; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ - - - -/** + + /** * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive * This manager also supports multitouch. * @@ -2451,6 +2501,8 @@ PIXI.InteractionManager = function(stage) */ this.touchs = {}; + + // helpers this.tempPoint = new PIXI.Point(); //this.tempMatrix = mat3.create(); @@ -2461,7 +2513,19 @@ PIXI.InteractionManager = function(stage) this.pool = []; this.interactiveItems = []; + this.interactionDOMElement = null; + //this will make it so that you dont have to call bind all the time + this.onMouseMove = this.onMouseMove.bind( this ); + this.onMouseDown = this.onMouseDown.bind(this); + this.onMouseOut = this.onMouseOut.bind(this); + this.onMouseUp = this.onMouseUp.bind(this); + + this.onTouchStart = this.onTouchStart.bind(this); + this.onTouchEnd = this.onTouchEnd.bind(this); + this.onTouchMove = this.onTouchMove.bind(this); + + this.last = 0; } @@ -2486,7 +2550,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj { var child = children[i]; - if(child.visible) { +// if(child.visible) { // push all interactive bits if(child.interactive) { @@ -2508,7 +2572,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj this.collectInteractiveSprite(child, iParent); } } - } +// } } } @@ -2521,27 +2585,68 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj */ PIXI.InteractionManager.prototype.setTarget = function(target) { + this.target = target; + + //check if the dom element has been set. If it has don't do anything + if( this.interactionDOMElement === null ) { + + this.setTargetDomElement( target.view ); + } + + document.body.addEventListener('mouseup', this.onMouseUp, true); +} + + +/** + * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM + * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element + * to receive those events + * + * @method setTargetDomElement + * @param domElement {DOMElement} the dom element which will receive mouse and touch events + * @private + */ +PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) +{ + //remove previouse listeners + if( this.interactionDOMElement !== null ) + { + this.interactionDOMElement.style['-ms-content-zooming'] = ''; + this.interactionDOMElement.style['-ms-touch-action'] = ''; + + this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); + this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); + this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); + this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); + this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); + } + + if (window.navigator.msPointerEnabled) { // time to remove some of that zoom in ja.. - target.view.style["-ms-content-zooming"] = "none"; - target.view.style["-ms-touch-action"] = "none" + domElement.style['-ms-content-zooming'] = 'none'; + domElement.style['-ms-touch-action'] = 'none'; // DO some window specific touch! } - - this.target = target; - target.view.addEventListener('mousemove', this.onMouseMove.bind(this), true); - target.view.addEventListener('mousedown', this.onMouseDown.bind(this), true); - document.body.addEventListener('mouseup', this.onMouseUp.bind(this), true); - target.view.addEventListener('mouseout', this.onMouseUp.bind(this), true); - - // aint no multi touch just yet! - target.view.addEventListener("touchstart", this.onTouchStart.bind(this), true); - target.view.addEventListener("touchend", this.onTouchEnd.bind(this), true); - target.view.addEventListener("touchmove", this.onTouchMove.bind(this), true); + + this.interactionDOMElement = domElement; + + domElement.addEventListener('mousemove', this.onMouseMove, true); + domElement.addEventListener('mousedown', this.onMouseDown, true); + domElement.addEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + domElement.addEventListener('touchstart', this.onTouchStart, true); + domElement.addEventListener('touchend', this.onTouchEnd, true); + domElement.addEventListener('touchmove', this.onTouchMove, true); } + /** * updates the state of interactive objects * @@ -2583,12 +2688,14 @@ PIXI.InteractionManager.prototype.update = function() // loop through interactive objects! var length = this.interactiveItems.length; - this.target.view.style.cursor = "default"; + this.interactionDOMElement.style.cursor = "default"; for (var i = 0; i < length; i++) { var item = this.interactiveItems[i]; - if(!item.visible)continue; + + + //if(!item.visible)continue; // OPTIMISATION - only calculate every time if the mousemove function exists.. // OK so.. does the object have any other interactive functions? @@ -2604,7 +2711,7 @@ PIXI.InteractionManager.prototype.update = function() // loks like there was a hit! if(item.__hit) { - if(item.buttonMode)this.target.view.style.cursor = "pointer"; + if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; if(!item.__isOver) { @@ -2639,7 +2746,7 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) { this.mouse.originalEvent = event || window.event; //IE uses window.event // TODO optimize by not check EVERY TIME! maybe half as often? // - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); @@ -2669,7 +2776,6 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) */ PIXI.InteractionManager.prototype.onMouseDown = function(event) { - event.preventDefault(); this.mouse.originalEvent = event || window.event; //IE uses window.event // loop through inteaction tree... @@ -2706,6 +2812,26 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) } } + +PIXI.InteractionManager.prototype.onMouseOut = function(event) +{ + var length = this.interactiveItems.length; + + this.interactionDOMElement.style.cursor = "default"; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.__isOver) + { + this.mouse.target = item; + if(item.mouseout)item.mouseout(this.mouse); + item.__isOver = false; + } + } +} + /** * Is called when the mouse button is released on the renderer element * @@ -2770,7 +2896,7 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) { var global = interactionData.global; - if(!item.visible)return false; + if(item.vcount !== PIXI.visibleCount)return false; var isSprite = (item instanceof PIXI.Sprite), worldTransform = item.worldTransform, @@ -2840,14 +2966,14 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) */ PIXI.InteractionManager.prototype.onTouchMove = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) { var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; + touchData.originalEvent = event || window.event; // update the touch position touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); @@ -2871,10 +2997,7 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) */ PIXI.InteractionManager.prototype.onTouchStart = function(event) { - event.preventDefault(); - this.mouse.originalEvent = event || window.event; //IE uses window.event - - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2884,6 +3007,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) var touchData = this.pool.pop(); if(!touchData)touchData = new PIXI.InteractionData(); + touchData.originalEvent = event || window.event; + this.touchs[touchEvent.identifier] = touchData; touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); @@ -2921,8 +3046,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) */ PIXI.InteractionManager.prototype.onTouchEnd = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + //this.mouse.originalEvent = event || window.event; //IE uses window.event + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2943,7 +3068,7 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) if(itemTouchData == touchData) { // so this one WAS down... - + touchData.originalEvent = event || window.event; // hitTest?? if(item.touchend || item.tap) @@ -3055,9 +3180,8 @@ PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; * @constructor * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format * like: 0xFFFFFF for white - * @param interactive {Boolean} enable / disable interaction (default is false) */ -PIXI.Stage = function(backgroundColor, interactive) +PIXI.Stage = function(backgroundColor) { PIXI.DisplayObjectContainer.call( this ); @@ -3077,7 +3201,7 @@ PIXI.Stage = function(backgroundColor, interactive) * @property interactive * @type Boolean */ - this.interactive = interactive; + this.interactive = true; /** * The interaction manage for this stage, manages all interactive activity on the stage @@ -3113,6 +3237,18 @@ PIXI.Stage = function(backgroundColor, interactive) PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); PIXI.Stage.prototype.constructor = PIXI.Stage; +/** + * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. + * This is useful for when you have other DOM elements ontop of the Canvas element. + * + * @method setInteractionDelegate + * @param domElement {DOMElement} This new domElement which will receive mouse/touch events + */ +PIXI.Stage.prototype.setInteractionDelegate = function(domElement) +{ + this.interactionManager.setTargetDomElement( domElement ); +} + /* * Updates the object transform for rendering * @@ -3122,6 +3258,7 @@ PIXI.Stage.prototype.constructor = PIXI.Stage; PIXI.Stage.prototype.updateTransform = function() { this.worldAlpha = 1; + this.vcount = PIXI.visibleCount; for(var i=0,j=this.children.length; i 100) { console.log("BREAK") break } - } + } } @@ -3361,14 +3466,14 @@ PIXI.runList = function(item) PIXI.EventTarget = function () { var listeners = {}; - + this.addEventListener = this.on = function ( type, listener ) { - - + + if ( listeners[ type ] === undefined ) { listeners[ type ] = []; - + } if ( listeners[ type ].indexOf( listener ) === - 1 ) { @@ -3379,11 +3484,17 @@ PIXI.EventTarget = function () { }; this.dispatchEvent = this.emit = function ( event ) { - - for ( var listener in listeners[ event.type ] ) { - listeners[ event.type ][ listener ]( event ); - + if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { + + return; + + } + + for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { + + listeners[ event.type ][ i ]( event ); + } }; @@ -3417,8 +3528,11 @@ PIXI.EventTarget = function () { * @param height {Number} the height of the renderers view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) + * + * antialias */ -PIXI.autoDetectRenderer = function(width, height, view, transparent) +PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) { if(!width)width = 800; if(!height)height = 600; @@ -3429,7 +3543,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) //console.log(webgl); if( webgl ) { - return new PIXI.WebGLRenderer(width, height, view, transparent); + return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); } return new PIXI.CanvasRenderer(width, height, view, transparent); @@ -3441,7 +3555,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) PolyK library url: http://polyk.ivank.net Released under MIT licence. - + Copyright (c) 2012 Ivan Kuckir Permission is hereby granted, free of charge, to any person @@ -3465,8 +3579,8 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - This is an amazing lib! - + This is an amazing lib! + slightly modified by mat groves (matgroves.com); */ @@ -3482,13 +3596,13 @@ PIXI.PolyK = {}; PIXI.PolyK.Triangulate = function(p) { var sign = true; - + var n = p.length>>1; if(n<3) return []; var tgs = []; var avl = []; for(var i=0; i 3) @@ -3496,11 +3610,11 @@ PIXI.PolyK.Triangulate = function(p) var i0 = avl[(i+0)%al]; var i1 = avl[(i+1)%al]; var i2 = avl[(i+2)%al]; - + var ax = p[2*i0], ay = p[2*i0+1]; var bx = p[2*i1], by = p[2*i1+1]; var cx = p[2*i2], cy = p[2*i2+1]; - + var earFound = false; if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) { @@ -3519,7 +3633,7 @@ PIXI.PolyK.Triangulate = function(p) al--; i = 0; } - else if(i++ > 3*al) + else if(i++ > 3*al) { // need to flip flip reverse it! // reset! @@ -3528,17 +3642,17 @@ PIXI.PolyK.Triangulate = function(p) var tgs = []; avl = []; for(var i=0; i= 0) == sign; } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -3612,13 +3725,11 @@ PIXI.shaderVertexSrc = [ "attribute vec2 aVertexPosition;", "attribute vec2 aTextureCoord;", "attribute float aColor;", - //"uniform mat4 uMVMatrix;", "uniform vec2 projectionVector;", "varying vec2 vTextureCoord;", "varying float vColor;", "void main(void) {", - // "gl_Position = uMVMatrix * vec4(aVertexPosition, 1.0, 1.0);", "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", "vTextureCoord = aTextureCoord;", "vColor = aColor;", @@ -3658,7 +3769,6 @@ PIXI.stripShaderVertexSrc = [ "}" ]; - /* * primitive shader.. */ @@ -3685,6 +3795,8 @@ PIXI.primitiveShaderVertexSrc = [ "}" ]; +PIXI.shaderStack = []; + PIXI.initPrimitiveShader = function() { var gl = PIXI.gl; @@ -3699,27 +3811,26 @@ PIXI.initPrimitiveShader = function() shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); + + //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(shaderProgram.colorAttribute); +//gl.enableVertexAttribArray(program.textureCoordAttribute); + shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); PIXI.primitiveProgram = shaderProgram; + + } PIXI.initDefaultShader = function() { - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.shaderVertexSrc, PIXI.shaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - // shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.shaderProgram = shaderProgram; + PIXI.defaultShader = new PIXI.PixiShader(); + PIXI.defaultShader.init(); + PIXI.activateShader(PIXI.defaultShader); + /* + PIXI.shaderStack.push(PIXI.defaultShader); + PIXI.current*/ } PIXI.initDefaultStripShader = function() @@ -3736,9 +3847,7 @@ PIXI.initDefaultStripShader = function() shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); PIXI.stripShaderProgram = shaderProgram; @@ -3789,35 +3898,135 @@ PIXI.compileProgram = function(vertexSrc, fragmentSrc) return shaderProgram; } +PIXI.activateShader = function(shader) +{ + PIXI.shaderStack.push(shader); + + //console.log(">>>") + var gl = PIXI.gl; + + var shaderProgram = shader.program; + + // map uniforms.. + gl.useProgram(shaderProgram); + + gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + gl.enableVertexAttribArray(shaderProgram.colorAttribute); + gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); -PIXI.activateDefaultShader = function() + shader.syncUniforms(); + + PIXI.currentShader = shaderProgram; +} + + +PIXI.popShader = function() { var gl = PIXI.gl; - var shaderProgram = PIXI.shaderProgram; + // activate last program.. + var lastProgram = PIXI.shaderStack.pop(); + + var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); + PIXI.currentShader = shaderProgram; } - - PIXI.activatePrimitiveShader = function() { var gl = PIXI.gl; - gl.disableVertexAttribArray(PIXI.shaderProgram.textureCoordAttribute); - gl.disableVertexAttribArray(PIXI.shaderProgram.colorAttribute); - gl.useProgram(PIXI.primitiveProgram); - gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); + gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + + //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); } +PIXI.deactivatePrimitiveShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.currentShader); + + gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.PixiShader = function() +{ + // the webGL program.. + this.program; + + this.fragmentSrc = [ + "precision lowp float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", + "}" + ]; + +} + +PIXI.PixiShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get the default shader bits! + program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); + program.colorAttribute = gl.getAttribLocation(program, "aColor"); + program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); + + program.projectionVector = gl.getUniformLocation(program, "projectionVector"); + program.samplerUniform = gl.getUniformLocation(program, "uSampler"); + + // add those custom shaders! + for (var key in this.uniforms) + { + // get the uniform locations.. + program[key] = gl.getUniformLocation(program, key); + } + + this.program = program; +} + +PIXI.PixiShader.prototype.syncUniforms = function() +{ + var gl = PIXI.gl; + + for (var key in this.uniforms) + { + //var + var type = this.uniforms[key].type; + + // need to grow this! + if(type == "f") + { + gl.uniform1f(this.program[key], this.uniforms[key].value); + } + else if(type == "mat4") + { + gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); + } + } + +} + /** * @author Mat Groves http://matgroves.com/ @Doormat23 @@ -3887,7 +4096,7 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); // WHY DOES THIS LINE NEED TO BE THERE??? - gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // its not even used.. but need to be set or it breaks? // only on pc though.. @@ -3899,8 +4108,10 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); + PIXI.deactivatePrimitiveShader(); + // return to default shader... - PIXI.activateDefaultShader(); +// PIXI.activateShader(PIXI.defaultShader); } /** @@ -4243,7 +4454,7 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) verts.push(px , py); verts.push(r, g, b, alpha); - verts.push(p2x - (px-p2x), p2y - (py - p2y));//, 4); + verts.push(p2x - (px-p2x), p2y - (py - p2y)); verts.push(r, g, b, alpha); } } @@ -4356,9 +4567,10 @@ PIXI.gl; * @param height=0 {Number} the height of the canvas view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) * */ -PIXI.WebGLRenderer = function(width, height, view, transparent) +PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) { // do a catch.. only 1 webGL renderer.. @@ -4382,7 +4594,7 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) { PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { alpha: this.transparent, - antialias:true, // SPEED UP?? + antialias:!!antialias, // SPEED UP?? premultipliedAlpha:false, stencil:true }); @@ -4392,11 +4604,12 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); } - PIXI.initPrimitiveShader(); PIXI.initDefaultShader(); + PIXI.initPrimitiveShader(); PIXI.initDefaultStripShader(); - PIXI.activateDefaultShader(); + +// PIXI.activateDefaultShader(); var gl = this.gl; PIXI.WebGLRenderer.gl = gl; @@ -4413,7 +4626,10 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) this.resize(this.width, this.height); this.contextLost = false; + PIXI.activateShader(PIXI.defaultShader); + this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); + } // constructor @@ -4469,8 +4685,6 @@ PIXI.WebGLRenderer.prototype.render = function(stage) { // TODO make this work // dont think this is needed any more? - //if(this.__stage)this.checkVisibility(this.__stage, false) - this.__stage = stage; this.stageRenderGroup.setRenderable(stage); } @@ -4487,10 +4701,8 @@ PIXI.WebGLRenderer.prototype.render = function(stage) // update any textures PIXI.WebGLRenderer.updateTextures(); - // recursivly loop through all items! - //this.checkVisibility(stage, true); - // update the scene graph + PIXI.visibleCount++; stage.updateTransform(); var gl = this.gl; @@ -4499,16 +4711,12 @@ PIXI.WebGLRenderer.prototype.render = function(stage) gl.colorMask(true, true, true, this.transparent); gl.viewport(0, 0, this.width, this.height); - // set the correct matrix.. - // gl.uniformMatrix4fv(this.shaderProgram.mvMatrixUniform, false, this.projectionMatrix); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); gl.clear(gl.COLOR_BUFFER_BIT); // HACK TO TEST - //PIXI.projectionMatrix = this.projectionMatrix; this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; this.stageRenderGroup.render(PIXI.projection); @@ -4546,8 +4754,9 @@ PIXI.WebGLRenderer.prototype.render = function(stage) */ PIXI.WebGLRenderer.updateTextures = function() { - for (var i=0; i < PIXI.texturesToUpdate.length; i++) this.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) this.destroyTexture(PIXI.texturesToDestroy[i]); + //TODO break this out into a texture manager... + for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); + for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; } @@ -4562,6 +4771,7 @@ PIXI.WebGLRenderer.updateTextures = function() */ PIXI.WebGLRenderer.updateTexture = function(texture) { + //TODO break this out into a texture manager... var gl = PIXI.gl; if(!texture._glTexture) @@ -4602,9 +4812,10 @@ PIXI.WebGLRenderer.updateTexture = function(texture) * @param texture {Texture} The texture to update * @private */ -PIXI.WebGLRenderer.prototype.destroyTexture = function(texture) +PIXI.WebGLRenderer.destroyTexture = function(texture) { - var gl = this.gl; + //TODO break this out into a texture manager... + var gl = PIXI.gl; if(texture._glTexture) { @@ -4768,7 +4979,6 @@ PIXI.WebGLBatch.prototype.clean = function() this.uvs = []; this.indices = []; this.colors = []; - //this.sprites = []; this.dynamicSize = 1; this.texture = null; this.last = null; @@ -4805,7 +5015,6 @@ PIXI.WebGLBatch.prototype.init = function(sprite) this.dirty = true; this.blendMode = sprite.blendMode; this.texture = sprite.texture.baseTexture; -// this.sprites.push(sprite); this.head = sprite; this.tail = sprite; this.size = 1; @@ -4838,7 +5047,6 @@ PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) else { this.head = sprite; - //this.head.__prev = null } } @@ -4926,7 +5134,7 @@ PIXI.WebGLBatch.prototype.split = function(sprite) { this.dirty = true; - var batch = new PIXI.WebGLBatch(this.gl);//PIXI._getBatch(this.gl); + var batch = new PIXI.WebGLBatch(this.gl); batch.init(sprite); batch.texture = this.texture; batch.tail = this.tail; @@ -4936,8 +5144,6 @@ PIXI.WebGLBatch.prototype.split = function(sprite) sprite.__prev = null; // return a splite batch! - //sprite.__prev.__next = null; - //sprite.__prev = null; // TODO this size is wrong! // need to recalculate :/ problem with a linked list! @@ -5007,13 +5213,13 @@ PIXI.WebGLBatch.prototype.growBatch = function() gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); - this.uvs = new Float32Array( this.dynamicSize * 8 ) + this.uvs = new Float32Array( this.dynamicSize * 8 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); this.dirtyUVS = true; - this.colors = new Float32Array( this.dynamicSize * 4 ) + this.colors = new Float32Array( this.dynamicSize * 4 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); @@ -5112,7 +5318,7 @@ PIXI.WebGLBatch.prototype.update = function() while(displayObject) { - if(displayObject.worldVisible) + if(displayObject.vcount === PIXI.visibleCount) { width = displayObject.texture.frame.width; height = displayObject.texture.frame.height; @@ -5214,7 +5420,7 @@ PIXI.WebGLBatch.prototype.update = function() PIXI.WebGLBatch.prototype.render = function(start, end) { start = start || 0; - //end = end || this.size; + if(end == undefined)end = this.size; if(this.dirty) @@ -5230,8 +5436,9 @@ PIXI.WebGLBatch.prototype.render = function(start, end) //TODO optimize this! - var shaderProgram = PIXI.shaderProgram; - gl.useProgram(shaderProgram); + var shaderProgram = PIXI.currentShader; + + //gl.useProgram(shaderProgram); // update the verts.. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); @@ -5239,6 +5446,8 @@ PIXI.WebGLBatch.prototype.render = function(start, end) gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // update the uvs + var isDefault = (shaderProgram == PIXI.shaderProgram) + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); if(this.dirtyUVS) @@ -5262,13 +5471,11 @@ PIXI.WebGLBatch.prototype.render = function(start, end) } gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - //var startIndex = 0//1; var len = end - start; - // console.log(this.size) + // DRAW THAT this! gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); } @@ -5336,77 +5543,45 @@ PIXI.WebGLRenderGroup.prototype.render = function(projection) PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - // TODO remove this by replacing visible with getter setters.. - this.checkVisibility(this.root, this.root.visible); - // will render all the elements in the group var renderable; - - for (var i=0; i < this.batchs.length; i++) { + renderable = this.batchs[i]; if(renderable instanceof PIXI.WebGLBatch) { this.batchs[i].render(); + continue; } - else if(renderable instanceof PIXI.TilingSprite) + + // non sprite batch.. + var worldVisible = renderable.vcount === PIXI.visibleCount; + + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ - if(renderable.open) - { - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - gl.colorMask(true, true, true, false); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - else - { - gl.disable(gl.STENCIL_TEST); - } + this.handleFilterBlock(renderable, projection); } } } -/** - * Renders the stage to its webgl view - * - * @method handleFilter - * @param filter {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.handleFilter = function(filter, projection) -{ - -} - /** * Renders a specific displayObject * @@ -5420,11 +5595,8 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - this.checkVisibility(displayObject, displayObject.visible); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); -// gl.uniformMatrix4fv(PIXI.shaderProgram.mvMatrixUniform, false, projectionMatrix); - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); - // to do! // render part of the scene... @@ -5483,7 +5655,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project while(lastItem.children.length > 0) { lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem; + if(lastItem.renderable)lastRenderable = lastItem.last; } if(lastRenderable instanceof PIXI.Sprite) @@ -5577,45 +5749,80 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project */ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) { + var sta = PIXI.shaderStack.length; + + var worldVisible = renderable.vcount === PIXI.visibleCount + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.CustomRenderable) { - if(renderable.visible) renderable.renderWebGL(this, projection); + if(worldVisible) renderable.renderWebGL(this, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ + this.handleFilterBlock(renderable, projection); + } +} - var gl = PIXI.gl; +PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) +{ + /* + * for now only masks are supported.. + */ + var gl = PIXI.gl; - if(renderable.open) + if(renderable.open) + { + if(renderable.data instanceof Array) + { + var filter = renderable.data[0]; + + if(!filter.shader) + { + var shader = new PIXI.PixiShader(); + + shader.fragmentSrc = filter.fragmentSrc; + shader.uniforms = filter.uniforms; + shader.init(); + + filter.shader = shader + } + + PIXI.activateShader(filter.shader); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } + else { gl.enable(gl.STENCIL_TEST); gl.colorMask(false, false, false, false); gl.stencilFunc(gl.ALWAYS,1,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - // we know this is a render texture so enable alpha too.. + PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); + gl.colorMask(true, true, true, true); gl.stencilFunc(gl.NOTEQUAL,0,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); } + } + else + { + if(renderable.data instanceof Array) + { + PIXI.popShader(); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } else { gl.disable(gl.STENCIL_TEST); @@ -5623,42 +5830,6 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) } } -/** - * Checks the visibility of a displayObject - * - * @method checkVisibility - * @param displayObject {DisplayObject} - * @param globalVisible {Boolean} - * @private - */ -PIXI.WebGLRenderGroup.prototype.checkVisibility = function(displayObject, globalVisible) -{ - // give the dp a reference to its renderGroup... - var children = displayObject.children; - //displayObject.worldVisible = globalVisible; - for (var i=0; i < children.length; i++) - { - var child = children[i]; - - // TODO optimize... should'nt need to loop through everything all the time - child.worldVisible = child.visible && globalVisible; - - // everything should have a batch! - // time to see whats new! - if(child.textureChange) - { - child.textureChange = false; - if(child.worldVisible)this.updateTexture(child); - // update texture!! - } - - if(child.children.length > 0) - { - this.checkVisibility(child, child.worldVisible); - } - }; -} - /** * Updates a webgl texture * @@ -5719,7 +5890,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * It keeps going back until it finds a sprite or the stage */ var previousRenderable = start; - while(previousRenderable != this.root) + while(previousRenderable != this.root.first) { previousRenderable = previousRenderable._iPrev; if(previousRenderable.renderable && previousRenderable.__renderGroup)break; @@ -5733,7 +5904,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * scene graph */ var previousRenderable2 = end; - while(previousRenderable2 != this.root) + while(previousRenderable2 != this.root.first) { previousRenderable2 = previousRenderable2._iPrev; if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; @@ -6105,6 +6276,7 @@ PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) } } + /** * Initializes a tiling sprite * @@ -6175,23 +6347,19 @@ PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) { var gl = this.gl; - var shaderProgram = PIXI.shaderProgram; -// mat - //var mat4Real = PIXI.mat3.toMat4(strip.worldTransform); - //PIXI.mat4.transpose(mat4Real); - //PIXI.mat4.multiply(projectionMatrix, mat4Real, mat4Real ) - + var shaderProgram = PIXI.stripShaderProgram; - gl.useProgram(PIXI.stripShaderProgram); + + gl.useProgram(shaderProgram); var m = PIXI.mat3.clone(strip.worldTransform); PIXI.mat3.transpose(m); // set the matrix transform for the - gl.uniformMatrix3fv(PIXI.stripShaderProgram.translationMatrix, false, m); - gl.uniform2f(PIXI.stripShaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(PIXI.stripShaderProgram.alpha, strip.worldAlpha); + gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); + gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); /* if(strip.blendMode == PIXI.blendModes.NORMAL) @@ -6249,11 +6417,10 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } - //console.log(gl.TRIANGLE_STRIP); gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - gl.useProgram(PIXI.shaderProgram); + gl.useProgram(PIXI.currentProgram); } /** @@ -6328,6 +6495,7 @@ PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } + /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -6401,7 +6569,6 @@ PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; */ PIXI.CanvasRenderer.prototype.render = function(stage) { - // update children if need be //stage.__childrenAdded = []; //stage.__childrenRemoved = []; @@ -6410,6 +6577,7 @@ PIXI.CanvasRenderer.prototype.render = function(stage) PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; + PIXI.visibleCount++; stage.updateTransform(); // update the background color @@ -6496,7 +6664,7 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) var frame = displayObject.texture.frame; - if(frame) + if(frame && frame.width && frame.height) { context.globalAlpha = displayObject.worldAlpha; @@ -6534,31 +6702,34 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) } else if(displayObject instanceof PIXI.FilterBlock) { - if(displayObject.open) + if(PIXI.FilterBlock.data instanceof PIXI.Graphics) { - context.save(); - - var cacheAlpha = displayObject.mask.alpha; - var maskTransform = displayObject.mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - displayObject.mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); - // context.fillStyle = 0xFF0000; - // context.fillRect(0, 0, 200, 200); - context.clip(); - - displayObject.mask.worldAlpha = cacheAlpha; - //context.globalCompositeOperation = 'lighter'; + if(displayObject.open) + { + context.save(); + + var cacheAlpha = displayObject.mask.alpha; + var maskTransform = displayObject.mask.worldTransform; + + context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) + + displayObject.mask.worldAlpha = 0.5; + + context.worldAlpha = 0; + + PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); + context.clip(); + + displayObject.mask.worldAlpha = cacheAlpha; + } + else + { + context.restore(); + } } else { - //context.globalCompositeOperation = 'source-over'; - context.restore(); + // only masks supported right now! } } // count++ @@ -6651,7 +6822,7 @@ PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) PIXI.CanvasRenderer.prototype.renderStrip = function(strip) { var context = this.context; - //context.globalCompositeOperation = 'lighter'; + // draw triangles!! var verticies = strip.verticies; var uvs = strip.uvs; @@ -6678,8 +6849,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.lineTo(x2, y2); context.closePath(); - // context.fillStyle = "white"//rgb(1, 1, 1,1)); - // context.fill(); context.clip(); @@ -6703,7 +6872,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.restore(); }; -// context.globalCompositeOperation = 'source-over'; } /** @@ -6718,7 +6886,7 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) */ PIXI.CanvasGraphics = function() { - + } @@ -6734,35 +6902,33 @@ PIXI.CanvasGraphics = function() PIXI.CanvasGraphics.renderGraphics = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - - for (var i=0; i < graphics.graphicsData.length; i++) + + for (var i=0; i < graphics.graphicsData.length; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); context.lineWidth = data.lineWidth; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); - + context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6777,21 +6943,20 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.RECT) { - - // TODO - need to be Undefined! - if(data.fillColor) + + if(data.fillColor || data.fillColor === 0) { context.globalAlpha = data.fillAlpha * worldAlpha; context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); context.fillRect(points[0], points[1], points[2], points[3]); - + } if(data.lineWidth) { context.globalAlpha = data.lineAlpha * worldAlpha; context.strokeRect(points[0], points[1], points[2], points[3]); } - + } else if(data.type == PIXI.Graphics.CIRC) { @@ -6799,7 +6964,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.beginPath(); context.arc(points[0], points[1], points[2],0,2*Math.PI); context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6814,19 +6979,19 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - + var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6834,15 +6999,15 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - + context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6855,7 +7020,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.stroke(); } } - + }; } @@ -6871,37 +7036,35 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - + var len = graphics.graphicsData.length; if(len > 1) { len = 1; console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") } - - for (var i=0; i < 1; i++) + + for (var i=0; i < 1; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + } else if(data.type == PIXI.Graphics.RECT) { @@ -6918,18 +7081,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6937,7 +7100,7 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); @@ -6945,8 +7108,8 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); context.closePath(); } - - + + }; } @@ -6956,18 +7119,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) /** - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. + * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. * It is important to know that with the webGL renderer only simple polys can be filled at this stage * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png * - * @class Graphics + * @class Graphics * @extends DisplayObjectContainer * @constructor */ PIXI.Graphics = function() { PIXI.DisplayObjectContainer.call( this ); - + this.renderable = true; /** @@ -7028,14 +7191,14 @@ PIXI.Graphics.prototype.constructor = PIXI.Graphics; PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - + this.lineWidth = lineWidth || 0; this.lineColor = color || 0; this.lineAlpha = (alpha == undefined) ? 1 : alpha; - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.graphicsData.push(this.currentPath); } @@ -7049,12 +7212,12 @@ PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) PIXI.Graphics.prototype.moveTo = function(x, y) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.currentPath.points.push(x, y); - + this.graphicsData.push(this.currentPath); } @@ -7084,7 +7247,7 @@ PIXI.Graphics.prototype.beginFill = function(color, alpha) { this.filling = true; this.fillColor = color || 0; - this.fillAlpha = alpha || 1; + this.fillAlpha = (alpha == undefined) ? 1 : alpha; } /** @@ -7110,11 +7273,11 @@ PIXI.Graphics.prototype.endFill = function() PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.RECT}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7130,11 +7293,11 @@ PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) PIXI.Graphics.prototype.drawCircle = function( x, y, radius) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7151,11 +7314,11 @@ PIXI.Graphics.prototype.drawCircle = function( x, y, radius) PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.ELIP}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7169,7 +7332,7 @@ PIXI.Graphics.prototype.clear = function() { this.lineWidth = 0; this.filling = false; - + this.dirty = true; this.clearDirty = true; this.graphicsData = []; @@ -7190,20 +7353,20 @@ PIXI.Strip = function(texture, width, height) PIXI.DisplayObjectContainer.call( this ); this.texture = texture; this.blendMode = PIXI.blendModes.NORMAL; - + try { this.uvs = new Float32Array([0, 1, 1, 1, 1, 0, 0,1]); - + this.verticies = new Float32Array([0, 0, 0,0, 0,0, 0, 0, 0]); - + this.colors = new Float32Array([1, 1, 1, 1]); - + this.indices = new Uint16Array([0, 1, 2, 3]); } catch(error) @@ -7211,18 +7374,18 @@ PIXI.Strip = function(texture, width, height) this.uvs = [0, 1, 1, 1, 1, 0, 0,1]; - + this.verticies = [0, 0, 0,0, 0,0, 0, 0, 0]; - + this.colors = [1, 1, 1, 1]; - + this.indices = [0, 1, 2, 3]; } - - + + /* this.uvs = new Float32Array() this.verticies = new Float32Array() @@ -7231,7 +7394,7 @@ PIXI.Strip = function(texture, width, height) */ this.width = width; this.height = height; - + // load the texture! if(texture.baseTexture.hasLoaded) { @@ -7244,7 +7407,7 @@ PIXI.Strip = function(texture, width, height) this.onTextureUpdateBind = this.onTextureUpdate.bind(this); this.texture.addEventListener( 'update', this.onTextureUpdateBind ); } - + this.renderable = true; } @@ -7256,8 +7419,8 @@ PIXI.Strip.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.width = texture.frame.width; this.height = texture.frame.height; @@ -7280,7 +7443,7 @@ PIXI.Rope = function(texture, points) { PIXI.Strip.call( this, texture ); this.points = points; - + try { this.verticies = new Float32Array( points.length * 4); @@ -7291,12 +7454,12 @@ PIXI.Rope = function(texture, points) catch(error) { this.verticies = verticies - + this.uvs = uvs this.colors = colors this.indices = indices } - + this.refresh(); } @@ -7309,99 +7472,99 @@ PIXI.Rope.prototype.refresh = function() { var points = this.points; if(points.length < 1)return; - + var uvs = this.uvs var indices = this.indices; var colors = this.colors; - + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - + + uvs[0] = 0 uvs[1] = 1 uvs[2] = 0 uvs[3] = 1 - + colors[0] = 1; colors[1] = 1; - + indices[0] = 0; indices[1] = 1; - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; // time to do some smart drawing! var 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; } } PIXI.Rope.prototype.updateTransform = function() { - + var points = this.points; if(points.length < 1)return; - - var verticies = this.verticies - + + var verticies = this.verticies + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - verticies[0] = point.x + perp.x + + verticies[0] = point.x + perp.x verticies[1] = point.y + perp.y //+ 200 - verticies[2] = point.x - perp.x + verticies[2] = point.x - perp.x verticies[3] = point.y - perp.y//+200 // time to do some smart drawing! - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; - + if(i < points.length-1) { nextPoint = points[i+1]; @@ -7410,35 +7573,35 @@ PIXI.Rope.prototype.updateTransform = function() { nextPoint = point } - + perp.y = -(nextPoint.x - lastPoint.x); perp.x = nextPoint.y - lastPoint.y; - + var ratio = (1 - (i / (total-1))) * 10; if(ratio > 1)ratio = 1; - + var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); var 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; - - verticies[index] = point.x + perp.x + + verticies[index] = point.x + perp.x verticies[index+1] = point.y + perp.y - verticies[index+2] = point.x - perp.x + verticies[index+2] = point.x - perp.x verticies[index+3] = point.y - perp.y lastPoint = point; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); } PIXI.Rope.prototype.setTexture = function(texture) { - // stop current texture + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7494,7 +7657,7 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tileScale * @type Point - */ + */ this.tileScale = new PIXI.Point(1,1); /** @@ -7502,11 +7665,11 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tilePosition * @type Point - */ + */ this.tilePosition = new PIXI.Point(0,0); this.renderable = true; - + this.blendMode = PIXI.blendModes.NORMAL } @@ -7524,8 +7687,8 @@ PIXI.TilingSprite.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7546,10 +7709,10 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) /** * @author Mat Groves http://matgroves.com/ @Doormat23 * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * + * * Awesome JS run time provided by EsotericSoftware * https://github.com/EsotericSoftware/spine-runtimes - * + * */ /** @@ -7562,48 +7725,41 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) * @constructor * @param url {String} The url of the spine anim file to be used */ -PIXI.Spine = function(url) -{ +PIXI.Spine = function (url) { PIXI.DisplayObjectContainer.call(this); - + this.spineData = PIXI.AnimCache[url]; - - if(!this.spineData) - { + + if (!this.spineData) { throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: " + url); - return; } - - this.count = 0; - - this.sprites = []; - + this.skeleton = new spine.Skeleton(this.spineData); this.skeleton.updateWorldTransform(); - this.stateData = new spine.AnimationStateData(this.spineData); + this.stateData = new spine.AnimationStateData(this.spineData); this.state = new spine.AnimationState(this.stateData); - - // add the sprites.. - for (var i = 0; i < this.skeleton.drawOrder.length; i++) { - - var attachmentName = this.skeleton.drawOrder[i].data.attachmentName; - - // kind of an assumtion here. that its a png - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; - } - - - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(attachmentName)); - sprite.anchor.x = sprite.anchor.y = 0.5; - this.addChild(sprite); - this.sprites.push(sprite); - }; -} -PIXI.Spine.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); + 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)) { + continue; + } + var spriteName = attachment.rendererObject.name; + var sprite = this.createSprite(slot, attachment.rendererObject); + slot.currentSprite = sprite; + slot.currentSpriteName = spriteName; + slotContainer.addChild(sprite); + } +}; + +PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); PIXI.Spine.prototype.constructor = PIXI.Spine; /* @@ -7612,55 +7768,74 @@ PIXI.Spine.prototype.constructor = PIXI.Spine; * @method updateTransform * @private */ -PIXI.Spine.prototype.updateTransform = function() -{ - // TODO should make this time based really.. - this.state.update(1/60); +PIXI.Spine.prototype.updateTransform = function () { + this.lastTime = this.lastTime || Date.now(); + var timeDelta = (Date.now() - this.lastTime) * 0.001; + this.lastTime = Date.now(); + this.state.update(timeDelta); this.state.apply(this.skeleton); this.skeleton.updateWorldTransform(); - - for (var i = 0; i < this.skeleton.drawOrder.length; i++) - { - var slot = this.skeleton.drawOrder[i]; + 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 instanceof spine.RegionAttachment)) { + slotContainer.visible = false; + continue; + } - var x = slot.bone.worldX + slot.attachment.x * slot.bone.m00 + slot.attachment.y * slot.bone.m01 + slot.attachment.width * 0.5; - var y = slot.bone.worldY + slot.attachment.x * slot.bone.m10 + slot.attachment.y * slot.bone.m11 + slot.attachment.height * 0.5; - //console.log(x + ' : ' + y); - - - //console.log(slot.attachment.name) - if(slot.cacheName != slot.attachment.name) - { - var attachmentName = slot.attachment.name; - - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; + if (attachment.rendererObject) { + if (!slot.currentSpriteName || slot.currentSpriteName != attachment.name) { + var spriteName = attachment.rendererObject.name; + if (slot.currentSprite !== undefined) { + slot.currentSprite.visible = false; } - - this.sprites[i].setTexture(PIXI.TextureCache[attachmentName]); - - slot.cacheName = slot.attachment.name; + slot.sprites = slot.sprites || {}; + if (slot.sprites[spriteName] !== undefined) { + slot.sprites[spriteName].visible = true; + } else { + var sprite = this.createSprite(slot, attachment.rendererObject); + slotContainer.addChild(sprite); + } + slot.currentSprite = slot.sprites[spriteName]; + slot.currentSpriteName = spriteName; } - - x += -((slot.attachment.width * (slot.bone.worldScaleX + slot.attachment.scaleX - 1))>>1); - y += -((slot.attachment.height * (slot.bone.worldScaleY + slot.attachment.scaleY - 1))>>1); - - - this.sprites[i].position.x = x; - this.sprites[i].position.y = y; - this.sprites[i].rotation = (-(slot.bone.worldRotation + slot.attachment.rotation)) * (Math.PI/180); - } - + } + slotContainer.visible = true; + + 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 * Math.PI / 180); + } + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -} +}; + + +PIXI.Spine.prototype.createSprite = function (slot, descriptor) { + var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; + var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); + sprite.scale = descriptor.scale; + sprite.rotation = descriptor.rotation; + sprite.anchor.x = sprite.anchor.y = 0.5; + + slot.sprites = slot.sprites || {}; + slot.sprites[descriptor.name] = sprite; + return sprite; +}; /* * Awesome JS run time provided by EsotericSoftware - * + * * https://github.com/EsotericSoftware/spine-runtimes - * + * */ var spine = {}; @@ -7770,7 +7945,7 @@ spine.Slot.prototype = { this.g = data.g; this.b = data.b; this.a = data.a; - + var slotDatas = this.skeleton.data.slots; for (var i = 0, n = slotDatas.length; i < n; i++) { if (slotDatas[i] == data) { @@ -8001,6 +8176,7 @@ spine.TranslateTimeline.prototype = { var frameTime = frames[frameIndex]; var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); + bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; } @@ -8025,14 +8201,12 @@ spine.ScaleTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. - + var bone = skeleton.bones[this.boneIndex]; if (time >= frames[frames.length - 3]) { // Time is after last frame. bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - - return; } @@ -8070,6 +8244,7 @@ spine.ColorTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. + var slot = skeleton.slots[this.slotIndex]; if (time >= frames[frames.length - 5]) { // Time is after last frame. @@ -8119,7 +8294,7 @@ spine.AttachmentTimeline = function (frameCount) { spine.AttachmentTimeline.prototype = { slotIndex: 0, getFrameCount: function () { - return this.frames.length / 2; + return this.frames.length; }, setFrame: function (frameIndex, time, attachmentName) { this.frames[frameIndex] = time; @@ -8136,11 +8311,6 @@ spine.AttachmentTimeline.prototype = { frameIndex = spine.binarySearch(frames, time, 1) - 1; var attachmentName = this.attachmentNames[frameIndex]; - //console.log(skeleton.slots[this.slotIndex]) - - // change the name! - // skeleton.slots[this.slotIndex].attachmentName = attachmentName; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); } }; @@ -8312,11 +8482,9 @@ spine.Skeleton.prototype = { if (slot.data.name == slotName) { var attachment = null; if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; } - slot.setAttachment(attachment); return; } @@ -8398,7 +8566,6 @@ spine.RegionAttachment.prototype = { offset[7/*Y4*/] = localYCos + localX2Sin; }, computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; y += bone.worldY; var m00 = bone.m00; @@ -8422,6 +8589,7 @@ spine.AnimationStateData = function (skeletonData) { this.animationToMixTime = {}; }; spine.AnimationStateData.prototype = { + defaultMix: 0, setMixByName: function (fromName, toName, duration) { var from = this.skeletonData.findAnimation(fromName); if (!from) throw "Animation not found: " + fromName; @@ -8434,7 +8602,7 @@ spine.AnimationStateData.prototype = { }, getMix: function (from, to) { var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : 0; + return time ? time : this.defaultMix; } }; @@ -8474,7 +8642,7 @@ spine.AnimationState.prototype = { this.previous = null; } this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else + } else this.current.apply(skeleton, this.currentTime, this.currentLoop); }, clearAnimation: function () { @@ -8620,16 +8788,9 @@ spine.SkeletonJson.prototype = { name = map["name"] || name; var type = spine.AttachmentType[map["type"] || "region"]; - - // @ekelokorpi - // var attachment = this.attachmentLoader.newAttachment(skin, type, name); - var attachment = new spine.RegionAttachment(); - - // @Doormat23 - // add the name of the attachment - attachment.name = name; - + if (type == spine.AttachmentType.region) { + var attachment = new spine.RegionAttachment(); attachment.x = (map["x"] || 0) * this.scale; attachment.y = (map["y"] || 0) * this.scale; attachment.scaleX = map["scaleX"] || 1; @@ -8638,10 +8799,19 @@ spine.SkeletonJson.prototype = { attachment.width = (map["width"] || 32) * this.scale; attachment.height = (map["height"] || 32) * this.scale; attachment.updateOffset(); + + attachment.rendererObject = {}; + attachment.rendererObject.name = name; + attachment.rendererObject.scale = {}; + attachment.rendererObject.scale.x = attachment.scaleX; + attachment.rendererObject.scale.y = attachment.scaleY; + attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; + return attachment; } - return attachment; + throw "Unknown attachment type: " + type; }, + readAnimation: function (name, map, skeletonData) { var timelines = []; var duration = 0; @@ -8692,7 +8862,7 @@ spine.SkeletonJson.prototype = { } timelines.push(timeline); duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - + } else throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; } @@ -8735,8 +8905,8 @@ spine.SkeletonJson.prototype = { timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); } timelines.push(timeline); - // PIXI FIX - duration = Math.max(duration, timeline.frames[Math.floor(timeline.getFrameCount()) - 1]); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } else throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; } @@ -9005,14 +9175,14 @@ spine.Bone.yDown = true; /** * This object is one that will allow you to specify custom rendering functions based on render type * - * @class CustomRenderable + * @class CustomRenderable * @extends DisplayObject * @constructor */ PIXI.CustomRenderable = function() { PIXI.DisplayObject.call( this ); - + } // constructor @@ -9118,19 +9288,19 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } else { - + var scope = this; this.source.onload = function(){ - + scope.hasLoaded = true; scope.width = scope.source.width; scope.height = scope.source.height; - + // add it to somewhere... PIXI.texturesToUpdate.push(scope); scope.dispatchEvent( { type: 'loaded', content: scope } ); @@ -9143,7 +9313,7 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } @@ -9183,7 +9353,7 @@ PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) { // new Image() breaks tex loading in some versions of Chrome. // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); + var image = new Image();//document.createElement('img'); if (crossorigin) { image.crossOrigin = ''; @@ -9211,7 +9381,7 @@ PIXI.FrameCache = {}; * @uses EventTarget * @constructor * @param baseTexture {BaseTexture} The base texture source to create the texture from - * @param frmae {Rectangle} The rectangle frame of the texture to show + * @param frame {Rectangle} The rectangle frame of the texture to show */ PIXI.Texture = function(baseTexture, frame) { @@ -9256,7 +9426,7 @@ PIXI.Texture = function(baseTexture, frame) { if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); //console.log(frame) - + this.setFrame(frame); } else @@ -9335,13 +9505,13 @@ PIXI.Texture.prototype.setFrame = function(frame) PIXI.Texture.fromImage = function(imageUrl, crossorigin) { var texture = PIXI.TextureCache[imageUrl]; - + if(!texture) { texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); PIXI.TextureCache[imageUrl] = texture; } - + return texture; } @@ -9391,7 +9561,7 @@ PIXI.Texture.addTextureToCache = function(texture, id) } /** - * Remove a texture from the textureCache. + * Remove a texture from the textureCache. * * @static * @method removeTextureFromCache @@ -9503,15 +9673,7 @@ PIXI.RenderTexture.prototype.initWebGL = function() // create a projection matrix.. this.projection = new PIXI.Point(this.width/2 , this.height/2); -/* - this.projectionMatrix = PIXI.mat4.create(); - this.projectionMatrix[5] = 2/this.height// * 0.5; - this.projectionMatrix[13] = -1; - - this.projectionMatrix[0] = 2/this.width; - this.projectionMatrix[12] = -1; -*/ // set the correct render function.. this.render = this.renderWebGL; @@ -9525,10 +9687,6 @@ PIXI.RenderTexture.prototype.resize = function(width, height) this.width = width; this.height = height; - //this.frame.width = this.width - //this.frame.height = this.height; - - if(PIXI.gl) { this.projection.x = this.width/2 @@ -9592,6 +9750,7 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle var children = displayObject.children; //TODO -? create a new one??? dont think so! + var originalWorldTransform = displayObject.worldTransform; displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; // modify to flip... displayObject.worldTransform[4] = -1; @@ -9604,8 +9763,9 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle displayObject.worldTransform[5] -= position.y; } - - + PIXI.visibleCount++; + displayObject.vcount = PIXI.visibleCount; + for(var i=0,j=children.length; i- format + */ +PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) +{ + this.frames = []; + var cols = Math.floor(this.texture.width / frameWidth); + var rows = Math.floor(this.texture.height / frameHeight); + + var i=0; + for (var y=0; y x1 && x < x1 + this.width) + if(x >= x1 && x <= x1 + this.width) { var y1 = this.y; - - if(y > y1 && y < y1 + this.height) + + if(y >= y1 && y <= y1 + this.height) { return true; } @@ -165,7 +165,7 @@ PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; * @class Polygon * @constructor * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, - * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arugments passed can be + * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are * Numbers. @@ -232,9 +232,9 @@ PIXI.Polygon.prototype.contains = function(x, y) return inside; } +// constructor PIXI.Polygon.prototype.constructor = PIXI.Polygon; - /** * @author Chad Engler */ @@ -256,7 +256,7 @@ PIXI.Circle = function(x, y, radius) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number @@ -306,6 +306,7 @@ PIXI.Circle.prototype.contains = function(x, y) return (dx + dy <= r2); } +// constructor PIXI.Circle.prototype.constructor = PIXI.Circle; @@ -320,8 +321,8 @@ PIXI.Circle.prototype.constructor = PIXI.Circle; * @constructor * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse - * @param width {Number} The overall height of this ellipse - * @param height {Number} The overall width of this ellipse + * @param width {Number} The overall width of this ellipse + * @param height {Number} The overall height of this ellipse */ PIXI.Ellipse = function(x, y, width, height) { @@ -331,21 +332,21 @@ PIXI.Ellipse = function(x, y, width, height) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number * @default 0 */ this.y = y || 0; - + /** * @property width * @type Number * @default 0 */ this.width = width || 0; - + /** * @property height * @type Number @@ -394,11 +395,11 @@ PIXI.Ellipse.getBounds = function() return new PIXI.Rectangle(this.x, this.y, this.width, this.height); } +// constructor PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; - /* * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV * you both rock! @@ -426,7 +427,7 @@ PIXI.mat3.create = function() matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -442,7 +443,7 @@ PIXI.mat3.identity = function(matrix) matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -469,35 +470,35 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat3.multiply = function (mat, mat2, dest) +PIXI.mat3.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[0], a01 = mat[1], a02 = mat[2], a10 = mat[3], a11 = mat[4], a12 = mat[5], a20 = mat[6], a21 = mat[7], a22 = mat[8], - + b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; - + dest[0] = b00 * a00 + b01 * a10 + b02 * a20; dest[1] = b00 * a01 + b01 * a11 + b02 * a21; dest[2] = b00 * a02 + b01 * a12 + b02 * a22; - + dest[3] = b10 * a00 + b11 * a10 + b12 * a20; dest[4] = b10 * a01 + b11 * a11 + b12 * a21; dest[5] = b10 * a02 + b11 * a12 + b12 * a22; - + dest[6] = b20 * a00 + b21 * a10 + b22 * a20; dest[7] = b20 * a01 + b21 * a11 + b22 * a21; dest[8] = b20 * a02 + b21 * a12 + b22 * a22; - + return dest; } @@ -514,11 +515,11 @@ PIXI.mat3.clone = function(mat) matrix[6] = mat[6]; matrix[7] = mat[7]; matrix[8] = mat[8]; - + return matrix; } -PIXI.mat3.transpose = function (mat, dest) +PIXI.mat3.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values if (!dest || mat === dest) { @@ -546,30 +547,30 @@ PIXI.mat3.transpose = function (mat, dest) return dest; } -PIXI.mat3.toMat4 = function (mat, dest) +PIXI.mat3.toMat4 = function (mat, dest) { if (!dest) { dest = PIXI.mat4.create(); } - + dest[15] = 1; dest[14] = 0; dest[13] = 0; dest[12] = 0; - + dest[11] = 0; dest[10] = mat[8]; dest[9] = mat[7]; dest[8] = mat[6]; - + dest[7] = 0; dest[6] = mat[5]; dest[5] = mat[4]; dest[4] = mat[3]; - + dest[3] = 0; dest[2] = mat[2]; dest[1] = mat[1]; dest[0] = mat[0]; - + return dest; } @@ -597,19 +598,19 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat4.transpose = function (mat, dest) +PIXI.mat4.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) + if (!dest || mat === dest) { var a01 = mat[1], a02 = mat[2], a03 = mat[3], a12 = mat[6], a13 = mat[7], a23 = mat[11]; - + mat[1] = mat[4]; mat[2] = mat[8]; mat[3] = mat[12]; @@ -624,7 +625,7 @@ PIXI.mat4.transpose = function (mat, dest) mat[14] = a23; return mat; } - + dest[0] = mat[0]; dest[1] = mat[4]; dest[2] = mat[8]; @@ -644,18 +645,18 @@ PIXI.mat4.transpose = function (mat, dest) return dest; } -PIXI.mat4.multiply = function (mat, mat2, dest) +PIXI.mat4.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - + // Cache only the current line of the second matrix - var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; + var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; @@ -705,7 +706,6 @@ PIXI.DisplayObject = function() { this.last = this; this.first = this; - /** * The coordinate of the object relative to the local coordinates of the parent. * @@ -779,15 +779,6 @@ PIXI.DisplayObject = function() */ this.renderable = false; - /** - * [read-only] The visibility of the object based on world (parent) factors. - * - * @property worldVisible - * @type Boolean - * @readOnly - */ - this.worldVisible = false; - /** * [read-only] The display object container that contains this display object. * @@ -806,15 +797,6 @@ PIXI.DisplayObject = function() */ this.stage = null; - /** - * [read-only] The index of this object in the parent's `children` array - * - * @property childIndex - * @type Number - * @readOnly - */ - this.childIndex = 0; - /** * [read-only] The multiplied alpha of the displayobject * @@ -953,17 +935,6 @@ PIXI.DisplayObject = function() // constructor PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObject.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - } -});*/ - /** * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default * Instead of using this function you can now simply set the interactive property to true or false @@ -1011,16 +982,57 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { }, set: function(value) { - this._mask = value; - + if(value) { + if(this._mask) + { + value.start = this._mask.start; + value.end = this._mask.end; + } + else + { + this.addFilter(value); + value.renderable = false; + } + } + else + { + this.removeFilter(this._mask); + this._mask.renderable = true; + } + + this._mask = value; + } +}); + +/** + * Sets the filters for the displayObject. Currently there's a few limitations. + * 1: At the moment only one filter can be applied at a time.. + * 2: They cannot be nested. + * 3: There's no padding yet. + * 4: this is a webGL only feature. + * @property filters + * @type Array + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { + get: function() { + return this._filters; + }, + set: function(value) { + + //if(value == ) + if(value) + { + if(this._filters)this.removeFilter(this._filters); this.addFilter(value) } else { - this.removeFilter(); + if(this._filters)this.removeFilter(this._filters); } + + this._filters = value; } }); @@ -1031,19 +1043,21 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { * @param mask {Graphics} the graphics object to use as a filter * @private */ -PIXI.DisplayObject.prototype.addFilter = function(mask) +PIXI.DisplayObject.prototype.addFilter = function(data) { - if(this.filter)return; - this.filter = true; - + //if(this.filter)return; + //this.filter = true; // insert a filter block.. + // TODO Onject pool thease bad boys.. var start = new PIXI.FilterBlock(); var end = new PIXI.FilterBlock(); + data.start = start; + data.end = end; - start.mask = mask; - end.mask = mask; + start.data = data; + end.data = data; start.first = start.last = this; end.first = end.last = this; @@ -1051,9 +1065,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) start.open = true; /* - * * insert start - * */ var childFirst = start @@ -1084,9 +1096,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) // now insert the end filter block.. /* - * * insert end filter - * */ var childFirst = end var childLast = end @@ -1125,8 +1135,6 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) this.__renderGroup.addFilterBlocks(start, end); } - mask.renderable = false; - } /* @@ -1135,13 +1143,14 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) * @method removeFilter * @private */ -PIXI.DisplayObject.prototype.removeFilter = function() +PIXI.DisplayObject.prototype.removeFilter = function(data) { - if(!this.filter)return; - this.filter = false; - + //if(!this.filter)return; + //this.filter = false; + console.log("YUOIO") // modify the list.. - var startBlock = this.first; + var startBlock = data.start; + var nextObject = startBlock._iNext; var previousObject = startBlock._iPrev; @@ -1151,9 +1160,8 @@ PIXI.DisplayObject.prototype.removeFilter = function() this.first = startBlock._iNext; - // remove the end filter - var lastBlock = this.last; + var lastBlock = data.end; var nextObject = lastBlock._iNext; var previousObject = lastBlock._iPrev; @@ -1162,8 +1170,6 @@ PIXI.DisplayObject.prototype.removeFilter = function() previousObject._iNext = nextObject; // this is always true too! -// if(this.last == lastBlock) - //{ var tempLast = lastBlock._iPrev; // need to make sure the parents last is updated too var updateLast = this; @@ -1174,15 +1180,11 @@ PIXI.DisplayObject.prototype.removeFilter = function() if(!updateLast)break; } - var mask = startBlock.mask - mask.renderable = true; - // if webGL... if(this.__renderGroup) { this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); } - //} } /* @@ -1194,7 +1196,7 @@ PIXI.DisplayObject.prototype.removeFilter = function() PIXI.DisplayObject.prototype.updateTransform = function() { // TODO OPTIMIZE THIS!! with dirty - if(this.rotation != this.rotationCache) + if(this.rotation !== this.rotationCache) { this.rotationCache = this.rotation; this._sr = Math.sin(this.rotation); @@ -1236,9 +1238,12 @@ PIXI.DisplayObject.prototype.updateTransform = function() // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); this.worldAlpha = this.alpha * this.parent.worldAlpha; + + this.vcount = PIXI.visibleCount; } +PIXI.visibleCount = 0; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1270,18 +1275,6 @@ PIXI.DisplayObjectContainer = function() PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObjectContainer.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - - } -});*/ - /** * Adds a child to the container. * @@ -1299,11 +1292,10 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) } child.parent = this; - child.childIndex = this.children.length; this.children.push(child); - // updae the stage refference.. + // update the stage refference.. if(this.stage) { @@ -1326,7 +1318,7 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) var previousObject; // this could be wrong if there is a filter?? - if(this.filter) + if(this._filters) { previousObject = this.last._iPrev; } @@ -1338,7 +1330,6 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) nextObject = previousObject._iNext; // always true in this case - //this.last = child.last; // need to make sure the parents last is updated too var updateLast = this; var prevLast = previousObject; @@ -1402,7 +1393,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) } // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject; var previousObject; @@ -1410,7 +1401,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) if(index == this.children.length) { previousObject = this.last; - var updateLast = this;//.parent; + var updateLast = this; var prevLast = this.last; while(updateLast) { @@ -1539,7 +1530,7 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child) { // unlink // // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject = childLast._iNext; @@ -1609,7 +1600,6 @@ PIXI.DisplayObjectContainer.prototype.updateTransform = function() this.children[i].updateTransform(); } } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1739,9 +1729,18 @@ PIXI.Sprite.prototype.setTexture = function(texture) if(this.texture.baseTexture != texture.baseTexture) { this.textureChange = true; + this.texture = texture; + + if(this.__renderGroup) + { + this.__renderGroup.updateTexture(this); + } + } + else + { + this.texture = texture; } - this.texture = texture; this.updateFrame = true; } @@ -1798,7 +1797,6 @@ PIXI.Sprite.fromImage = function(imageId) return new PIXI.Sprite(texture); } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1814,7 +1812,7 @@ PIXI.Sprite.fromImage = function(imageId) PIXI.MovieClip = function(textures) { PIXI.Sprite.call(this, textures[0]); - + /** * The array of textures that make up the animation * @@ -1822,7 +1820,7 @@ PIXI.MovieClip = function(textures) * @type Array */ this.textures = textures; - + /** * The speed that the MovieClip will play at. Higher is faster, lower is slower * @@ -1848,7 +1846,7 @@ PIXI.MovieClip = function(textures) * @type Function */ this.onComplete = null; - + /** * [read-only] The index MovieClips current frame (this may not have to be a whole number) * @@ -1857,8 +1855,8 @@ PIXI.MovieClip = function(textures) * @default 0 * @readOnly */ - this.currentFrame = 0; - + this.currentFrame = 0; + /** * [read-only] Indicates if the MovieClip is currently playing * @@ -1873,6 +1871,23 @@ PIXI.MovieClip = function(textures) PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; +/** +* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures +* assigned to the MovieClip. +* +* @property totalFrames +* @type Number +* @default 0 +* @readOnly +*/ +Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { + get: function() { + + return this.textures.length; + } +}); + + /** * Stops the MovieClip * @@ -1928,11 +1943,13 @@ PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) PIXI.MovieClip.prototype.updateTransform = function() { PIXI.Sprite.prototype.updateTransform.call(this); - + if(!this.playing)return; - + this.currentFrame += this.animationSpeed; + var round = (this.currentFrame + 0.5) | 0; + if(this.loop || round < this.textures.length) { this.setTexture(this.textures[round % this.textures.length]); @@ -1952,14 +1969,49 @@ PIXI.MovieClip.prototype.updateTransform = function() -PIXI.FilterBlock = function(mask) +PIXI.FilterBlock = function() { - this.graphics = mask this.visible = true; this.renderable = true; } +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.ColorMatrixFilter = function() +{ + // set the uniforms + this.uniforms = { + matrix: {type: 'mat4', value: [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1]}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float invert;", + "uniform mat4 matrix;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", + "gl_FragColor = gl_FragColor * vColor;", + "}" + ]; + +} +Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { + get: function() { + return this.uniforms.matrix.value; + }, + set: function(value) { + this.uniforms.matrix.value = value; + } +}); /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1988,7 +2040,7 @@ PIXI.Text = function(text, style) this.setText(text); this.setStyle(style); - + this.updateText(); this.dirty = false; }; @@ -2030,7 +2082,7 @@ PIXI.Text.prototype.setStyle = function(style) * @methos setText * @param {String} text The copy that you would like the text to display */ -PIXI.Sprite.prototype.setText = function(text) +PIXI.Text.prototype.setText = function(text) { this.text = text.toString() || " "; this.dirty = true; @@ -2045,9 +2097,9 @@ PIXI.Sprite.prototype.setText = function(text) PIXI.Text.prototype.updateText = function() { this.context.font = this.style.font; - + var outputText = this.text; - + // word wrap // preserve original text if(this.style.wordWrap)outputText = this.wordWrap(this.text); @@ -2065,7 +2117,7 @@ PIXI.Text.prototype.updateText = function() maxLineWidth = Math.max(maxLineWidth, lineWidth); } this.canvas.width = maxLineWidth + this.style.strokeThickness; - + //calculate text height var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; this.canvas.height = lineHeight * lines.length; @@ -2073,7 +2125,7 @@ PIXI.Text.prototype.updateText = function() //set canvas text styles this.context.fillStyle = this.style.fill; this.context.font = this.style.font; - + this.context.strokeStyle = this.style.stroke; this.context.lineWidth = this.style.strokeThickness; @@ -2083,7 +2135,7 @@ PIXI.Text.prototype.updateText = function() for (i = 0; i < lines.length; i++) { var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); - + if(this.style.align == "right") { linePosition.x += maxLineWidth - lineWidths[i]; @@ -2103,7 +2155,7 @@ PIXI.Text.prototype.updateText = function() this.context.fillText(lines[i], linePosition.x, linePosition.y); } } - + this.updateTexture(); }; @@ -2119,10 +2171,10 @@ PIXI.Text.prototype.updateTexture = function() this.texture.baseTexture.height = this.canvas.height; this.texture.frame.width = this.canvas.width; this.texture.frame.height = this.canvas.height; - + this._width = this.canvas.width; this._height = this.canvas.height; - + PIXI.texturesToUpdate.push(this.texture.baseTexture); }; @@ -2136,10 +2188,10 @@ PIXI.Text.prototype.updateTransform = function() { if(this.dirty) { - this.updateText(); + this.updateText(); this.dirty = false; } - + PIXI.Sprite.prototype.updateTransform.call(this); }; @@ -2151,12 +2203,12 @@ PIXI.Text.prototype.updateTransform = function() * @param fontStyle {Object} * @private */ -PIXI.Text.prototype.determineFontHeight = function(fontStyle) +PIXI.Text.prototype.determineFontHeight = function(fontStyle) { // build a little reference dictionary so if the font style has been used return a // cached version... var result = PIXI.Text.heightCache[fontStyle]; - + if(!result) { var body = document.getElementsByTagName("body")[0]; @@ -2165,13 +2217,13 @@ PIXI.Text.prototype.determineFontHeight = function(fontStyle) dummy.appendChild(dummyText); dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); body.appendChild(dummy); - + result = dummy.offsetHeight; PIXI.Text.heightCache[fontStyle] = result; - + body.removeChild(dummy); } - + return result; }; @@ -2191,7 +2243,7 @@ PIXI.Text.prototype.wordWrap = function(text) if(p == start) { return 1; } - + if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) { if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) @@ -2208,7 +2260,7 @@ PIXI.Text.prototype.wordWrap = function(text) return arguments.callee(ctx, text, start, p, wrapWidth); } }; - + var lineWrap = function(ctx, text, wrapWidth) { if(ctx.measureText(text).width <= wrapWidth || text.length < 1) @@ -2218,14 +2270,14 @@ PIXI.Text.prototype.wordWrap = function(text) var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); }; - + var result = ""; var lines = text.split("\n"); for (var i = 0; i < lines.length; i++) { result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; } - + return result; }; @@ -2241,7 +2293,7 @@ PIXI.Text.prototype.destroy = function(destroyTexture) { this.texture.destroy(); } - + }; PIXI.Text.heightCache = {}; @@ -2252,7 +2304,7 @@ PIXI.Text.heightCache = {}; /** * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" - * You can generate the fnt files using + * You can generate the fnt files using * http://www.angelcode.com/products/bmfont/ for windows or * http://www.bmglyph.com/ for mac. * @@ -2342,7 +2394,7 @@ PIXI.BitmapText.prototype.updateText = function() prevCharCode = null; continue; } - + var charData = data.chars[charCode]; if(!charData) continue; @@ -2405,7 +2457,7 @@ PIXI.BitmapText.prototype.updateTransform = function() this.dirty = false; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); }; @@ -2414,10 +2466,8 @@ PIXI.BitmapText.fonts = {}; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ - - - -/** + + /** * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive * This manager also supports multitouch. * @@ -2451,6 +2501,8 @@ PIXI.InteractionManager = function(stage) */ this.touchs = {}; + + // helpers this.tempPoint = new PIXI.Point(); //this.tempMatrix = mat3.create(); @@ -2461,7 +2513,19 @@ PIXI.InteractionManager = function(stage) this.pool = []; this.interactiveItems = []; + this.interactionDOMElement = null; + //this will make it so that you dont have to call bind all the time + this.onMouseMove = this.onMouseMove.bind( this ); + this.onMouseDown = this.onMouseDown.bind(this); + this.onMouseOut = this.onMouseOut.bind(this); + this.onMouseUp = this.onMouseUp.bind(this); + + this.onTouchStart = this.onTouchStart.bind(this); + this.onTouchEnd = this.onTouchEnd.bind(this); + this.onTouchMove = this.onTouchMove.bind(this); + + this.last = 0; } @@ -2486,7 +2550,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj { var child = children[i]; - if(child.visible) { +// if(child.visible) { // push all interactive bits if(child.interactive) { @@ -2508,7 +2572,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj this.collectInteractiveSprite(child, iParent); } } - } +// } } } @@ -2521,27 +2585,68 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj */ PIXI.InteractionManager.prototype.setTarget = function(target) { + this.target = target; + + //check if the dom element has been set. If it has don't do anything + if( this.interactionDOMElement === null ) { + + this.setTargetDomElement( target.view ); + } + + document.body.addEventListener('mouseup', this.onMouseUp, true); +} + + +/** + * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM + * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element + * to receive those events + * + * @method setTargetDomElement + * @param domElement {DOMElement} the dom element which will receive mouse and touch events + * @private + */ +PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) +{ + //remove previouse listeners + if( this.interactionDOMElement !== null ) + { + this.interactionDOMElement.style['-ms-content-zooming'] = ''; + this.interactionDOMElement.style['-ms-touch-action'] = ''; + + this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); + this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); + this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); + this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); + this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); + } + + if (window.navigator.msPointerEnabled) { // time to remove some of that zoom in ja.. - target.view.style["-ms-content-zooming"] = "none"; - target.view.style["-ms-touch-action"] = "none" + domElement.style['-ms-content-zooming'] = 'none'; + domElement.style['-ms-touch-action'] = 'none'; // DO some window specific touch! } - - this.target = target; - target.view.addEventListener('mousemove', this.onMouseMove.bind(this), true); - target.view.addEventListener('mousedown', this.onMouseDown.bind(this), true); - document.body.addEventListener('mouseup', this.onMouseUp.bind(this), true); - target.view.addEventListener('mouseout', this.onMouseUp.bind(this), true); - - // aint no multi touch just yet! - target.view.addEventListener("touchstart", this.onTouchStart.bind(this), true); - target.view.addEventListener("touchend", this.onTouchEnd.bind(this), true); - target.view.addEventListener("touchmove", this.onTouchMove.bind(this), true); + + this.interactionDOMElement = domElement; + + domElement.addEventListener('mousemove', this.onMouseMove, true); + domElement.addEventListener('mousedown', this.onMouseDown, true); + domElement.addEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + domElement.addEventListener('touchstart', this.onTouchStart, true); + domElement.addEventListener('touchend', this.onTouchEnd, true); + domElement.addEventListener('touchmove', this.onTouchMove, true); } + /** * updates the state of interactive objects * @@ -2583,12 +2688,14 @@ PIXI.InteractionManager.prototype.update = function() // loop through interactive objects! var length = this.interactiveItems.length; - this.target.view.style.cursor = "default"; + this.interactionDOMElement.style.cursor = "default"; for (var i = 0; i < length; i++) { var item = this.interactiveItems[i]; - if(!item.visible)continue; + + + //if(!item.visible)continue; // OPTIMISATION - only calculate every time if the mousemove function exists.. // OK so.. does the object have any other interactive functions? @@ -2604,7 +2711,7 @@ PIXI.InteractionManager.prototype.update = function() // loks like there was a hit! if(item.__hit) { - if(item.buttonMode)this.target.view.style.cursor = "pointer"; + if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; if(!item.__isOver) { @@ -2639,7 +2746,7 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) { this.mouse.originalEvent = event || window.event; //IE uses window.event // TODO optimize by not check EVERY TIME! maybe half as often? // - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); @@ -2669,7 +2776,6 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) */ PIXI.InteractionManager.prototype.onMouseDown = function(event) { - event.preventDefault(); this.mouse.originalEvent = event || window.event; //IE uses window.event // loop through inteaction tree... @@ -2706,6 +2812,26 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) } } + +PIXI.InteractionManager.prototype.onMouseOut = function(event) +{ + var length = this.interactiveItems.length; + + this.interactionDOMElement.style.cursor = "default"; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.__isOver) + { + this.mouse.target = item; + if(item.mouseout)item.mouseout(this.mouse); + item.__isOver = false; + } + } +} + /** * Is called when the mouse button is released on the renderer element * @@ -2770,7 +2896,7 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) { var global = interactionData.global; - if(!item.visible)return false; + if(item.vcount !== PIXI.visibleCount)return false; var isSprite = (item instanceof PIXI.Sprite), worldTransform = item.worldTransform, @@ -2840,14 +2966,14 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) */ PIXI.InteractionManager.prototype.onTouchMove = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) { var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; + touchData.originalEvent = event || window.event; // update the touch position touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); @@ -2871,10 +2997,7 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) */ PIXI.InteractionManager.prototype.onTouchStart = function(event) { - event.preventDefault(); - this.mouse.originalEvent = event || window.event; //IE uses window.event - - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2884,6 +3007,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) var touchData = this.pool.pop(); if(!touchData)touchData = new PIXI.InteractionData(); + touchData.originalEvent = event || window.event; + this.touchs[touchEvent.identifier] = touchData; touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); @@ -2921,8 +3046,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) */ PIXI.InteractionManager.prototype.onTouchEnd = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + //this.mouse.originalEvent = event || window.event; //IE uses window.event + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2943,7 +3068,7 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) if(itemTouchData == touchData) { // so this one WAS down... - + touchData.originalEvent = event || window.event; // hitTest?? if(item.touchend || item.tap) @@ -3055,9 +3180,8 @@ PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; * @constructor * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format * like: 0xFFFFFF for white - * @param interactive {Boolean} enable / disable interaction (default is false) */ -PIXI.Stage = function(backgroundColor, interactive) +PIXI.Stage = function(backgroundColor) { PIXI.DisplayObjectContainer.call( this ); @@ -3077,7 +3201,7 @@ PIXI.Stage = function(backgroundColor, interactive) * @property interactive * @type Boolean */ - this.interactive = interactive; + this.interactive = true; /** * The interaction manage for this stage, manages all interactive activity on the stage @@ -3113,6 +3237,18 @@ PIXI.Stage = function(backgroundColor, interactive) PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); PIXI.Stage.prototype.constructor = PIXI.Stage; +/** + * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. + * This is useful for when you have other DOM elements ontop of the Canvas element. + * + * @method setInteractionDelegate + * @param domElement {DOMElement} This new domElement which will receive mouse/touch events + */ +PIXI.Stage.prototype.setInteractionDelegate = function(domElement) +{ + this.interactionManager.setTargetDomElement( domElement ); +} + /* * Updates the object transform for rendering * @@ -3122,6 +3258,7 @@ PIXI.Stage.prototype.constructor = PIXI.Stage; PIXI.Stage.prototype.updateTransform = function() { this.worldAlpha = 1; + this.vcount = PIXI.visibleCount; for(var i=0,j=this.children.length; i 100) { console.log("BREAK") break } - } + } } @@ -3361,14 +3466,14 @@ PIXI.runList = function(item) PIXI.EventTarget = function () { var listeners = {}; - + this.addEventListener = this.on = function ( type, listener ) { - - + + if ( listeners[ type ] === undefined ) { listeners[ type ] = []; - + } if ( listeners[ type ].indexOf( listener ) === - 1 ) { @@ -3379,11 +3484,17 @@ PIXI.EventTarget = function () { }; this.dispatchEvent = this.emit = function ( event ) { - - for ( var listener in listeners[ event.type ] ) { - listeners[ event.type ][ listener ]( event ); - + if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { + + return; + + } + + for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { + + listeners[ event.type ][ i ]( event ); + } }; @@ -3417,8 +3528,11 @@ PIXI.EventTarget = function () { * @param height {Number} the height of the renderers view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) + * + * antialias */ -PIXI.autoDetectRenderer = function(width, height, view, transparent) +PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) { if(!width)width = 800; if(!height)height = 600; @@ -3429,7 +3543,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) //console.log(webgl); if( webgl ) { - return new PIXI.WebGLRenderer(width, height, view, transparent); + return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); } return new PIXI.CanvasRenderer(width, height, view, transparent); @@ -3441,7 +3555,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) PolyK library url: http://polyk.ivank.net Released under MIT licence. - + Copyright (c) 2012 Ivan Kuckir Permission is hereby granted, free of charge, to any person @@ -3465,8 +3579,8 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - This is an amazing lib! - + This is an amazing lib! + slightly modified by mat groves (matgroves.com); */ @@ -3482,13 +3596,13 @@ PIXI.PolyK = {}; PIXI.PolyK.Triangulate = function(p) { var sign = true; - + var n = p.length>>1; if(n<3) return []; var tgs = []; var avl = []; for(var i=0; i 3) @@ -3496,11 +3610,11 @@ PIXI.PolyK.Triangulate = function(p) var i0 = avl[(i+0)%al]; var i1 = avl[(i+1)%al]; var i2 = avl[(i+2)%al]; - + var ax = p[2*i0], ay = p[2*i0+1]; var bx = p[2*i1], by = p[2*i1+1]; var cx = p[2*i2], cy = p[2*i2+1]; - + var earFound = false; if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) { @@ -3519,7 +3633,7 @@ PIXI.PolyK.Triangulate = function(p) al--; i = 0; } - else if(i++ > 3*al) + else if(i++ > 3*al) { // need to flip flip reverse it! // reset! @@ -3528,17 +3642,17 @@ PIXI.PolyK.Triangulate = function(p) var tgs = []; avl = []; for(var i=0; i= 0) == sign; } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -3612,13 +3725,11 @@ PIXI.shaderVertexSrc = [ "attribute vec2 aVertexPosition;", "attribute vec2 aTextureCoord;", "attribute float aColor;", - //"uniform mat4 uMVMatrix;", "uniform vec2 projectionVector;", "varying vec2 vTextureCoord;", "varying float vColor;", "void main(void) {", - // "gl_Position = uMVMatrix * vec4(aVertexPosition, 1.0, 1.0);", "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", "vTextureCoord = aTextureCoord;", "vColor = aColor;", @@ -3658,7 +3769,6 @@ PIXI.stripShaderVertexSrc = [ "}" ]; - /* * primitive shader.. */ @@ -3685,6 +3795,8 @@ PIXI.primitiveShaderVertexSrc = [ "}" ]; +PIXI.shaderStack = []; + PIXI.initPrimitiveShader = function() { var gl = PIXI.gl; @@ -3699,27 +3811,26 @@ PIXI.initPrimitiveShader = function() shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); + + //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(shaderProgram.colorAttribute); +//gl.enableVertexAttribArray(program.textureCoordAttribute); + shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); PIXI.primitiveProgram = shaderProgram; + + } PIXI.initDefaultShader = function() { - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.shaderVertexSrc, PIXI.shaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - // shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.shaderProgram = shaderProgram; + PIXI.defaultShader = new PIXI.PixiShader(); + PIXI.defaultShader.init(); + PIXI.activateShader(PIXI.defaultShader); + /* + PIXI.shaderStack.push(PIXI.defaultShader); + PIXI.current*/ } PIXI.initDefaultStripShader = function() @@ -3736,9 +3847,7 @@ PIXI.initDefaultStripShader = function() shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); PIXI.stripShaderProgram = shaderProgram; @@ -3789,35 +3898,135 @@ PIXI.compileProgram = function(vertexSrc, fragmentSrc) return shaderProgram; } +PIXI.activateShader = function(shader) +{ + PIXI.shaderStack.push(shader); + + //console.log(">>>") + var gl = PIXI.gl; + + var shaderProgram = shader.program; + + // map uniforms.. + gl.useProgram(shaderProgram); + + gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + gl.enableVertexAttribArray(shaderProgram.colorAttribute); + gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); -PIXI.activateDefaultShader = function() + shader.syncUniforms(); + + PIXI.currentShader = shaderProgram; +} + + +PIXI.popShader = function() { var gl = PIXI.gl; - var shaderProgram = PIXI.shaderProgram; + // activate last program.. + var lastProgram = PIXI.shaderStack.pop(); + + var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); + PIXI.currentShader = shaderProgram; } - - PIXI.activatePrimitiveShader = function() { var gl = PIXI.gl; - gl.disableVertexAttribArray(PIXI.shaderProgram.textureCoordAttribute); - gl.disableVertexAttribArray(PIXI.shaderProgram.colorAttribute); - gl.useProgram(PIXI.primitiveProgram); - gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); + gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + + //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); } +PIXI.deactivatePrimitiveShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.currentShader); + + gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.PixiShader = function() +{ + // the webGL program.. + this.program; + + this.fragmentSrc = [ + "precision lowp float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", + "}" + ]; + +} + +PIXI.PixiShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get the default shader bits! + program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); + program.colorAttribute = gl.getAttribLocation(program, "aColor"); + program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); + + program.projectionVector = gl.getUniformLocation(program, "projectionVector"); + program.samplerUniform = gl.getUniformLocation(program, "uSampler"); + + // add those custom shaders! + for (var key in this.uniforms) + { + // get the uniform locations.. + program[key] = gl.getUniformLocation(program, key); + } + + this.program = program; +} + +PIXI.PixiShader.prototype.syncUniforms = function() +{ + var gl = PIXI.gl; + + for (var key in this.uniforms) + { + //var + var type = this.uniforms[key].type; + + // need to grow this! + if(type == "f") + { + gl.uniform1f(this.program[key], this.uniforms[key].value); + } + else if(type == "mat4") + { + gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); + } + } + +} + /** * @author Mat Groves http://matgroves.com/ @Doormat23 @@ -3887,7 +4096,7 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); // WHY DOES THIS LINE NEED TO BE THERE??? - gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // its not even used.. but need to be set or it breaks? // only on pc though.. @@ -3899,8 +4108,10 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); + PIXI.deactivatePrimitiveShader(); + // return to default shader... - PIXI.activateDefaultShader(); +// PIXI.activateShader(PIXI.defaultShader); } /** @@ -4243,7 +4454,7 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) verts.push(px , py); verts.push(r, g, b, alpha); - verts.push(p2x - (px-p2x), p2y - (py - p2y));//, 4); + verts.push(p2x - (px-p2x), p2y - (py - p2y)); verts.push(r, g, b, alpha); } } @@ -4356,9 +4567,10 @@ PIXI.gl; * @param height=0 {Number} the height of the canvas view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) * */ -PIXI.WebGLRenderer = function(width, height, view, transparent) +PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) { // do a catch.. only 1 webGL renderer.. @@ -4382,7 +4594,7 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) { PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { alpha: this.transparent, - antialias:true, // SPEED UP?? + antialias:!!antialias, // SPEED UP?? premultipliedAlpha:false, stencil:true }); @@ -4392,11 +4604,12 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); } - PIXI.initPrimitiveShader(); PIXI.initDefaultShader(); + PIXI.initPrimitiveShader(); PIXI.initDefaultStripShader(); - PIXI.activateDefaultShader(); + +// PIXI.activateDefaultShader(); var gl = this.gl; PIXI.WebGLRenderer.gl = gl; @@ -4413,7 +4626,10 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) this.resize(this.width, this.height); this.contextLost = false; + PIXI.activateShader(PIXI.defaultShader); + this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); + } // constructor @@ -4469,8 +4685,6 @@ PIXI.WebGLRenderer.prototype.render = function(stage) { // TODO make this work // dont think this is needed any more? - //if(this.__stage)this.checkVisibility(this.__stage, false) - this.__stage = stage; this.stageRenderGroup.setRenderable(stage); } @@ -4487,10 +4701,8 @@ PIXI.WebGLRenderer.prototype.render = function(stage) // update any textures PIXI.WebGLRenderer.updateTextures(); - // recursivly loop through all items! - //this.checkVisibility(stage, true); - // update the scene graph + PIXI.visibleCount++; stage.updateTransform(); var gl = this.gl; @@ -4499,16 +4711,12 @@ PIXI.WebGLRenderer.prototype.render = function(stage) gl.colorMask(true, true, true, this.transparent); gl.viewport(0, 0, this.width, this.height); - // set the correct matrix.. - // gl.uniformMatrix4fv(this.shaderProgram.mvMatrixUniform, false, this.projectionMatrix); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); gl.clear(gl.COLOR_BUFFER_BIT); // HACK TO TEST - //PIXI.projectionMatrix = this.projectionMatrix; this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; this.stageRenderGroup.render(PIXI.projection); @@ -4546,8 +4754,9 @@ PIXI.WebGLRenderer.prototype.render = function(stage) */ PIXI.WebGLRenderer.updateTextures = function() { - for (var i=0; i < PIXI.texturesToUpdate.length; i++) this.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) this.destroyTexture(PIXI.texturesToDestroy[i]); + //TODO break this out into a texture manager... + for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); + for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; } @@ -4562,6 +4771,7 @@ PIXI.WebGLRenderer.updateTextures = function() */ PIXI.WebGLRenderer.updateTexture = function(texture) { + //TODO break this out into a texture manager... var gl = PIXI.gl; if(!texture._glTexture) @@ -4602,9 +4812,10 @@ PIXI.WebGLRenderer.updateTexture = function(texture) * @param texture {Texture} The texture to update * @private */ -PIXI.WebGLRenderer.prototype.destroyTexture = function(texture) +PIXI.WebGLRenderer.destroyTexture = function(texture) { - var gl = this.gl; + //TODO break this out into a texture manager... + var gl = PIXI.gl; if(texture._glTexture) { @@ -4768,7 +4979,6 @@ PIXI.WebGLBatch.prototype.clean = function() this.uvs = []; this.indices = []; this.colors = []; - //this.sprites = []; this.dynamicSize = 1; this.texture = null; this.last = null; @@ -4805,7 +5015,6 @@ PIXI.WebGLBatch.prototype.init = function(sprite) this.dirty = true; this.blendMode = sprite.blendMode; this.texture = sprite.texture.baseTexture; -// this.sprites.push(sprite); this.head = sprite; this.tail = sprite; this.size = 1; @@ -4838,7 +5047,6 @@ PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) else { this.head = sprite; - //this.head.__prev = null } } @@ -4926,7 +5134,7 @@ PIXI.WebGLBatch.prototype.split = function(sprite) { this.dirty = true; - var batch = new PIXI.WebGLBatch(this.gl);//PIXI._getBatch(this.gl); + var batch = new PIXI.WebGLBatch(this.gl); batch.init(sprite); batch.texture = this.texture; batch.tail = this.tail; @@ -4936,8 +5144,6 @@ PIXI.WebGLBatch.prototype.split = function(sprite) sprite.__prev = null; // return a splite batch! - //sprite.__prev.__next = null; - //sprite.__prev = null; // TODO this size is wrong! // need to recalculate :/ problem with a linked list! @@ -5007,13 +5213,13 @@ PIXI.WebGLBatch.prototype.growBatch = function() gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); - this.uvs = new Float32Array( this.dynamicSize * 8 ) + this.uvs = new Float32Array( this.dynamicSize * 8 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); this.dirtyUVS = true; - this.colors = new Float32Array( this.dynamicSize * 4 ) + this.colors = new Float32Array( this.dynamicSize * 4 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); @@ -5112,7 +5318,7 @@ PIXI.WebGLBatch.prototype.update = function() while(displayObject) { - if(displayObject.worldVisible) + if(displayObject.vcount === PIXI.visibleCount) { width = displayObject.texture.frame.width; height = displayObject.texture.frame.height; @@ -5214,7 +5420,7 @@ PIXI.WebGLBatch.prototype.update = function() PIXI.WebGLBatch.prototype.render = function(start, end) { start = start || 0; - //end = end || this.size; + if(end == undefined)end = this.size; if(this.dirty) @@ -5230,8 +5436,9 @@ PIXI.WebGLBatch.prototype.render = function(start, end) //TODO optimize this! - var shaderProgram = PIXI.shaderProgram; - gl.useProgram(shaderProgram); + var shaderProgram = PIXI.currentShader; + + //gl.useProgram(shaderProgram); // update the verts.. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); @@ -5239,6 +5446,8 @@ PIXI.WebGLBatch.prototype.render = function(start, end) gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // update the uvs + var isDefault = (shaderProgram == PIXI.shaderProgram) + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); if(this.dirtyUVS) @@ -5262,13 +5471,11 @@ PIXI.WebGLBatch.prototype.render = function(start, end) } gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - //var startIndex = 0//1; var len = end - start; - // console.log(this.size) + // DRAW THAT this! gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); } @@ -5336,77 +5543,45 @@ PIXI.WebGLRenderGroup.prototype.render = function(projection) PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - // TODO remove this by replacing visible with getter setters.. - this.checkVisibility(this.root, this.root.visible); - // will render all the elements in the group var renderable; - - for (var i=0; i < this.batchs.length; i++) { + renderable = this.batchs[i]; if(renderable instanceof PIXI.WebGLBatch) { this.batchs[i].render(); + continue; } - else if(renderable instanceof PIXI.TilingSprite) + + // non sprite batch.. + var worldVisible = renderable.vcount === PIXI.visibleCount; + + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ - if(renderable.open) - { - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - gl.colorMask(true, true, true, false); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - else - { - gl.disable(gl.STENCIL_TEST); - } + this.handleFilterBlock(renderable, projection); } } } -/** - * Renders the stage to its webgl view - * - * @method handleFilter - * @param filter {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.handleFilter = function(filter, projection) -{ - -} - /** * Renders a specific displayObject * @@ -5420,11 +5595,8 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - this.checkVisibility(displayObject, displayObject.visible); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); -// gl.uniformMatrix4fv(PIXI.shaderProgram.mvMatrixUniform, false, projectionMatrix); - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); - // to do! // render part of the scene... @@ -5483,7 +5655,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project while(lastItem.children.length > 0) { lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem; + if(lastItem.renderable)lastRenderable = lastItem.last; } if(lastRenderable instanceof PIXI.Sprite) @@ -5577,45 +5749,80 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project */ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) { + var sta = PIXI.shaderStack.length; + + var worldVisible = renderable.vcount === PIXI.visibleCount + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.CustomRenderable) { - if(renderable.visible) renderable.renderWebGL(this, projection); + if(worldVisible) renderable.renderWebGL(this, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ + this.handleFilterBlock(renderable, projection); + } +} - var gl = PIXI.gl; +PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) +{ + /* + * for now only masks are supported.. + */ + var gl = PIXI.gl; - if(renderable.open) + if(renderable.open) + { + if(renderable.data instanceof Array) + { + var filter = renderable.data[0]; + + if(!filter.shader) + { + var shader = new PIXI.PixiShader(); + + shader.fragmentSrc = filter.fragmentSrc; + shader.uniforms = filter.uniforms; + shader.init(); + + filter.shader = shader + } + + PIXI.activateShader(filter.shader); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } + else { gl.enable(gl.STENCIL_TEST); gl.colorMask(false, false, false, false); gl.stencilFunc(gl.ALWAYS,1,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - // we know this is a render texture so enable alpha too.. + PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); + gl.colorMask(true, true, true, true); gl.stencilFunc(gl.NOTEQUAL,0,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); } + } + else + { + if(renderable.data instanceof Array) + { + PIXI.popShader(); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } else { gl.disable(gl.STENCIL_TEST); @@ -5623,42 +5830,6 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) } } -/** - * Checks the visibility of a displayObject - * - * @method checkVisibility - * @param displayObject {DisplayObject} - * @param globalVisible {Boolean} - * @private - */ -PIXI.WebGLRenderGroup.prototype.checkVisibility = function(displayObject, globalVisible) -{ - // give the dp a reference to its renderGroup... - var children = displayObject.children; - //displayObject.worldVisible = globalVisible; - for (var i=0; i < children.length; i++) - { - var child = children[i]; - - // TODO optimize... should'nt need to loop through everything all the time - child.worldVisible = child.visible && globalVisible; - - // everything should have a batch! - // time to see whats new! - if(child.textureChange) - { - child.textureChange = false; - if(child.worldVisible)this.updateTexture(child); - // update texture!! - } - - if(child.children.length > 0) - { - this.checkVisibility(child, child.worldVisible); - } - }; -} - /** * Updates a webgl texture * @@ -5719,7 +5890,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * It keeps going back until it finds a sprite or the stage */ var previousRenderable = start; - while(previousRenderable != this.root) + while(previousRenderable != this.root.first) { previousRenderable = previousRenderable._iPrev; if(previousRenderable.renderable && previousRenderable.__renderGroup)break; @@ -5733,7 +5904,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * scene graph */ var previousRenderable2 = end; - while(previousRenderable2 != this.root) + while(previousRenderable2 != this.root.first) { previousRenderable2 = previousRenderable2._iPrev; if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; @@ -6105,6 +6276,7 @@ PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) } } + /** * Initializes a tiling sprite * @@ -6175,23 +6347,19 @@ PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) { var gl = this.gl; - var shaderProgram = PIXI.shaderProgram; -// mat - //var mat4Real = PIXI.mat3.toMat4(strip.worldTransform); - //PIXI.mat4.transpose(mat4Real); - //PIXI.mat4.multiply(projectionMatrix, mat4Real, mat4Real ) - + var shaderProgram = PIXI.stripShaderProgram; - gl.useProgram(PIXI.stripShaderProgram); + + gl.useProgram(shaderProgram); var m = PIXI.mat3.clone(strip.worldTransform); PIXI.mat3.transpose(m); // set the matrix transform for the - gl.uniformMatrix3fv(PIXI.stripShaderProgram.translationMatrix, false, m); - gl.uniform2f(PIXI.stripShaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(PIXI.stripShaderProgram.alpha, strip.worldAlpha); + gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); + gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); /* if(strip.blendMode == PIXI.blendModes.NORMAL) @@ -6249,11 +6417,10 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } - //console.log(gl.TRIANGLE_STRIP); gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - gl.useProgram(PIXI.shaderProgram); + gl.useProgram(PIXI.currentProgram); } /** @@ -6328,6 +6495,7 @@ PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } + /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -6401,7 +6569,6 @@ PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; */ PIXI.CanvasRenderer.prototype.render = function(stage) { - // update children if need be //stage.__childrenAdded = []; //stage.__childrenRemoved = []; @@ -6410,6 +6577,7 @@ PIXI.CanvasRenderer.prototype.render = function(stage) PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; + PIXI.visibleCount++; stage.updateTransform(); // update the background color @@ -6496,7 +6664,7 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) var frame = displayObject.texture.frame; - if(frame) + if(frame && frame.width && frame.height) { context.globalAlpha = displayObject.worldAlpha; @@ -6534,31 +6702,34 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) } else if(displayObject instanceof PIXI.FilterBlock) { - if(displayObject.open) + if(PIXI.FilterBlock.data instanceof PIXI.Graphics) { - context.save(); - - var cacheAlpha = displayObject.mask.alpha; - var maskTransform = displayObject.mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - displayObject.mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); - // context.fillStyle = 0xFF0000; - // context.fillRect(0, 0, 200, 200); - context.clip(); - - displayObject.mask.worldAlpha = cacheAlpha; - //context.globalCompositeOperation = 'lighter'; + if(displayObject.open) + { + context.save(); + + var cacheAlpha = displayObject.mask.alpha; + var maskTransform = displayObject.mask.worldTransform; + + context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) + + displayObject.mask.worldAlpha = 0.5; + + context.worldAlpha = 0; + + PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); + context.clip(); + + displayObject.mask.worldAlpha = cacheAlpha; + } + else + { + context.restore(); + } } else { - //context.globalCompositeOperation = 'source-over'; - context.restore(); + // only masks supported right now! } } // count++ @@ -6651,7 +6822,7 @@ PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) PIXI.CanvasRenderer.prototype.renderStrip = function(strip) { var context = this.context; - //context.globalCompositeOperation = 'lighter'; + // draw triangles!! var verticies = strip.verticies; var uvs = strip.uvs; @@ -6678,8 +6849,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.lineTo(x2, y2); context.closePath(); - // context.fillStyle = "white"//rgb(1, 1, 1,1)); - // context.fill(); context.clip(); @@ -6703,7 +6872,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.restore(); }; -// context.globalCompositeOperation = 'source-over'; } /** @@ -6718,7 +6886,7 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) */ PIXI.CanvasGraphics = function() { - + } @@ -6734,35 +6902,33 @@ PIXI.CanvasGraphics = function() PIXI.CanvasGraphics.renderGraphics = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - - for (var i=0; i < graphics.graphicsData.length; i++) + + for (var i=0; i < graphics.graphicsData.length; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); context.lineWidth = data.lineWidth; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); - + context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6777,21 +6943,20 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.RECT) { - - // TODO - need to be Undefined! - if(data.fillColor) + + if(data.fillColor || data.fillColor === 0) { context.globalAlpha = data.fillAlpha * worldAlpha; context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); context.fillRect(points[0], points[1], points[2], points[3]); - + } if(data.lineWidth) { context.globalAlpha = data.lineAlpha * worldAlpha; context.strokeRect(points[0], points[1], points[2], points[3]); } - + } else if(data.type == PIXI.Graphics.CIRC) { @@ -6799,7 +6964,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.beginPath(); context.arc(points[0], points[1], points[2],0,2*Math.PI); context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6814,19 +6979,19 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - + var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6834,15 +6999,15 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - + context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6855,7 +7020,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.stroke(); } } - + }; } @@ -6871,37 +7036,35 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - + var len = graphics.graphicsData.length; if(len > 1) { len = 1; console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") } - - for (var i=0; i < 1; i++) + + for (var i=0; i < 1; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + } else if(data.type == PIXI.Graphics.RECT) { @@ -6918,18 +7081,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6937,7 +7100,7 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); @@ -6945,8 +7108,8 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); context.closePath(); } - - + + }; } @@ -6956,18 +7119,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) /** - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. + * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. * It is important to know that with the webGL renderer only simple polys can be filled at this stage * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png * - * @class Graphics + * @class Graphics * @extends DisplayObjectContainer * @constructor */ PIXI.Graphics = function() { PIXI.DisplayObjectContainer.call( this ); - + this.renderable = true; /** @@ -7028,14 +7191,14 @@ PIXI.Graphics.prototype.constructor = PIXI.Graphics; PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - + this.lineWidth = lineWidth || 0; this.lineColor = color || 0; this.lineAlpha = (alpha == undefined) ? 1 : alpha; - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.graphicsData.push(this.currentPath); } @@ -7049,12 +7212,12 @@ PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) PIXI.Graphics.prototype.moveTo = function(x, y) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.currentPath.points.push(x, y); - + this.graphicsData.push(this.currentPath); } @@ -7084,7 +7247,7 @@ PIXI.Graphics.prototype.beginFill = function(color, alpha) { this.filling = true; this.fillColor = color || 0; - this.fillAlpha = alpha || 1; + this.fillAlpha = (alpha == undefined) ? 1 : alpha; } /** @@ -7110,11 +7273,11 @@ PIXI.Graphics.prototype.endFill = function() PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.RECT}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7130,11 +7293,11 @@ PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) PIXI.Graphics.prototype.drawCircle = function( x, y, radius) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7151,11 +7314,11 @@ PIXI.Graphics.prototype.drawCircle = function( x, y, radius) PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.ELIP}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7169,7 +7332,7 @@ PIXI.Graphics.prototype.clear = function() { this.lineWidth = 0; this.filling = false; - + this.dirty = true; this.clearDirty = true; this.graphicsData = []; @@ -7190,20 +7353,20 @@ PIXI.Strip = function(texture, width, height) PIXI.DisplayObjectContainer.call( this ); this.texture = texture; this.blendMode = PIXI.blendModes.NORMAL; - + try { this.uvs = new Float32Array([0, 1, 1, 1, 1, 0, 0,1]); - + this.verticies = new Float32Array([0, 0, 0,0, 0,0, 0, 0, 0]); - + this.colors = new Float32Array([1, 1, 1, 1]); - + this.indices = new Uint16Array([0, 1, 2, 3]); } catch(error) @@ -7211,18 +7374,18 @@ PIXI.Strip = function(texture, width, height) this.uvs = [0, 1, 1, 1, 1, 0, 0,1]; - + this.verticies = [0, 0, 0,0, 0,0, 0, 0, 0]; - + this.colors = [1, 1, 1, 1]; - + this.indices = [0, 1, 2, 3]; } - - + + /* this.uvs = new Float32Array() this.verticies = new Float32Array() @@ -7231,7 +7394,7 @@ PIXI.Strip = function(texture, width, height) */ this.width = width; this.height = height; - + // load the texture! if(texture.baseTexture.hasLoaded) { @@ -7244,7 +7407,7 @@ PIXI.Strip = function(texture, width, height) this.onTextureUpdateBind = this.onTextureUpdate.bind(this); this.texture.addEventListener( 'update', this.onTextureUpdateBind ); } - + this.renderable = true; } @@ -7256,8 +7419,8 @@ PIXI.Strip.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.width = texture.frame.width; this.height = texture.frame.height; @@ -7280,7 +7443,7 @@ PIXI.Rope = function(texture, points) { PIXI.Strip.call( this, texture ); this.points = points; - + try { this.verticies = new Float32Array( points.length * 4); @@ -7291,12 +7454,12 @@ PIXI.Rope = function(texture, points) catch(error) { this.verticies = verticies - + this.uvs = uvs this.colors = colors this.indices = indices } - + this.refresh(); } @@ -7309,99 +7472,99 @@ PIXI.Rope.prototype.refresh = function() { var points = this.points; if(points.length < 1)return; - + var uvs = this.uvs var indices = this.indices; var colors = this.colors; - + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - + + uvs[0] = 0 uvs[1] = 1 uvs[2] = 0 uvs[3] = 1 - + colors[0] = 1; colors[1] = 1; - + indices[0] = 0; indices[1] = 1; - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; // time to do some smart drawing! var 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; } } PIXI.Rope.prototype.updateTransform = function() { - + var points = this.points; if(points.length < 1)return; - - var verticies = this.verticies - + + var verticies = this.verticies + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - verticies[0] = point.x + perp.x + + verticies[0] = point.x + perp.x verticies[1] = point.y + perp.y //+ 200 - verticies[2] = point.x - perp.x + verticies[2] = point.x - perp.x verticies[3] = point.y - perp.y//+200 // time to do some smart drawing! - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; - + if(i < points.length-1) { nextPoint = points[i+1]; @@ -7410,35 +7573,35 @@ PIXI.Rope.prototype.updateTransform = function() { nextPoint = point } - + perp.y = -(nextPoint.x - lastPoint.x); perp.x = nextPoint.y - lastPoint.y; - + var ratio = (1 - (i / (total-1))) * 10; if(ratio > 1)ratio = 1; - + var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); var 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; - - verticies[index] = point.x + perp.x + + verticies[index] = point.x + perp.x verticies[index+1] = point.y + perp.y - verticies[index+2] = point.x - perp.x + verticies[index+2] = point.x - perp.x verticies[index+3] = point.y - perp.y lastPoint = point; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); } PIXI.Rope.prototype.setTexture = function(texture) { - // stop current texture + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7494,7 +7657,7 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tileScale * @type Point - */ + */ this.tileScale = new PIXI.Point(1,1); /** @@ -7502,11 +7665,11 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tilePosition * @type Point - */ + */ this.tilePosition = new PIXI.Point(0,0); this.renderable = true; - + this.blendMode = PIXI.blendModes.NORMAL } @@ -7524,8 +7687,8 @@ PIXI.TilingSprite.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7546,10 +7709,10 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) /** * @author Mat Groves http://matgroves.com/ @Doormat23 * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * + * * Awesome JS run time provided by EsotericSoftware * https://github.com/EsotericSoftware/spine-runtimes - * + * */ /** @@ -7562,48 +7725,41 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) * @constructor * @param url {String} The url of the spine anim file to be used */ -PIXI.Spine = function(url) -{ +PIXI.Spine = function (url) { PIXI.DisplayObjectContainer.call(this); - + this.spineData = PIXI.AnimCache[url]; - - if(!this.spineData) - { + + if (!this.spineData) { throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: " + url); - return; } - - this.count = 0; - - this.sprites = []; - + this.skeleton = new spine.Skeleton(this.spineData); this.skeleton.updateWorldTransform(); - this.stateData = new spine.AnimationStateData(this.spineData); + this.stateData = new spine.AnimationStateData(this.spineData); this.state = new spine.AnimationState(this.stateData); - - // add the sprites.. - for (var i = 0; i < this.skeleton.drawOrder.length; i++) { - - var attachmentName = this.skeleton.drawOrder[i].data.attachmentName; - - // kind of an assumtion here. that its a png - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; - } - - - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(attachmentName)); - sprite.anchor.x = sprite.anchor.y = 0.5; - this.addChild(sprite); - this.sprites.push(sprite); - }; -} -PIXI.Spine.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); + 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)) { + continue; + } + var spriteName = attachment.rendererObject.name; + var sprite = this.createSprite(slot, attachment.rendererObject); + slot.currentSprite = sprite; + slot.currentSpriteName = spriteName; + slotContainer.addChild(sprite); + } +}; + +PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); PIXI.Spine.prototype.constructor = PIXI.Spine; /* @@ -7612,55 +7768,74 @@ PIXI.Spine.prototype.constructor = PIXI.Spine; * @method updateTransform * @private */ -PIXI.Spine.prototype.updateTransform = function() -{ - // TODO should make this time based really.. - this.state.update(1/60); +PIXI.Spine.prototype.updateTransform = function () { + this.lastTime = this.lastTime || Date.now(); + var timeDelta = (Date.now() - this.lastTime) * 0.001; + this.lastTime = Date.now(); + this.state.update(timeDelta); this.state.apply(this.skeleton); this.skeleton.updateWorldTransform(); - - for (var i = 0; i < this.skeleton.drawOrder.length; i++) - { - var slot = this.skeleton.drawOrder[i]; + 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 instanceof spine.RegionAttachment)) { + slotContainer.visible = false; + continue; + } - var x = slot.bone.worldX + slot.attachment.x * slot.bone.m00 + slot.attachment.y * slot.bone.m01 + slot.attachment.width * 0.5; - var y = slot.bone.worldY + slot.attachment.x * slot.bone.m10 + slot.attachment.y * slot.bone.m11 + slot.attachment.height * 0.5; - //console.log(x + ' : ' + y); - - - //console.log(slot.attachment.name) - if(slot.cacheName != slot.attachment.name) - { - var attachmentName = slot.attachment.name; - - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; + if (attachment.rendererObject) { + if (!slot.currentSpriteName || slot.currentSpriteName != attachment.name) { + var spriteName = attachment.rendererObject.name; + if (slot.currentSprite !== undefined) { + slot.currentSprite.visible = false; } - - this.sprites[i].setTexture(PIXI.TextureCache[attachmentName]); - - slot.cacheName = slot.attachment.name; + slot.sprites = slot.sprites || {}; + if (slot.sprites[spriteName] !== undefined) { + slot.sprites[spriteName].visible = true; + } else { + var sprite = this.createSprite(slot, attachment.rendererObject); + slotContainer.addChild(sprite); + } + slot.currentSprite = slot.sprites[spriteName]; + slot.currentSpriteName = spriteName; } - - x += -((slot.attachment.width * (slot.bone.worldScaleX + slot.attachment.scaleX - 1))>>1); - y += -((slot.attachment.height * (slot.bone.worldScaleY + slot.attachment.scaleY - 1))>>1); - - - this.sprites[i].position.x = x; - this.sprites[i].position.y = y; - this.sprites[i].rotation = (-(slot.bone.worldRotation + slot.attachment.rotation)) * (Math.PI/180); - } - + } + slotContainer.visible = true; + + 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 * Math.PI / 180); + } + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -} +}; + + +PIXI.Spine.prototype.createSprite = function (slot, descriptor) { + var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; + var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); + sprite.scale = descriptor.scale; + sprite.rotation = descriptor.rotation; + sprite.anchor.x = sprite.anchor.y = 0.5; + + slot.sprites = slot.sprites || {}; + slot.sprites[descriptor.name] = sprite; + return sprite; +}; /* * Awesome JS run time provided by EsotericSoftware - * + * * https://github.com/EsotericSoftware/spine-runtimes - * + * */ var spine = {}; @@ -7770,7 +7945,7 @@ spine.Slot.prototype = { this.g = data.g; this.b = data.b; this.a = data.a; - + var slotDatas = this.skeleton.data.slots; for (var i = 0, n = slotDatas.length; i < n; i++) { if (slotDatas[i] == data) { @@ -8001,6 +8176,7 @@ spine.TranslateTimeline.prototype = { var frameTime = frames[frameIndex]; var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); + bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; } @@ -8025,14 +8201,12 @@ spine.ScaleTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. - + var bone = skeleton.bones[this.boneIndex]; if (time >= frames[frames.length - 3]) { // Time is after last frame. bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - - return; } @@ -8070,6 +8244,7 @@ spine.ColorTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. + var slot = skeleton.slots[this.slotIndex]; if (time >= frames[frames.length - 5]) { // Time is after last frame. @@ -8119,7 +8294,7 @@ spine.AttachmentTimeline = function (frameCount) { spine.AttachmentTimeline.prototype = { slotIndex: 0, getFrameCount: function () { - return this.frames.length / 2; + return this.frames.length; }, setFrame: function (frameIndex, time, attachmentName) { this.frames[frameIndex] = time; @@ -8136,11 +8311,6 @@ spine.AttachmentTimeline.prototype = { frameIndex = spine.binarySearch(frames, time, 1) - 1; var attachmentName = this.attachmentNames[frameIndex]; - //console.log(skeleton.slots[this.slotIndex]) - - // change the name! - // skeleton.slots[this.slotIndex].attachmentName = attachmentName; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); } }; @@ -8312,11 +8482,9 @@ spine.Skeleton.prototype = { if (slot.data.name == slotName) { var attachment = null; if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; } - slot.setAttachment(attachment); return; } @@ -8398,7 +8566,6 @@ spine.RegionAttachment.prototype = { offset[7/*Y4*/] = localYCos + localX2Sin; }, computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; y += bone.worldY; var m00 = bone.m00; @@ -8422,6 +8589,7 @@ spine.AnimationStateData = function (skeletonData) { this.animationToMixTime = {}; }; spine.AnimationStateData.prototype = { + defaultMix: 0, setMixByName: function (fromName, toName, duration) { var from = this.skeletonData.findAnimation(fromName); if (!from) throw "Animation not found: " + fromName; @@ -8434,7 +8602,7 @@ spine.AnimationStateData.prototype = { }, getMix: function (from, to) { var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : 0; + return time ? time : this.defaultMix; } }; @@ -8474,7 +8642,7 @@ spine.AnimationState.prototype = { this.previous = null; } this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else + } else this.current.apply(skeleton, this.currentTime, this.currentLoop); }, clearAnimation: function () { @@ -8620,16 +8788,9 @@ spine.SkeletonJson.prototype = { name = map["name"] || name; var type = spine.AttachmentType[map["type"] || "region"]; - - // @ekelokorpi - // var attachment = this.attachmentLoader.newAttachment(skin, type, name); - var attachment = new spine.RegionAttachment(); - - // @Doormat23 - // add the name of the attachment - attachment.name = name; - + if (type == spine.AttachmentType.region) { + var attachment = new spine.RegionAttachment(); attachment.x = (map["x"] || 0) * this.scale; attachment.y = (map["y"] || 0) * this.scale; attachment.scaleX = map["scaleX"] || 1; @@ -8638,10 +8799,19 @@ spine.SkeletonJson.prototype = { attachment.width = (map["width"] || 32) * this.scale; attachment.height = (map["height"] || 32) * this.scale; attachment.updateOffset(); + + attachment.rendererObject = {}; + attachment.rendererObject.name = name; + attachment.rendererObject.scale = {}; + attachment.rendererObject.scale.x = attachment.scaleX; + attachment.rendererObject.scale.y = attachment.scaleY; + attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; + return attachment; } - return attachment; + throw "Unknown attachment type: " + type; }, + readAnimation: function (name, map, skeletonData) { var timelines = []; var duration = 0; @@ -8692,7 +8862,7 @@ spine.SkeletonJson.prototype = { } timelines.push(timeline); duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - + } else throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; } @@ -8735,8 +8905,8 @@ spine.SkeletonJson.prototype = { timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); } timelines.push(timeline); - // PIXI FIX - duration = Math.max(duration, timeline.frames[Math.floor(timeline.getFrameCount()) - 1]); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } else throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; } @@ -9005,14 +9175,14 @@ spine.Bone.yDown = true; /** * This object is one that will allow you to specify custom rendering functions based on render type * - * @class CustomRenderable + * @class CustomRenderable * @extends DisplayObject * @constructor */ PIXI.CustomRenderable = function() { PIXI.DisplayObject.call( this ); - + } // constructor @@ -9118,19 +9288,19 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } else { - + var scope = this; this.source.onload = function(){ - + scope.hasLoaded = true; scope.width = scope.source.width; scope.height = scope.source.height; - + // add it to somewhere... PIXI.texturesToUpdate.push(scope); scope.dispatchEvent( { type: 'loaded', content: scope } ); @@ -9143,7 +9313,7 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } @@ -9183,7 +9353,7 @@ PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) { // new Image() breaks tex loading in some versions of Chrome. // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); + var image = new Image();//document.createElement('img'); if (crossorigin) { image.crossOrigin = ''; @@ -9211,7 +9381,7 @@ PIXI.FrameCache = {}; * @uses EventTarget * @constructor * @param baseTexture {BaseTexture} The base texture source to create the texture from - * @param frmae {Rectangle} The rectangle frame of the texture to show + * @param frame {Rectangle} The rectangle frame of the texture to show */ PIXI.Texture = function(baseTexture, frame) { @@ -9256,7 +9426,7 @@ PIXI.Texture = function(baseTexture, frame) { if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); //console.log(frame) - + this.setFrame(frame); } else @@ -9335,13 +9505,13 @@ PIXI.Texture.prototype.setFrame = function(frame) PIXI.Texture.fromImage = function(imageUrl, crossorigin) { var texture = PIXI.TextureCache[imageUrl]; - + if(!texture) { texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); PIXI.TextureCache[imageUrl] = texture; } - + return texture; } @@ -9391,7 +9561,7 @@ PIXI.Texture.addTextureToCache = function(texture, id) } /** - * Remove a texture from the textureCache. + * Remove a texture from the textureCache. * * @static * @method removeTextureFromCache @@ -9503,15 +9673,7 @@ PIXI.RenderTexture.prototype.initWebGL = function() // create a projection matrix.. this.projection = new PIXI.Point(this.width/2 , this.height/2); -/* - this.projectionMatrix = PIXI.mat4.create(); - this.projectionMatrix[5] = 2/this.height// * 0.5; - this.projectionMatrix[13] = -1; - - this.projectionMatrix[0] = 2/this.width; - this.projectionMatrix[12] = -1; -*/ // set the correct render function.. this.render = this.renderWebGL; @@ -9525,10 +9687,6 @@ PIXI.RenderTexture.prototype.resize = function(width, height) this.width = width; this.height = height; - //this.frame.width = this.width - //this.frame.height = this.height; - - if(PIXI.gl) { this.projection.x = this.width/2 @@ -9592,6 +9750,7 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle var children = displayObject.children; //TODO -? create a new one??? dont think so! + var originalWorldTransform = displayObject.worldTransform; displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; // modify to flip... displayObject.worldTransform[4] = -1; @@ -9604,8 +9763,9 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle displayObject.worldTransform[5] -= position.y; } - - + PIXI.visibleCount++; + displayObject.vcount = PIXI.visibleCount; + for(var i=0,j=children.length; i- format + */ +PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) +{ + this.frames = []; + var cols = Math.floor(this.texture.width / frameWidth); + var rows = Math.floor(this.texture.height / frameHeight); + + var i=0; + for (var y=0; y x1 && x < x1 + this.width) + if(x >= x1 && x <= x1 + this.width) { var y1 = this.y; - - if(y > y1 && y < y1 + this.height) + + if(y >= y1 && y <= y1 + this.height) { return true; } @@ -165,7 +165,7 @@ PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; * @class Polygon * @constructor * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, - * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arugments passed can be + * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are * Numbers. @@ -232,9 +232,9 @@ PIXI.Polygon.prototype.contains = function(x, y) return inside; } +// constructor PIXI.Polygon.prototype.constructor = PIXI.Polygon; - /** * @author Chad Engler */ @@ -256,7 +256,7 @@ PIXI.Circle = function(x, y, radius) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number @@ -306,6 +306,7 @@ PIXI.Circle.prototype.contains = function(x, y) return (dx + dy <= r2); } +// constructor PIXI.Circle.prototype.constructor = PIXI.Circle; @@ -320,8 +321,8 @@ PIXI.Circle.prototype.constructor = PIXI.Circle; * @constructor * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse - * @param width {Number} The overall height of this ellipse - * @param height {Number} The overall width of this ellipse + * @param width {Number} The overall width of this ellipse + * @param height {Number} The overall height of this ellipse */ PIXI.Ellipse = function(x, y, width, height) { @@ -331,21 +332,21 @@ PIXI.Ellipse = function(x, y, width, height) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number * @default 0 */ this.y = y || 0; - + /** * @property width * @type Number * @default 0 */ this.width = width || 0; - + /** * @property height * @type Number @@ -394,11 +395,11 @@ PIXI.Ellipse.getBounds = function() return new PIXI.Rectangle(this.x, this.y, this.width, this.height); } +// constructor PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; - /* * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV * you both rock! @@ -426,7 +427,7 @@ PIXI.mat3.create = function() matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -442,7 +443,7 @@ PIXI.mat3.identity = function(matrix) matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -469,35 +470,35 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat3.multiply = function (mat, mat2, dest) +PIXI.mat3.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[0], a01 = mat[1], a02 = mat[2], a10 = mat[3], a11 = mat[4], a12 = mat[5], a20 = mat[6], a21 = mat[7], a22 = mat[8], - + b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; - + dest[0] = b00 * a00 + b01 * a10 + b02 * a20; dest[1] = b00 * a01 + b01 * a11 + b02 * a21; dest[2] = b00 * a02 + b01 * a12 + b02 * a22; - + dest[3] = b10 * a00 + b11 * a10 + b12 * a20; dest[4] = b10 * a01 + b11 * a11 + b12 * a21; dest[5] = b10 * a02 + b11 * a12 + b12 * a22; - + dest[6] = b20 * a00 + b21 * a10 + b22 * a20; dest[7] = b20 * a01 + b21 * a11 + b22 * a21; dest[8] = b20 * a02 + b21 * a12 + b22 * a22; - + return dest; } @@ -514,11 +515,11 @@ PIXI.mat3.clone = function(mat) matrix[6] = mat[6]; matrix[7] = mat[7]; matrix[8] = mat[8]; - + return matrix; } -PIXI.mat3.transpose = function (mat, dest) +PIXI.mat3.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values if (!dest || mat === dest) { @@ -546,30 +547,30 @@ PIXI.mat3.transpose = function (mat, dest) return dest; } -PIXI.mat3.toMat4 = function (mat, dest) +PIXI.mat3.toMat4 = function (mat, dest) { if (!dest) { dest = PIXI.mat4.create(); } - + dest[15] = 1; dest[14] = 0; dest[13] = 0; dest[12] = 0; - + dest[11] = 0; dest[10] = mat[8]; dest[9] = mat[7]; dest[8] = mat[6]; - + dest[7] = 0; dest[6] = mat[5]; dest[5] = mat[4]; dest[4] = mat[3]; - + dest[3] = 0; dest[2] = mat[2]; dest[1] = mat[1]; dest[0] = mat[0]; - + return dest; } @@ -597,19 +598,19 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat4.transpose = function (mat, dest) +PIXI.mat4.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) + if (!dest || mat === dest) { var a01 = mat[1], a02 = mat[2], a03 = mat[3], a12 = mat[6], a13 = mat[7], a23 = mat[11]; - + mat[1] = mat[4]; mat[2] = mat[8]; mat[3] = mat[12]; @@ -624,7 +625,7 @@ PIXI.mat4.transpose = function (mat, dest) mat[14] = a23; return mat; } - + dest[0] = mat[0]; dest[1] = mat[4]; dest[2] = mat[8]; @@ -644,18 +645,18 @@ PIXI.mat4.transpose = function (mat, dest) return dest; } -PIXI.mat4.multiply = function (mat, mat2, dest) +PIXI.mat4.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - + // Cache only the current line of the second matrix - var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; + var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; @@ -705,7 +706,6 @@ PIXI.DisplayObject = function() { this.last = this; this.first = this; - /** * The coordinate of the object relative to the local coordinates of the parent. * @@ -779,15 +779,6 @@ PIXI.DisplayObject = function() */ this.renderable = false; - /** - * [read-only] The visibility of the object based on world (parent) factors. - * - * @property worldVisible - * @type Boolean - * @readOnly - */ - this.worldVisible = false; - /** * [read-only] The display object container that contains this display object. * @@ -806,15 +797,6 @@ PIXI.DisplayObject = function() */ this.stage = null; - /** - * [read-only] The index of this object in the parent's `children` array - * - * @property childIndex - * @type Number - * @readOnly - */ - this.childIndex = 0; - /** * [read-only] The multiplied alpha of the displayobject * @@ -953,17 +935,6 @@ PIXI.DisplayObject = function() // constructor PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObject.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - } -});*/ - /** * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default * Instead of using this function you can now simply set the interactive property to true or false @@ -1011,16 +982,57 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { }, set: function(value) { - this._mask = value; - + if(value) { + if(this._mask) + { + value.start = this._mask.start; + value.end = this._mask.end; + } + else + { + this.addFilter(value); + value.renderable = false; + } + } + else + { + this.removeFilter(this._mask); + this._mask.renderable = true; + } + + this._mask = value; + } +}); + +/** + * Sets the filters for the displayObject. Currently there's a few limitations. + * 1: At the moment only one filter can be applied at a time.. + * 2: They cannot be nested. + * 3: There's no padding yet. + * 4: this is a webGL only feature. + * @property filters + * @type Array + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { + get: function() { + return this._filters; + }, + set: function(value) { + + //if(value == ) + if(value) + { + if(this._filters)this.removeFilter(this._filters); this.addFilter(value) } else { - this.removeFilter(); + if(this._filters)this.removeFilter(this._filters); } + + this._filters = value; } }); @@ -1031,19 +1043,21 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { * @param mask {Graphics} the graphics object to use as a filter * @private */ -PIXI.DisplayObject.prototype.addFilter = function(mask) +PIXI.DisplayObject.prototype.addFilter = function(data) { - if(this.filter)return; - this.filter = true; - + //if(this.filter)return; + //this.filter = true; // insert a filter block.. + // TODO Onject pool thease bad boys.. var start = new PIXI.FilterBlock(); var end = new PIXI.FilterBlock(); + data.start = start; + data.end = end; - start.mask = mask; - end.mask = mask; + start.data = data; + end.data = data; start.first = start.last = this; end.first = end.last = this; @@ -1051,9 +1065,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) start.open = true; /* - * * insert start - * */ var childFirst = start @@ -1084,9 +1096,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) // now insert the end filter block.. /* - * * insert end filter - * */ var childFirst = end var childLast = end @@ -1125,8 +1135,6 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) this.__renderGroup.addFilterBlocks(start, end); } - mask.renderable = false; - } /* @@ -1135,13 +1143,14 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) * @method removeFilter * @private */ -PIXI.DisplayObject.prototype.removeFilter = function() +PIXI.DisplayObject.prototype.removeFilter = function(data) { - if(!this.filter)return; - this.filter = false; - + //if(!this.filter)return; + //this.filter = false; + console.log("YUOIO") // modify the list.. - var startBlock = this.first; + var startBlock = data.start; + var nextObject = startBlock._iNext; var previousObject = startBlock._iPrev; @@ -1151,9 +1160,8 @@ PIXI.DisplayObject.prototype.removeFilter = function() this.first = startBlock._iNext; - // remove the end filter - var lastBlock = this.last; + var lastBlock = data.end; var nextObject = lastBlock._iNext; var previousObject = lastBlock._iPrev; @@ -1162,8 +1170,6 @@ PIXI.DisplayObject.prototype.removeFilter = function() previousObject._iNext = nextObject; // this is always true too! -// if(this.last == lastBlock) - //{ var tempLast = lastBlock._iPrev; // need to make sure the parents last is updated too var updateLast = this; @@ -1174,15 +1180,11 @@ PIXI.DisplayObject.prototype.removeFilter = function() if(!updateLast)break; } - var mask = startBlock.mask - mask.renderable = true; - // if webGL... if(this.__renderGroup) { this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); } - //} } /* @@ -1194,7 +1196,7 @@ PIXI.DisplayObject.prototype.removeFilter = function() PIXI.DisplayObject.prototype.updateTransform = function() { // TODO OPTIMIZE THIS!! with dirty - if(this.rotation != this.rotationCache) + if(this.rotation !== this.rotationCache) { this.rotationCache = this.rotation; this._sr = Math.sin(this.rotation); @@ -1236,9 +1238,12 @@ PIXI.DisplayObject.prototype.updateTransform = function() // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); this.worldAlpha = this.alpha * this.parent.worldAlpha; + + this.vcount = PIXI.visibleCount; } +PIXI.visibleCount = 0; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1270,18 +1275,6 @@ PIXI.DisplayObjectContainer = function() PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObjectContainer.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - - } -});*/ - /** * Adds a child to the container. * @@ -1299,11 +1292,10 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) } child.parent = this; - child.childIndex = this.children.length; this.children.push(child); - // updae the stage refference.. + // update the stage refference.. if(this.stage) { @@ -1326,7 +1318,7 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) var previousObject; // this could be wrong if there is a filter?? - if(this.filter) + if(this._filters) { previousObject = this.last._iPrev; } @@ -1338,7 +1330,6 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) nextObject = previousObject._iNext; // always true in this case - //this.last = child.last; // need to make sure the parents last is updated too var updateLast = this; var prevLast = previousObject; @@ -1402,7 +1393,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) } // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject; var previousObject; @@ -1410,7 +1401,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) if(index == this.children.length) { previousObject = this.last; - var updateLast = this;//.parent; + var updateLast = this; var prevLast = this.last; while(updateLast) { @@ -1539,7 +1530,7 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child) { // unlink // // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject = childLast._iNext; @@ -1609,7 +1600,6 @@ PIXI.DisplayObjectContainer.prototype.updateTransform = function() this.children[i].updateTransform(); } } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1739,9 +1729,18 @@ PIXI.Sprite.prototype.setTexture = function(texture) if(this.texture.baseTexture != texture.baseTexture) { this.textureChange = true; + this.texture = texture; + + if(this.__renderGroup) + { + this.__renderGroup.updateTexture(this); + } + } + else + { + this.texture = texture; } - this.texture = texture; this.updateFrame = true; } @@ -1798,7 +1797,6 @@ PIXI.Sprite.fromImage = function(imageId) return new PIXI.Sprite(texture); } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1814,7 +1812,7 @@ PIXI.Sprite.fromImage = function(imageId) PIXI.MovieClip = function(textures) { PIXI.Sprite.call(this, textures[0]); - + /** * The array of textures that make up the animation * @@ -1822,7 +1820,7 @@ PIXI.MovieClip = function(textures) * @type Array */ this.textures = textures; - + /** * The speed that the MovieClip will play at. Higher is faster, lower is slower * @@ -1848,7 +1846,7 @@ PIXI.MovieClip = function(textures) * @type Function */ this.onComplete = null; - + /** * [read-only] The index MovieClips current frame (this may not have to be a whole number) * @@ -1857,8 +1855,8 @@ PIXI.MovieClip = function(textures) * @default 0 * @readOnly */ - this.currentFrame = 0; - + this.currentFrame = 0; + /** * [read-only] Indicates if the MovieClip is currently playing * @@ -1873,6 +1871,23 @@ PIXI.MovieClip = function(textures) PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; +/** +* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures +* assigned to the MovieClip. +* +* @property totalFrames +* @type Number +* @default 0 +* @readOnly +*/ +Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { + get: function() { + + return this.textures.length; + } +}); + + /** * Stops the MovieClip * @@ -1928,11 +1943,13 @@ PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) PIXI.MovieClip.prototype.updateTransform = function() { PIXI.Sprite.prototype.updateTransform.call(this); - + if(!this.playing)return; - + this.currentFrame += this.animationSpeed; + var round = (this.currentFrame + 0.5) | 0; + if(this.loop || round < this.textures.length) { this.setTexture(this.textures[round % this.textures.length]); @@ -1952,14 +1969,49 @@ PIXI.MovieClip.prototype.updateTransform = function() -PIXI.FilterBlock = function(mask) +PIXI.FilterBlock = function() { - this.graphics = mask this.visible = true; this.renderable = true; } +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.ColorMatrixFilter = function() +{ + // set the uniforms + this.uniforms = { + matrix: {type: 'mat4', value: [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1]}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float invert;", + "uniform mat4 matrix;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", + "gl_FragColor = gl_FragColor * vColor;", + "}" + ]; + +} +Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { + get: function() { + return this.uniforms.matrix.value; + }, + set: function(value) { + this.uniforms.matrix.value = value; + } +}); /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1988,7 +2040,7 @@ PIXI.Text = function(text, style) this.setText(text); this.setStyle(style); - + this.updateText(); this.dirty = false; }; @@ -2030,7 +2082,7 @@ PIXI.Text.prototype.setStyle = function(style) * @methos setText * @param {String} text The copy that you would like the text to display */ -PIXI.Sprite.prototype.setText = function(text) +PIXI.Text.prototype.setText = function(text) { this.text = text.toString() || " "; this.dirty = true; @@ -2045,9 +2097,9 @@ PIXI.Sprite.prototype.setText = function(text) PIXI.Text.prototype.updateText = function() { this.context.font = this.style.font; - + var outputText = this.text; - + // word wrap // preserve original text if(this.style.wordWrap)outputText = this.wordWrap(this.text); @@ -2065,7 +2117,7 @@ PIXI.Text.prototype.updateText = function() maxLineWidth = Math.max(maxLineWidth, lineWidth); } this.canvas.width = maxLineWidth + this.style.strokeThickness; - + //calculate text height var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; this.canvas.height = lineHeight * lines.length; @@ -2073,7 +2125,7 @@ PIXI.Text.prototype.updateText = function() //set canvas text styles this.context.fillStyle = this.style.fill; this.context.font = this.style.font; - + this.context.strokeStyle = this.style.stroke; this.context.lineWidth = this.style.strokeThickness; @@ -2083,7 +2135,7 @@ PIXI.Text.prototype.updateText = function() for (i = 0; i < lines.length; i++) { var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); - + if(this.style.align == "right") { linePosition.x += maxLineWidth - lineWidths[i]; @@ -2103,7 +2155,7 @@ PIXI.Text.prototype.updateText = function() this.context.fillText(lines[i], linePosition.x, linePosition.y); } } - + this.updateTexture(); }; @@ -2119,10 +2171,10 @@ PIXI.Text.prototype.updateTexture = function() this.texture.baseTexture.height = this.canvas.height; this.texture.frame.width = this.canvas.width; this.texture.frame.height = this.canvas.height; - + this._width = this.canvas.width; this._height = this.canvas.height; - + PIXI.texturesToUpdate.push(this.texture.baseTexture); }; @@ -2136,10 +2188,10 @@ PIXI.Text.prototype.updateTransform = function() { if(this.dirty) { - this.updateText(); + this.updateText(); this.dirty = false; } - + PIXI.Sprite.prototype.updateTransform.call(this); }; @@ -2151,12 +2203,12 @@ PIXI.Text.prototype.updateTransform = function() * @param fontStyle {Object} * @private */ -PIXI.Text.prototype.determineFontHeight = function(fontStyle) +PIXI.Text.prototype.determineFontHeight = function(fontStyle) { // build a little reference dictionary so if the font style has been used return a // cached version... var result = PIXI.Text.heightCache[fontStyle]; - + if(!result) { var body = document.getElementsByTagName("body")[0]; @@ -2165,13 +2217,13 @@ PIXI.Text.prototype.determineFontHeight = function(fontStyle) dummy.appendChild(dummyText); dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); body.appendChild(dummy); - + result = dummy.offsetHeight; PIXI.Text.heightCache[fontStyle] = result; - + body.removeChild(dummy); } - + return result; }; @@ -2191,7 +2243,7 @@ PIXI.Text.prototype.wordWrap = function(text) if(p == start) { return 1; } - + if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) { if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) @@ -2208,7 +2260,7 @@ PIXI.Text.prototype.wordWrap = function(text) return arguments.callee(ctx, text, start, p, wrapWidth); } }; - + var lineWrap = function(ctx, text, wrapWidth) { if(ctx.measureText(text).width <= wrapWidth || text.length < 1) @@ -2218,14 +2270,14 @@ PIXI.Text.prototype.wordWrap = function(text) var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); }; - + var result = ""; var lines = text.split("\n"); for (var i = 0; i < lines.length; i++) { result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; } - + return result; }; @@ -2241,7 +2293,7 @@ PIXI.Text.prototype.destroy = function(destroyTexture) { this.texture.destroy(); } - + }; PIXI.Text.heightCache = {}; @@ -2252,7 +2304,7 @@ PIXI.Text.heightCache = {}; /** * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" - * You can generate the fnt files using + * You can generate the fnt files using * http://www.angelcode.com/products/bmfont/ for windows or * http://www.bmglyph.com/ for mac. * @@ -2342,7 +2394,7 @@ PIXI.BitmapText.prototype.updateText = function() prevCharCode = null; continue; } - + var charData = data.chars[charCode]; if(!charData) continue; @@ -2405,7 +2457,7 @@ PIXI.BitmapText.prototype.updateTransform = function() this.dirty = false; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); }; @@ -2414,10 +2466,8 @@ PIXI.BitmapText.fonts = {}; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ - - - -/** + + /** * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive * This manager also supports multitouch. * @@ -2451,6 +2501,8 @@ PIXI.InteractionManager = function(stage) */ this.touchs = {}; + + // helpers this.tempPoint = new PIXI.Point(); //this.tempMatrix = mat3.create(); @@ -2461,7 +2513,19 @@ PIXI.InteractionManager = function(stage) this.pool = []; this.interactiveItems = []; + this.interactionDOMElement = null; + //this will make it so that you dont have to call bind all the time + this.onMouseMove = this.onMouseMove.bind( this ); + this.onMouseDown = this.onMouseDown.bind(this); + this.onMouseOut = this.onMouseOut.bind(this); + this.onMouseUp = this.onMouseUp.bind(this); + + this.onTouchStart = this.onTouchStart.bind(this); + this.onTouchEnd = this.onTouchEnd.bind(this); + this.onTouchMove = this.onTouchMove.bind(this); + + this.last = 0; } @@ -2486,7 +2550,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj { var child = children[i]; - if(child.visible) { +// if(child.visible) { // push all interactive bits if(child.interactive) { @@ -2508,7 +2572,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj this.collectInteractiveSprite(child, iParent); } } - } +// } } } @@ -2521,27 +2585,68 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj */ PIXI.InteractionManager.prototype.setTarget = function(target) { + this.target = target; + + //check if the dom element has been set. If it has don't do anything + if( this.interactionDOMElement === null ) { + + this.setTargetDomElement( target.view ); + } + + document.body.addEventListener('mouseup', this.onMouseUp, true); +} + + +/** + * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM + * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element + * to receive those events + * + * @method setTargetDomElement + * @param domElement {DOMElement} the dom element which will receive mouse and touch events + * @private + */ +PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) +{ + //remove previouse listeners + if( this.interactionDOMElement !== null ) + { + this.interactionDOMElement.style['-ms-content-zooming'] = ''; + this.interactionDOMElement.style['-ms-touch-action'] = ''; + + this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); + this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); + this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); + this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); + this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); + } + + if (window.navigator.msPointerEnabled) { // time to remove some of that zoom in ja.. - target.view.style["-ms-content-zooming"] = "none"; - target.view.style["-ms-touch-action"] = "none" + domElement.style['-ms-content-zooming'] = 'none'; + domElement.style['-ms-touch-action'] = 'none'; // DO some window specific touch! } - - this.target = target; - target.view.addEventListener('mousemove', this.onMouseMove.bind(this), true); - target.view.addEventListener('mousedown', this.onMouseDown.bind(this), true); - document.body.addEventListener('mouseup', this.onMouseUp.bind(this), true); - target.view.addEventListener('mouseout', this.onMouseUp.bind(this), true); - - // aint no multi touch just yet! - target.view.addEventListener("touchstart", this.onTouchStart.bind(this), true); - target.view.addEventListener("touchend", this.onTouchEnd.bind(this), true); - target.view.addEventListener("touchmove", this.onTouchMove.bind(this), true); + + this.interactionDOMElement = domElement; + + domElement.addEventListener('mousemove', this.onMouseMove, true); + domElement.addEventListener('mousedown', this.onMouseDown, true); + domElement.addEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + domElement.addEventListener('touchstart', this.onTouchStart, true); + domElement.addEventListener('touchend', this.onTouchEnd, true); + domElement.addEventListener('touchmove', this.onTouchMove, true); } + /** * updates the state of interactive objects * @@ -2583,12 +2688,14 @@ PIXI.InteractionManager.prototype.update = function() // loop through interactive objects! var length = this.interactiveItems.length; - this.target.view.style.cursor = "default"; + this.interactionDOMElement.style.cursor = "default"; for (var i = 0; i < length; i++) { var item = this.interactiveItems[i]; - if(!item.visible)continue; + + + //if(!item.visible)continue; // OPTIMISATION - only calculate every time if the mousemove function exists.. // OK so.. does the object have any other interactive functions? @@ -2604,7 +2711,7 @@ PIXI.InteractionManager.prototype.update = function() // loks like there was a hit! if(item.__hit) { - if(item.buttonMode)this.target.view.style.cursor = "pointer"; + if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; if(!item.__isOver) { @@ -2639,7 +2746,7 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) { this.mouse.originalEvent = event || window.event; //IE uses window.event // TODO optimize by not check EVERY TIME! maybe half as often? // - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); @@ -2669,7 +2776,6 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) */ PIXI.InteractionManager.prototype.onMouseDown = function(event) { - event.preventDefault(); this.mouse.originalEvent = event || window.event; //IE uses window.event // loop through inteaction tree... @@ -2706,6 +2812,26 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) } } + +PIXI.InteractionManager.prototype.onMouseOut = function(event) +{ + var length = this.interactiveItems.length; + + this.interactionDOMElement.style.cursor = "default"; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.__isOver) + { + this.mouse.target = item; + if(item.mouseout)item.mouseout(this.mouse); + item.__isOver = false; + } + } +} + /** * Is called when the mouse button is released on the renderer element * @@ -2770,7 +2896,7 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) { var global = interactionData.global; - if(!item.visible)return false; + if(item.vcount !== PIXI.visibleCount)return false; var isSprite = (item instanceof PIXI.Sprite), worldTransform = item.worldTransform, @@ -2840,14 +2966,14 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) */ PIXI.InteractionManager.prototype.onTouchMove = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) { var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; + touchData.originalEvent = event || window.event; // update the touch position touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); @@ -2871,10 +2997,7 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) */ PIXI.InteractionManager.prototype.onTouchStart = function(event) { - event.preventDefault(); - this.mouse.originalEvent = event || window.event; //IE uses window.event - - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2884,6 +3007,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) var touchData = this.pool.pop(); if(!touchData)touchData = new PIXI.InteractionData(); + touchData.originalEvent = event || window.event; + this.touchs[touchEvent.identifier] = touchData; touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); @@ -2921,8 +3046,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) */ PIXI.InteractionManager.prototype.onTouchEnd = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + //this.mouse.originalEvent = event || window.event; //IE uses window.event + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2943,7 +3068,7 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) if(itemTouchData == touchData) { // so this one WAS down... - + touchData.originalEvent = event || window.event; // hitTest?? if(item.touchend || item.tap) @@ -3055,9 +3180,8 @@ PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; * @constructor * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format * like: 0xFFFFFF for white - * @param interactive {Boolean} enable / disable interaction (default is false) */ -PIXI.Stage = function(backgroundColor, interactive) +PIXI.Stage = function(backgroundColor) { PIXI.DisplayObjectContainer.call( this ); @@ -3077,7 +3201,7 @@ PIXI.Stage = function(backgroundColor, interactive) * @property interactive * @type Boolean */ - this.interactive = interactive; + this.interactive = true; /** * The interaction manage for this stage, manages all interactive activity on the stage @@ -3113,6 +3237,18 @@ PIXI.Stage = function(backgroundColor, interactive) PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); PIXI.Stage.prototype.constructor = PIXI.Stage; +/** + * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. + * This is useful for when you have other DOM elements ontop of the Canvas element. + * + * @method setInteractionDelegate + * @param domElement {DOMElement} This new domElement which will receive mouse/touch events + */ +PIXI.Stage.prototype.setInteractionDelegate = function(domElement) +{ + this.interactionManager.setTargetDomElement( domElement ); +} + /* * Updates the object transform for rendering * @@ -3122,6 +3258,7 @@ PIXI.Stage.prototype.constructor = PIXI.Stage; PIXI.Stage.prototype.updateTransform = function() { this.worldAlpha = 1; + this.vcount = PIXI.visibleCount; for(var i=0,j=this.children.length; i 100) { console.log("BREAK") break } - } + } } @@ -3361,14 +3466,14 @@ PIXI.runList = function(item) PIXI.EventTarget = function () { var listeners = {}; - + this.addEventListener = this.on = function ( type, listener ) { - - + + if ( listeners[ type ] === undefined ) { listeners[ type ] = []; - + } if ( listeners[ type ].indexOf( listener ) === - 1 ) { @@ -3379,11 +3484,17 @@ PIXI.EventTarget = function () { }; this.dispatchEvent = this.emit = function ( event ) { - - for ( var listener in listeners[ event.type ] ) { - listeners[ event.type ][ listener ]( event ); - + if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { + + return; + + } + + for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { + + listeners[ event.type ][ i ]( event ); + } }; @@ -3417,8 +3528,11 @@ PIXI.EventTarget = function () { * @param height {Number} the height of the renderers view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) + * + * antialias */ -PIXI.autoDetectRenderer = function(width, height, view, transparent) +PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) { if(!width)width = 800; if(!height)height = 600; @@ -3429,7 +3543,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) //console.log(webgl); if( webgl ) { - return new PIXI.WebGLRenderer(width, height, view, transparent); + return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); } return new PIXI.CanvasRenderer(width, height, view, transparent); @@ -3441,7 +3555,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) PolyK library url: http://polyk.ivank.net Released under MIT licence. - + Copyright (c) 2012 Ivan Kuckir Permission is hereby granted, free of charge, to any person @@ -3465,8 +3579,8 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - This is an amazing lib! - + This is an amazing lib! + slightly modified by mat groves (matgroves.com); */ @@ -3482,13 +3596,13 @@ PIXI.PolyK = {}; PIXI.PolyK.Triangulate = function(p) { var sign = true; - + var n = p.length>>1; if(n<3) return []; var tgs = []; var avl = []; for(var i=0; i 3) @@ -3496,11 +3610,11 @@ PIXI.PolyK.Triangulate = function(p) var i0 = avl[(i+0)%al]; var i1 = avl[(i+1)%al]; var i2 = avl[(i+2)%al]; - + var ax = p[2*i0], ay = p[2*i0+1]; var bx = p[2*i1], by = p[2*i1+1]; var cx = p[2*i2], cy = p[2*i2+1]; - + var earFound = false; if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) { @@ -3519,7 +3633,7 @@ PIXI.PolyK.Triangulate = function(p) al--; i = 0; } - else if(i++ > 3*al) + else if(i++ > 3*al) { // need to flip flip reverse it! // reset! @@ -3528,17 +3642,17 @@ PIXI.PolyK.Triangulate = function(p) var tgs = []; avl = []; for(var i=0; i= 0) == sign; } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -3612,13 +3725,11 @@ PIXI.shaderVertexSrc = [ "attribute vec2 aVertexPosition;", "attribute vec2 aTextureCoord;", "attribute float aColor;", - //"uniform mat4 uMVMatrix;", "uniform vec2 projectionVector;", "varying vec2 vTextureCoord;", "varying float vColor;", "void main(void) {", - // "gl_Position = uMVMatrix * vec4(aVertexPosition, 1.0, 1.0);", "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", "vTextureCoord = aTextureCoord;", "vColor = aColor;", @@ -3658,7 +3769,6 @@ PIXI.stripShaderVertexSrc = [ "}" ]; - /* * primitive shader.. */ @@ -3685,6 +3795,8 @@ PIXI.primitiveShaderVertexSrc = [ "}" ]; +PIXI.shaderStack = []; + PIXI.initPrimitiveShader = function() { var gl = PIXI.gl; @@ -3699,27 +3811,26 @@ PIXI.initPrimitiveShader = function() shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); + + //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(shaderProgram.colorAttribute); +//gl.enableVertexAttribArray(program.textureCoordAttribute); + shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); PIXI.primitiveProgram = shaderProgram; + + } PIXI.initDefaultShader = function() { - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.shaderVertexSrc, PIXI.shaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - // shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.shaderProgram = shaderProgram; + PIXI.defaultShader = new PIXI.PixiShader(); + PIXI.defaultShader.init(); + PIXI.activateShader(PIXI.defaultShader); + /* + PIXI.shaderStack.push(PIXI.defaultShader); + PIXI.current*/ } PIXI.initDefaultStripShader = function() @@ -3736,9 +3847,7 @@ PIXI.initDefaultStripShader = function() shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); PIXI.stripShaderProgram = shaderProgram; @@ -3789,35 +3898,135 @@ PIXI.compileProgram = function(vertexSrc, fragmentSrc) return shaderProgram; } +PIXI.activateShader = function(shader) +{ + PIXI.shaderStack.push(shader); + + //console.log(">>>") + var gl = PIXI.gl; + + var shaderProgram = shader.program; + + // map uniforms.. + gl.useProgram(shaderProgram); + + gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + gl.enableVertexAttribArray(shaderProgram.colorAttribute); + gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); -PIXI.activateDefaultShader = function() + shader.syncUniforms(); + + PIXI.currentShader = shaderProgram; +} + + +PIXI.popShader = function() { var gl = PIXI.gl; - var shaderProgram = PIXI.shaderProgram; + // activate last program.. + var lastProgram = PIXI.shaderStack.pop(); + + var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); + PIXI.currentShader = shaderProgram; } - - PIXI.activatePrimitiveShader = function() { var gl = PIXI.gl; - gl.disableVertexAttribArray(PIXI.shaderProgram.textureCoordAttribute); - gl.disableVertexAttribArray(PIXI.shaderProgram.colorAttribute); - gl.useProgram(PIXI.primitiveProgram); - gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); + gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + + //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); } +PIXI.deactivatePrimitiveShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.currentShader); + + gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.PixiShader = function() +{ + // the webGL program.. + this.program; + + this.fragmentSrc = [ + "precision lowp float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", + "}" + ]; + +} + +PIXI.PixiShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get the default shader bits! + program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); + program.colorAttribute = gl.getAttribLocation(program, "aColor"); + program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); + + program.projectionVector = gl.getUniformLocation(program, "projectionVector"); + program.samplerUniform = gl.getUniformLocation(program, "uSampler"); + + // add those custom shaders! + for (var key in this.uniforms) + { + // get the uniform locations.. + program[key] = gl.getUniformLocation(program, key); + } + + this.program = program; +} + +PIXI.PixiShader.prototype.syncUniforms = function() +{ + var gl = PIXI.gl; + + for (var key in this.uniforms) + { + //var + var type = this.uniforms[key].type; + + // need to grow this! + if(type == "f") + { + gl.uniform1f(this.program[key], this.uniforms[key].value); + } + else if(type == "mat4") + { + gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); + } + } + +} + /** * @author Mat Groves http://matgroves.com/ @Doormat23 @@ -3887,7 +4096,7 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); // WHY DOES THIS LINE NEED TO BE THERE??? - gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // its not even used.. but need to be set or it breaks? // only on pc though.. @@ -3899,8 +4108,10 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); + PIXI.deactivatePrimitiveShader(); + // return to default shader... - PIXI.activateDefaultShader(); +// PIXI.activateShader(PIXI.defaultShader); } /** @@ -4243,7 +4454,7 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) verts.push(px , py); verts.push(r, g, b, alpha); - verts.push(p2x - (px-p2x), p2y - (py - p2y));//, 4); + verts.push(p2x - (px-p2x), p2y - (py - p2y)); verts.push(r, g, b, alpha); } } @@ -4356,9 +4567,10 @@ PIXI.gl; * @param height=0 {Number} the height of the canvas view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) * */ -PIXI.WebGLRenderer = function(width, height, view, transparent) +PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) { // do a catch.. only 1 webGL renderer.. @@ -4382,7 +4594,7 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) { PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { alpha: this.transparent, - antialias:true, // SPEED UP?? + antialias:!!antialias, // SPEED UP?? premultipliedAlpha:false, stencil:true }); @@ -4392,11 +4604,12 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); } - PIXI.initPrimitiveShader(); PIXI.initDefaultShader(); + PIXI.initPrimitiveShader(); PIXI.initDefaultStripShader(); - PIXI.activateDefaultShader(); + +// PIXI.activateDefaultShader(); var gl = this.gl; PIXI.WebGLRenderer.gl = gl; @@ -4413,7 +4626,10 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) this.resize(this.width, this.height); this.contextLost = false; + PIXI.activateShader(PIXI.defaultShader); + this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); + } // constructor @@ -4469,8 +4685,6 @@ PIXI.WebGLRenderer.prototype.render = function(stage) { // TODO make this work // dont think this is needed any more? - //if(this.__stage)this.checkVisibility(this.__stage, false) - this.__stage = stage; this.stageRenderGroup.setRenderable(stage); } @@ -4487,10 +4701,8 @@ PIXI.WebGLRenderer.prototype.render = function(stage) // update any textures PIXI.WebGLRenderer.updateTextures(); - // recursivly loop through all items! - //this.checkVisibility(stage, true); - // update the scene graph + PIXI.visibleCount++; stage.updateTransform(); var gl = this.gl; @@ -4499,16 +4711,12 @@ PIXI.WebGLRenderer.prototype.render = function(stage) gl.colorMask(true, true, true, this.transparent); gl.viewport(0, 0, this.width, this.height); - // set the correct matrix.. - // gl.uniformMatrix4fv(this.shaderProgram.mvMatrixUniform, false, this.projectionMatrix); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); gl.clear(gl.COLOR_BUFFER_BIT); // HACK TO TEST - //PIXI.projectionMatrix = this.projectionMatrix; this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; this.stageRenderGroup.render(PIXI.projection); @@ -4546,8 +4754,9 @@ PIXI.WebGLRenderer.prototype.render = function(stage) */ PIXI.WebGLRenderer.updateTextures = function() { - for (var i=0; i < PIXI.texturesToUpdate.length; i++) this.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) this.destroyTexture(PIXI.texturesToDestroy[i]); + //TODO break this out into a texture manager... + for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); + for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; } @@ -4562,6 +4771,7 @@ PIXI.WebGLRenderer.updateTextures = function() */ PIXI.WebGLRenderer.updateTexture = function(texture) { + //TODO break this out into a texture manager... var gl = PIXI.gl; if(!texture._glTexture) @@ -4602,9 +4812,10 @@ PIXI.WebGLRenderer.updateTexture = function(texture) * @param texture {Texture} The texture to update * @private */ -PIXI.WebGLRenderer.prototype.destroyTexture = function(texture) +PIXI.WebGLRenderer.destroyTexture = function(texture) { - var gl = this.gl; + //TODO break this out into a texture manager... + var gl = PIXI.gl; if(texture._glTexture) { @@ -4768,7 +4979,6 @@ PIXI.WebGLBatch.prototype.clean = function() this.uvs = []; this.indices = []; this.colors = []; - //this.sprites = []; this.dynamicSize = 1; this.texture = null; this.last = null; @@ -4805,7 +5015,6 @@ PIXI.WebGLBatch.prototype.init = function(sprite) this.dirty = true; this.blendMode = sprite.blendMode; this.texture = sprite.texture.baseTexture; -// this.sprites.push(sprite); this.head = sprite; this.tail = sprite; this.size = 1; @@ -4838,7 +5047,6 @@ PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) else { this.head = sprite; - //this.head.__prev = null } } @@ -4926,7 +5134,7 @@ PIXI.WebGLBatch.prototype.split = function(sprite) { this.dirty = true; - var batch = new PIXI.WebGLBatch(this.gl);//PIXI._getBatch(this.gl); + var batch = new PIXI.WebGLBatch(this.gl); batch.init(sprite); batch.texture = this.texture; batch.tail = this.tail; @@ -4936,8 +5144,6 @@ PIXI.WebGLBatch.prototype.split = function(sprite) sprite.__prev = null; // return a splite batch! - //sprite.__prev.__next = null; - //sprite.__prev = null; // TODO this size is wrong! // need to recalculate :/ problem with a linked list! @@ -5007,13 +5213,13 @@ PIXI.WebGLBatch.prototype.growBatch = function() gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); - this.uvs = new Float32Array( this.dynamicSize * 8 ) + this.uvs = new Float32Array( this.dynamicSize * 8 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); this.dirtyUVS = true; - this.colors = new Float32Array( this.dynamicSize * 4 ) + this.colors = new Float32Array( this.dynamicSize * 4 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); @@ -5112,7 +5318,7 @@ PIXI.WebGLBatch.prototype.update = function() while(displayObject) { - if(displayObject.worldVisible) + if(displayObject.vcount === PIXI.visibleCount) { width = displayObject.texture.frame.width; height = displayObject.texture.frame.height; @@ -5214,7 +5420,7 @@ PIXI.WebGLBatch.prototype.update = function() PIXI.WebGLBatch.prototype.render = function(start, end) { start = start || 0; - //end = end || this.size; + if(end == undefined)end = this.size; if(this.dirty) @@ -5230,8 +5436,9 @@ PIXI.WebGLBatch.prototype.render = function(start, end) //TODO optimize this! - var shaderProgram = PIXI.shaderProgram; - gl.useProgram(shaderProgram); + var shaderProgram = PIXI.currentShader; + + //gl.useProgram(shaderProgram); // update the verts.. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); @@ -5239,6 +5446,8 @@ PIXI.WebGLBatch.prototype.render = function(start, end) gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // update the uvs + var isDefault = (shaderProgram == PIXI.shaderProgram) + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); if(this.dirtyUVS) @@ -5262,13 +5471,11 @@ PIXI.WebGLBatch.prototype.render = function(start, end) } gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - //var startIndex = 0//1; var len = end - start; - // console.log(this.size) + // DRAW THAT this! gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); } @@ -5336,77 +5543,45 @@ PIXI.WebGLRenderGroup.prototype.render = function(projection) PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - // TODO remove this by replacing visible with getter setters.. - this.checkVisibility(this.root, this.root.visible); - // will render all the elements in the group var renderable; - - for (var i=0; i < this.batchs.length; i++) { + renderable = this.batchs[i]; if(renderable instanceof PIXI.WebGLBatch) { this.batchs[i].render(); + continue; } - else if(renderable instanceof PIXI.TilingSprite) + + // non sprite batch.. + var worldVisible = renderable.vcount === PIXI.visibleCount; + + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ - if(renderable.open) - { - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - gl.colorMask(true, true, true, false); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - else - { - gl.disable(gl.STENCIL_TEST); - } + this.handleFilterBlock(renderable, projection); } } } -/** - * Renders the stage to its webgl view - * - * @method handleFilter - * @param filter {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.handleFilter = function(filter, projection) -{ - -} - /** * Renders a specific displayObject * @@ -5420,11 +5595,8 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - this.checkVisibility(displayObject, displayObject.visible); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); -// gl.uniformMatrix4fv(PIXI.shaderProgram.mvMatrixUniform, false, projectionMatrix); - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); - // to do! // render part of the scene... @@ -5483,7 +5655,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project while(lastItem.children.length > 0) { lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem; + if(lastItem.renderable)lastRenderable = lastItem.last; } if(lastRenderable instanceof PIXI.Sprite) @@ -5577,45 +5749,80 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project */ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) { + var sta = PIXI.shaderStack.length; + + var worldVisible = renderable.vcount === PIXI.visibleCount + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.CustomRenderable) { - if(renderable.visible) renderable.renderWebGL(this, projection); + if(worldVisible) renderable.renderWebGL(this, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ + this.handleFilterBlock(renderable, projection); + } +} - var gl = PIXI.gl; +PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) +{ + /* + * for now only masks are supported.. + */ + var gl = PIXI.gl; - if(renderable.open) + if(renderable.open) + { + if(renderable.data instanceof Array) + { + var filter = renderable.data[0]; + + if(!filter.shader) + { + var shader = new PIXI.PixiShader(); + + shader.fragmentSrc = filter.fragmentSrc; + shader.uniforms = filter.uniforms; + shader.init(); + + filter.shader = shader + } + + PIXI.activateShader(filter.shader); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } + else { gl.enable(gl.STENCIL_TEST); gl.colorMask(false, false, false, false); gl.stencilFunc(gl.ALWAYS,1,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - // we know this is a render texture so enable alpha too.. + PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); + gl.colorMask(true, true, true, true); gl.stencilFunc(gl.NOTEQUAL,0,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); } + } + else + { + if(renderable.data instanceof Array) + { + PIXI.popShader(); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } else { gl.disable(gl.STENCIL_TEST); @@ -5623,42 +5830,6 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) } } -/** - * Checks the visibility of a displayObject - * - * @method checkVisibility - * @param displayObject {DisplayObject} - * @param globalVisible {Boolean} - * @private - */ -PIXI.WebGLRenderGroup.prototype.checkVisibility = function(displayObject, globalVisible) -{ - // give the dp a reference to its renderGroup... - var children = displayObject.children; - //displayObject.worldVisible = globalVisible; - for (var i=0; i < children.length; i++) - { - var child = children[i]; - - // TODO optimize... should'nt need to loop through everything all the time - child.worldVisible = child.visible && globalVisible; - - // everything should have a batch! - // time to see whats new! - if(child.textureChange) - { - child.textureChange = false; - if(child.worldVisible)this.updateTexture(child); - // update texture!! - } - - if(child.children.length > 0) - { - this.checkVisibility(child, child.worldVisible); - } - }; -} - /** * Updates a webgl texture * @@ -5719,7 +5890,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * It keeps going back until it finds a sprite or the stage */ var previousRenderable = start; - while(previousRenderable != this.root) + while(previousRenderable != this.root.first) { previousRenderable = previousRenderable._iPrev; if(previousRenderable.renderable && previousRenderable.__renderGroup)break; @@ -5733,7 +5904,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * scene graph */ var previousRenderable2 = end; - while(previousRenderable2 != this.root) + while(previousRenderable2 != this.root.first) { previousRenderable2 = previousRenderable2._iPrev; if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; @@ -6105,6 +6276,7 @@ PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) } } + /** * Initializes a tiling sprite * @@ -6175,23 +6347,19 @@ PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) { var gl = this.gl; - var shaderProgram = PIXI.shaderProgram; -// mat - //var mat4Real = PIXI.mat3.toMat4(strip.worldTransform); - //PIXI.mat4.transpose(mat4Real); - //PIXI.mat4.multiply(projectionMatrix, mat4Real, mat4Real ) - + var shaderProgram = PIXI.stripShaderProgram; - gl.useProgram(PIXI.stripShaderProgram); + + gl.useProgram(shaderProgram); var m = PIXI.mat3.clone(strip.worldTransform); PIXI.mat3.transpose(m); // set the matrix transform for the - gl.uniformMatrix3fv(PIXI.stripShaderProgram.translationMatrix, false, m); - gl.uniform2f(PIXI.stripShaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(PIXI.stripShaderProgram.alpha, strip.worldAlpha); + gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); + gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); /* if(strip.blendMode == PIXI.blendModes.NORMAL) @@ -6249,11 +6417,10 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } - //console.log(gl.TRIANGLE_STRIP); gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - gl.useProgram(PIXI.shaderProgram); + gl.useProgram(PIXI.currentProgram); } /** @@ -6328,6 +6495,7 @@ PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } + /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -6401,7 +6569,6 @@ PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; */ PIXI.CanvasRenderer.prototype.render = function(stage) { - // update children if need be //stage.__childrenAdded = []; //stage.__childrenRemoved = []; @@ -6410,6 +6577,7 @@ PIXI.CanvasRenderer.prototype.render = function(stage) PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; + PIXI.visibleCount++; stage.updateTransform(); // update the background color @@ -6496,7 +6664,7 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) var frame = displayObject.texture.frame; - if(frame) + if(frame && frame.width && frame.height) { context.globalAlpha = displayObject.worldAlpha; @@ -6534,31 +6702,34 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) } else if(displayObject instanceof PIXI.FilterBlock) { - if(displayObject.open) + if(PIXI.FilterBlock.data instanceof PIXI.Graphics) { - context.save(); - - var cacheAlpha = displayObject.mask.alpha; - var maskTransform = displayObject.mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - displayObject.mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); - // context.fillStyle = 0xFF0000; - // context.fillRect(0, 0, 200, 200); - context.clip(); - - displayObject.mask.worldAlpha = cacheAlpha; - //context.globalCompositeOperation = 'lighter'; + if(displayObject.open) + { + context.save(); + + var cacheAlpha = displayObject.mask.alpha; + var maskTransform = displayObject.mask.worldTransform; + + context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) + + displayObject.mask.worldAlpha = 0.5; + + context.worldAlpha = 0; + + PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); + context.clip(); + + displayObject.mask.worldAlpha = cacheAlpha; + } + else + { + context.restore(); + } } else { - //context.globalCompositeOperation = 'source-over'; - context.restore(); + // only masks supported right now! } } // count++ @@ -6651,7 +6822,7 @@ PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) PIXI.CanvasRenderer.prototype.renderStrip = function(strip) { var context = this.context; - //context.globalCompositeOperation = 'lighter'; + // draw triangles!! var verticies = strip.verticies; var uvs = strip.uvs; @@ -6678,8 +6849,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.lineTo(x2, y2); context.closePath(); - // context.fillStyle = "white"//rgb(1, 1, 1,1)); - // context.fill(); context.clip(); @@ -6703,7 +6872,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.restore(); }; -// context.globalCompositeOperation = 'source-over'; } /** @@ -6718,7 +6886,7 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) */ PIXI.CanvasGraphics = function() { - + } @@ -6734,35 +6902,33 @@ PIXI.CanvasGraphics = function() PIXI.CanvasGraphics.renderGraphics = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - - for (var i=0; i < graphics.graphicsData.length; i++) + + for (var i=0; i < graphics.graphicsData.length; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); context.lineWidth = data.lineWidth; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); - + context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6777,21 +6943,20 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.RECT) { - - // TODO - need to be Undefined! - if(data.fillColor) + + if(data.fillColor || data.fillColor === 0) { context.globalAlpha = data.fillAlpha * worldAlpha; context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); context.fillRect(points[0], points[1], points[2], points[3]); - + } if(data.lineWidth) { context.globalAlpha = data.lineAlpha * worldAlpha; context.strokeRect(points[0], points[1], points[2], points[3]); } - + } else if(data.type == PIXI.Graphics.CIRC) { @@ -6799,7 +6964,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.beginPath(); context.arc(points[0], points[1], points[2],0,2*Math.PI); context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6814,19 +6979,19 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - + var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6834,15 +6999,15 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - + context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6855,7 +7020,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.stroke(); } } - + }; } @@ -6871,37 +7036,35 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - + var len = graphics.graphicsData.length; if(len > 1) { len = 1; console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") } - - for (var i=0; i < 1; i++) + + for (var i=0; i < 1; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + } else if(data.type == PIXI.Graphics.RECT) { @@ -6918,18 +7081,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6937,7 +7100,7 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); @@ -6945,8 +7108,8 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); context.closePath(); } - - + + }; } @@ -6956,18 +7119,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) /** - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. + * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. * It is important to know that with the webGL renderer only simple polys can be filled at this stage * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png * - * @class Graphics + * @class Graphics * @extends DisplayObjectContainer * @constructor */ PIXI.Graphics = function() { PIXI.DisplayObjectContainer.call( this ); - + this.renderable = true; /** @@ -7028,14 +7191,14 @@ PIXI.Graphics.prototype.constructor = PIXI.Graphics; PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - + this.lineWidth = lineWidth || 0; this.lineColor = color || 0; this.lineAlpha = (alpha == undefined) ? 1 : alpha; - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.graphicsData.push(this.currentPath); } @@ -7049,12 +7212,12 @@ PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) PIXI.Graphics.prototype.moveTo = function(x, y) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.currentPath.points.push(x, y); - + this.graphicsData.push(this.currentPath); } @@ -7084,7 +7247,7 @@ PIXI.Graphics.prototype.beginFill = function(color, alpha) { this.filling = true; this.fillColor = color || 0; - this.fillAlpha = alpha || 1; + this.fillAlpha = (alpha == undefined) ? 1 : alpha; } /** @@ -7110,11 +7273,11 @@ PIXI.Graphics.prototype.endFill = function() PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.RECT}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7130,11 +7293,11 @@ PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) PIXI.Graphics.prototype.drawCircle = function( x, y, radius) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7151,11 +7314,11 @@ PIXI.Graphics.prototype.drawCircle = function( x, y, radius) PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.ELIP}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7169,7 +7332,7 @@ PIXI.Graphics.prototype.clear = function() { this.lineWidth = 0; this.filling = false; - + this.dirty = true; this.clearDirty = true; this.graphicsData = []; @@ -7190,20 +7353,20 @@ PIXI.Strip = function(texture, width, height) PIXI.DisplayObjectContainer.call( this ); this.texture = texture; this.blendMode = PIXI.blendModes.NORMAL; - + try { this.uvs = new Float32Array([0, 1, 1, 1, 1, 0, 0,1]); - + this.verticies = new Float32Array([0, 0, 0,0, 0,0, 0, 0, 0]); - + this.colors = new Float32Array([1, 1, 1, 1]); - + this.indices = new Uint16Array([0, 1, 2, 3]); } catch(error) @@ -7211,18 +7374,18 @@ PIXI.Strip = function(texture, width, height) this.uvs = [0, 1, 1, 1, 1, 0, 0,1]; - + this.verticies = [0, 0, 0,0, 0,0, 0, 0, 0]; - + this.colors = [1, 1, 1, 1]; - + this.indices = [0, 1, 2, 3]; } - - + + /* this.uvs = new Float32Array() this.verticies = new Float32Array() @@ -7231,7 +7394,7 @@ PIXI.Strip = function(texture, width, height) */ this.width = width; this.height = height; - + // load the texture! if(texture.baseTexture.hasLoaded) { @@ -7244,7 +7407,7 @@ PIXI.Strip = function(texture, width, height) this.onTextureUpdateBind = this.onTextureUpdate.bind(this); this.texture.addEventListener( 'update', this.onTextureUpdateBind ); } - + this.renderable = true; } @@ -7256,8 +7419,8 @@ PIXI.Strip.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.width = texture.frame.width; this.height = texture.frame.height; @@ -7280,7 +7443,7 @@ PIXI.Rope = function(texture, points) { PIXI.Strip.call( this, texture ); this.points = points; - + try { this.verticies = new Float32Array( points.length * 4); @@ -7291,12 +7454,12 @@ PIXI.Rope = function(texture, points) catch(error) { this.verticies = verticies - + this.uvs = uvs this.colors = colors this.indices = indices } - + this.refresh(); } @@ -7309,99 +7472,99 @@ PIXI.Rope.prototype.refresh = function() { var points = this.points; if(points.length < 1)return; - + var uvs = this.uvs var indices = this.indices; var colors = this.colors; - + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - + + uvs[0] = 0 uvs[1] = 1 uvs[2] = 0 uvs[3] = 1 - + colors[0] = 1; colors[1] = 1; - + indices[0] = 0; indices[1] = 1; - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; // time to do some smart drawing! var 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; } } PIXI.Rope.prototype.updateTransform = function() { - + var points = this.points; if(points.length < 1)return; - - var verticies = this.verticies - + + var verticies = this.verticies + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - verticies[0] = point.x + perp.x + + verticies[0] = point.x + perp.x verticies[1] = point.y + perp.y //+ 200 - verticies[2] = point.x - perp.x + verticies[2] = point.x - perp.x verticies[3] = point.y - perp.y//+200 // time to do some smart drawing! - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; - + if(i < points.length-1) { nextPoint = points[i+1]; @@ -7410,35 +7573,35 @@ PIXI.Rope.prototype.updateTransform = function() { nextPoint = point } - + perp.y = -(nextPoint.x - lastPoint.x); perp.x = nextPoint.y - lastPoint.y; - + var ratio = (1 - (i / (total-1))) * 10; if(ratio > 1)ratio = 1; - + var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); var 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; - - verticies[index] = point.x + perp.x + + verticies[index] = point.x + perp.x verticies[index+1] = point.y + perp.y - verticies[index+2] = point.x - perp.x + verticies[index+2] = point.x - perp.x verticies[index+3] = point.y - perp.y lastPoint = point; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); } PIXI.Rope.prototype.setTexture = function(texture) { - // stop current texture + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7494,7 +7657,7 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tileScale * @type Point - */ + */ this.tileScale = new PIXI.Point(1,1); /** @@ -7502,11 +7665,11 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tilePosition * @type Point - */ + */ this.tilePosition = new PIXI.Point(0,0); this.renderable = true; - + this.blendMode = PIXI.blendModes.NORMAL } @@ -7524,8 +7687,8 @@ PIXI.TilingSprite.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7546,10 +7709,10 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) /** * @author Mat Groves http://matgroves.com/ @Doormat23 * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * + * * Awesome JS run time provided by EsotericSoftware * https://github.com/EsotericSoftware/spine-runtimes - * + * */ /** @@ -7562,48 +7725,41 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) * @constructor * @param url {String} The url of the spine anim file to be used */ -PIXI.Spine = function(url) -{ +PIXI.Spine = function (url) { PIXI.DisplayObjectContainer.call(this); - + this.spineData = PIXI.AnimCache[url]; - - if(!this.spineData) - { + + if (!this.spineData) { throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: " + url); - return; } - - this.count = 0; - - this.sprites = []; - + this.skeleton = new spine.Skeleton(this.spineData); this.skeleton.updateWorldTransform(); - this.stateData = new spine.AnimationStateData(this.spineData); + this.stateData = new spine.AnimationStateData(this.spineData); this.state = new spine.AnimationState(this.stateData); - - // add the sprites.. - for (var i = 0; i < this.skeleton.drawOrder.length; i++) { - - var attachmentName = this.skeleton.drawOrder[i].data.attachmentName; - - // kind of an assumtion here. that its a png - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; - } - - - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(attachmentName)); - sprite.anchor.x = sprite.anchor.y = 0.5; - this.addChild(sprite); - this.sprites.push(sprite); - }; -} -PIXI.Spine.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); + 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)) { + continue; + } + var spriteName = attachment.rendererObject.name; + var sprite = this.createSprite(slot, attachment.rendererObject); + slot.currentSprite = sprite; + slot.currentSpriteName = spriteName; + slotContainer.addChild(sprite); + } +}; + +PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); PIXI.Spine.prototype.constructor = PIXI.Spine; /* @@ -7612,55 +7768,74 @@ PIXI.Spine.prototype.constructor = PIXI.Spine; * @method updateTransform * @private */ -PIXI.Spine.prototype.updateTransform = function() -{ - // TODO should make this time based really.. - this.state.update(1/60); +PIXI.Spine.prototype.updateTransform = function () { + this.lastTime = this.lastTime || Date.now(); + var timeDelta = (Date.now() - this.lastTime) * 0.001; + this.lastTime = Date.now(); + this.state.update(timeDelta); this.state.apply(this.skeleton); this.skeleton.updateWorldTransform(); - - for (var i = 0; i < this.skeleton.drawOrder.length; i++) - { - var slot = this.skeleton.drawOrder[i]; + 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 instanceof spine.RegionAttachment)) { + slotContainer.visible = false; + continue; + } - var x = slot.bone.worldX + slot.attachment.x * slot.bone.m00 + slot.attachment.y * slot.bone.m01 + slot.attachment.width * 0.5; - var y = slot.bone.worldY + slot.attachment.x * slot.bone.m10 + slot.attachment.y * slot.bone.m11 + slot.attachment.height * 0.5; - //console.log(x + ' : ' + y); - - - //console.log(slot.attachment.name) - if(slot.cacheName != slot.attachment.name) - { - var attachmentName = slot.attachment.name; - - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; + if (attachment.rendererObject) { + if (!slot.currentSpriteName || slot.currentSpriteName != attachment.name) { + var spriteName = attachment.rendererObject.name; + if (slot.currentSprite !== undefined) { + slot.currentSprite.visible = false; } - - this.sprites[i].setTexture(PIXI.TextureCache[attachmentName]); - - slot.cacheName = slot.attachment.name; + slot.sprites = slot.sprites || {}; + if (slot.sprites[spriteName] !== undefined) { + slot.sprites[spriteName].visible = true; + } else { + var sprite = this.createSprite(slot, attachment.rendererObject); + slotContainer.addChild(sprite); + } + slot.currentSprite = slot.sprites[spriteName]; + slot.currentSpriteName = spriteName; } - - x += -((slot.attachment.width * (slot.bone.worldScaleX + slot.attachment.scaleX - 1))>>1); - y += -((slot.attachment.height * (slot.bone.worldScaleY + slot.attachment.scaleY - 1))>>1); - - - this.sprites[i].position.x = x; - this.sprites[i].position.y = y; - this.sprites[i].rotation = (-(slot.bone.worldRotation + slot.attachment.rotation)) * (Math.PI/180); - } - + } + slotContainer.visible = true; + + 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 * Math.PI / 180); + } + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -} +}; + + +PIXI.Spine.prototype.createSprite = function (slot, descriptor) { + var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; + var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); + sprite.scale = descriptor.scale; + sprite.rotation = descriptor.rotation; + sprite.anchor.x = sprite.anchor.y = 0.5; + + slot.sprites = slot.sprites || {}; + slot.sprites[descriptor.name] = sprite; + return sprite; +}; /* * Awesome JS run time provided by EsotericSoftware - * + * * https://github.com/EsotericSoftware/spine-runtimes - * + * */ var spine = {}; @@ -7770,7 +7945,7 @@ spine.Slot.prototype = { this.g = data.g; this.b = data.b; this.a = data.a; - + var slotDatas = this.skeleton.data.slots; for (var i = 0, n = slotDatas.length; i < n; i++) { if (slotDatas[i] == data) { @@ -8001,6 +8176,7 @@ spine.TranslateTimeline.prototype = { var frameTime = frames[frameIndex]; var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); + bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; } @@ -8025,14 +8201,12 @@ spine.ScaleTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. - + var bone = skeleton.bones[this.boneIndex]; if (time >= frames[frames.length - 3]) { // Time is after last frame. bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - - return; } @@ -8070,6 +8244,7 @@ spine.ColorTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. + var slot = skeleton.slots[this.slotIndex]; if (time >= frames[frames.length - 5]) { // Time is after last frame. @@ -8119,7 +8294,7 @@ spine.AttachmentTimeline = function (frameCount) { spine.AttachmentTimeline.prototype = { slotIndex: 0, getFrameCount: function () { - return this.frames.length / 2; + return this.frames.length; }, setFrame: function (frameIndex, time, attachmentName) { this.frames[frameIndex] = time; @@ -8136,11 +8311,6 @@ spine.AttachmentTimeline.prototype = { frameIndex = spine.binarySearch(frames, time, 1) - 1; var attachmentName = this.attachmentNames[frameIndex]; - //console.log(skeleton.slots[this.slotIndex]) - - // change the name! - // skeleton.slots[this.slotIndex].attachmentName = attachmentName; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); } }; @@ -8312,11 +8482,9 @@ spine.Skeleton.prototype = { if (slot.data.name == slotName) { var attachment = null; if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; } - slot.setAttachment(attachment); return; } @@ -8398,7 +8566,6 @@ spine.RegionAttachment.prototype = { offset[7/*Y4*/] = localYCos + localX2Sin; }, computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; y += bone.worldY; var m00 = bone.m00; @@ -8422,6 +8589,7 @@ spine.AnimationStateData = function (skeletonData) { this.animationToMixTime = {}; }; spine.AnimationStateData.prototype = { + defaultMix: 0, setMixByName: function (fromName, toName, duration) { var from = this.skeletonData.findAnimation(fromName); if (!from) throw "Animation not found: " + fromName; @@ -8434,7 +8602,7 @@ spine.AnimationStateData.prototype = { }, getMix: function (from, to) { var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : 0; + return time ? time : this.defaultMix; } }; @@ -8474,7 +8642,7 @@ spine.AnimationState.prototype = { this.previous = null; } this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else + } else this.current.apply(skeleton, this.currentTime, this.currentLoop); }, clearAnimation: function () { @@ -8620,16 +8788,9 @@ spine.SkeletonJson.prototype = { name = map["name"] || name; var type = spine.AttachmentType[map["type"] || "region"]; - - // @ekelokorpi - // var attachment = this.attachmentLoader.newAttachment(skin, type, name); - var attachment = new spine.RegionAttachment(); - - // @Doormat23 - // add the name of the attachment - attachment.name = name; - + if (type == spine.AttachmentType.region) { + var attachment = new spine.RegionAttachment(); attachment.x = (map["x"] || 0) * this.scale; attachment.y = (map["y"] || 0) * this.scale; attachment.scaleX = map["scaleX"] || 1; @@ -8638,10 +8799,19 @@ spine.SkeletonJson.prototype = { attachment.width = (map["width"] || 32) * this.scale; attachment.height = (map["height"] || 32) * this.scale; attachment.updateOffset(); + + attachment.rendererObject = {}; + attachment.rendererObject.name = name; + attachment.rendererObject.scale = {}; + attachment.rendererObject.scale.x = attachment.scaleX; + attachment.rendererObject.scale.y = attachment.scaleY; + attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; + return attachment; } - return attachment; + throw "Unknown attachment type: " + type; }, + readAnimation: function (name, map, skeletonData) { var timelines = []; var duration = 0; @@ -8692,7 +8862,7 @@ spine.SkeletonJson.prototype = { } timelines.push(timeline); duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - + } else throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; } @@ -8735,8 +8905,8 @@ spine.SkeletonJson.prototype = { timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); } timelines.push(timeline); - // PIXI FIX - duration = Math.max(duration, timeline.frames[Math.floor(timeline.getFrameCount()) - 1]); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } else throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; } @@ -9005,14 +9175,14 @@ spine.Bone.yDown = true; /** * This object is one that will allow you to specify custom rendering functions based on render type * - * @class CustomRenderable + * @class CustomRenderable * @extends DisplayObject * @constructor */ PIXI.CustomRenderable = function() { PIXI.DisplayObject.call( this ); - + } // constructor @@ -9118,19 +9288,19 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } else { - + var scope = this; this.source.onload = function(){ - + scope.hasLoaded = true; scope.width = scope.source.width; scope.height = scope.source.height; - + // add it to somewhere... PIXI.texturesToUpdate.push(scope); scope.dispatchEvent( { type: 'loaded', content: scope } ); @@ -9143,7 +9313,7 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } @@ -9183,7 +9353,7 @@ PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) { // new Image() breaks tex loading in some versions of Chrome. // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); + var image = new Image();//document.createElement('img'); if (crossorigin) { image.crossOrigin = ''; @@ -9211,7 +9381,7 @@ PIXI.FrameCache = {}; * @uses EventTarget * @constructor * @param baseTexture {BaseTexture} The base texture source to create the texture from - * @param frmae {Rectangle} The rectangle frame of the texture to show + * @param frame {Rectangle} The rectangle frame of the texture to show */ PIXI.Texture = function(baseTexture, frame) { @@ -9256,7 +9426,7 @@ PIXI.Texture = function(baseTexture, frame) { if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); //console.log(frame) - + this.setFrame(frame); } else @@ -9335,13 +9505,13 @@ PIXI.Texture.prototype.setFrame = function(frame) PIXI.Texture.fromImage = function(imageUrl, crossorigin) { var texture = PIXI.TextureCache[imageUrl]; - + if(!texture) { texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); PIXI.TextureCache[imageUrl] = texture; } - + return texture; } @@ -9391,7 +9561,7 @@ PIXI.Texture.addTextureToCache = function(texture, id) } /** - * Remove a texture from the textureCache. + * Remove a texture from the textureCache. * * @static * @method removeTextureFromCache @@ -9503,15 +9673,7 @@ PIXI.RenderTexture.prototype.initWebGL = function() // create a projection matrix.. this.projection = new PIXI.Point(this.width/2 , this.height/2); -/* - this.projectionMatrix = PIXI.mat4.create(); - this.projectionMatrix[5] = 2/this.height// * 0.5; - this.projectionMatrix[13] = -1; - - this.projectionMatrix[0] = 2/this.width; - this.projectionMatrix[12] = -1; -*/ // set the correct render function.. this.render = this.renderWebGL; @@ -9525,10 +9687,6 @@ PIXI.RenderTexture.prototype.resize = function(width, height) this.width = width; this.height = height; - //this.frame.width = this.width - //this.frame.height = this.height; - - if(PIXI.gl) { this.projection.x = this.width/2 @@ -9592,6 +9750,7 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle var children = displayObject.children; //TODO -? create a new one??? dont think so! + var originalWorldTransform = displayObject.worldTransform; displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; // modify to flip... displayObject.worldTransform[4] = -1; @@ -9604,8 +9763,9 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle displayObject.worldTransform[5] -= position.y; } - - + PIXI.visibleCount++; + displayObject.vcount = PIXI.visibleCount; + for(var i=0,j=children.length; i- format + */ +PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) +{ + this.frames = []; + var cols = Math.floor(this.texture.width / frameWidth); + var rows = Math.floor(this.texture.height / frameHeight); + + var i=0; + for (var y=0; y x1 && x < x1 + this.width) + if(x >= x1 && x <= x1 + this.width) { var y1 = this.y; - - if(y > y1 && y < y1 + this.height) + + if(y >= y1 && y <= y1 + this.height) { return true; } @@ -165,7 +165,7 @@ PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; * @class Polygon * @constructor * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, - * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arugments passed can be + * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are * Numbers. @@ -232,9 +232,9 @@ PIXI.Polygon.prototype.contains = function(x, y) return inside; } +// constructor PIXI.Polygon.prototype.constructor = PIXI.Polygon; - /** * @author Chad Engler */ @@ -256,7 +256,7 @@ PIXI.Circle = function(x, y, radius) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number @@ -306,6 +306,7 @@ PIXI.Circle.prototype.contains = function(x, y) return (dx + dy <= r2); } +// constructor PIXI.Circle.prototype.constructor = PIXI.Circle; @@ -320,8 +321,8 @@ PIXI.Circle.prototype.constructor = PIXI.Circle; * @constructor * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse - * @param width {Number} The overall height of this ellipse - * @param height {Number} The overall width of this ellipse + * @param width {Number} The overall width of this ellipse + * @param height {Number} The overall height of this ellipse */ PIXI.Ellipse = function(x, y, width, height) { @@ -331,21 +332,21 @@ PIXI.Ellipse = function(x, y, width, height) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number * @default 0 */ this.y = y || 0; - + /** * @property width * @type Number * @default 0 */ this.width = width || 0; - + /** * @property height * @type Number @@ -394,11 +395,11 @@ PIXI.Ellipse.getBounds = function() return new PIXI.Rectangle(this.x, this.y, this.width, this.height); } +// constructor PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; - /* * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV * you both rock! @@ -426,7 +427,7 @@ PIXI.mat3.create = function() matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -442,7 +443,7 @@ PIXI.mat3.identity = function(matrix) matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -469,35 +470,35 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat3.multiply = function (mat, mat2, dest) +PIXI.mat3.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[0], a01 = mat[1], a02 = mat[2], a10 = mat[3], a11 = mat[4], a12 = mat[5], a20 = mat[6], a21 = mat[7], a22 = mat[8], - + b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; - + dest[0] = b00 * a00 + b01 * a10 + b02 * a20; dest[1] = b00 * a01 + b01 * a11 + b02 * a21; dest[2] = b00 * a02 + b01 * a12 + b02 * a22; - + dest[3] = b10 * a00 + b11 * a10 + b12 * a20; dest[4] = b10 * a01 + b11 * a11 + b12 * a21; dest[5] = b10 * a02 + b11 * a12 + b12 * a22; - + dest[6] = b20 * a00 + b21 * a10 + b22 * a20; dest[7] = b20 * a01 + b21 * a11 + b22 * a21; dest[8] = b20 * a02 + b21 * a12 + b22 * a22; - + return dest; } @@ -514,11 +515,11 @@ PIXI.mat3.clone = function(mat) matrix[6] = mat[6]; matrix[7] = mat[7]; matrix[8] = mat[8]; - + return matrix; } -PIXI.mat3.transpose = function (mat, dest) +PIXI.mat3.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values if (!dest || mat === dest) { @@ -546,30 +547,30 @@ PIXI.mat3.transpose = function (mat, dest) return dest; } -PIXI.mat3.toMat4 = function (mat, dest) +PIXI.mat3.toMat4 = function (mat, dest) { if (!dest) { dest = PIXI.mat4.create(); } - + dest[15] = 1; dest[14] = 0; dest[13] = 0; dest[12] = 0; - + dest[11] = 0; dest[10] = mat[8]; dest[9] = mat[7]; dest[8] = mat[6]; - + dest[7] = 0; dest[6] = mat[5]; dest[5] = mat[4]; dest[4] = mat[3]; - + dest[3] = 0; dest[2] = mat[2]; dest[1] = mat[1]; dest[0] = mat[0]; - + return dest; } @@ -597,19 +598,19 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat4.transpose = function (mat, dest) +PIXI.mat4.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) + if (!dest || mat === dest) { var a01 = mat[1], a02 = mat[2], a03 = mat[3], a12 = mat[6], a13 = mat[7], a23 = mat[11]; - + mat[1] = mat[4]; mat[2] = mat[8]; mat[3] = mat[12]; @@ -624,7 +625,7 @@ PIXI.mat4.transpose = function (mat, dest) mat[14] = a23; return mat; } - + dest[0] = mat[0]; dest[1] = mat[4]; dest[2] = mat[8]; @@ -644,18 +645,18 @@ PIXI.mat4.transpose = function (mat, dest) return dest; } -PIXI.mat4.multiply = function (mat, mat2, dest) +PIXI.mat4.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - + // Cache only the current line of the second matrix - var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; + var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; @@ -705,7 +706,6 @@ PIXI.DisplayObject = function() { this.last = this; this.first = this; - /** * The coordinate of the object relative to the local coordinates of the parent. * @@ -779,15 +779,6 @@ PIXI.DisplayObject = function() */ this.renderable = false; - /** - * [read-only] The visibility of the object based on world (parent) factors. - * - * @property worldVisible - * @type Boolean - * @readOnly - */ - this.worldVisible = false; - /** * [read-only] The display object container that contains this display object. * @@ -806,15 +797,6 @@ PIXI.DisplayObject = function() */ this.stage = null; - /** - * [read-only] The index of this object in the parent's `children` array - * - * @property childIndex - * @type Number - * @readOnly - */ - this.childIndex = 0; - /** * [read-only] The multiplied alpha of the displayobject * @@ -953,17 +935,6 @@ PIXI.DisplayObject = function() // constructor PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObject.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - } -});*/ - /** * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default * Instead of using this function you can now simply set the interactive property to true or false @@ -1011,16 +982,57 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { }, set: function(value) { - this._mask = value; - + if(value) { + if(this._mask) + { + value.start = this._mask.start; + value.end = this._mask.end; + } + else + { + this.addFilter(value); + value.renderable = false; + } + } + else + { + this.removeFilter(this._mask); + this._mask.renderable = true; + } + + this._mask = value; + } +}); + +/** + * Sets the filters for the displayObject. Currently there's a few limitations. + * 1: At the moment only one filter can be applied at a time.. + * 2: They cannot be nested. + * 3: There's no padding yet. + * 4: this is a webGL only feature. + * @property filters + * @type Array + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { + get: function() { + return this._filters; + }, + set: function(value) { + + //if(value == ) + if(value) + { + if(this._filters)this.removeFilter(this._filters); this.addFilter(value) } else { - this.removeFilter(); + if(this._filters)this.removeFilter(this._filters); } + + this._filters = value; } }); @@ -1031,19 +1043,21 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { * @param mask {Graphics} the graphics object to use as a filter * @private */ -PIXI.DisplayObject.prototype.addFilter = function(mask) +PIXI.DisplayObject.prototype.addFilter = function(data) { - if(this.filter)return; - this.filter = true; - + //if(this.filter)return; + //this.filter = true; // insert a filter block.. + // TODO Onject pool thease bad boys.. var start = new PIXI.FilterBlock(); var end = new PIXI.FilterBlock(); + data.start = start; + data.end = end; - start.mask = mask; - end.mask = mask; + start.data = data; + end.data = data; start.first = start.last = this; end.first = end.last = this; @@ -1051,9 +1065,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) start.open = true; /* - * * insert start - * */ var childFirst = start @@ -1084,9 +1096,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) // now insert the end filter block.. /* - * * insert end filter - * */ var childFirst = end var childLast = end @@ -1125,8 +1135,6 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) this.__renderGroup.addFilterBlocks(start, end); } - mask.renderable = false; - } /* @@ -1135,13 +1143,14 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) * @method removeFilter * @private */ -PIXI.DisplayObject.prototype.removeFilter = function() +PIXI.DisplayObject.prototype.removeFilter = function(data) { - if(!this.filter)return; - this.filter = false; - + //if(!this.filter)return; + //this.filter = false; + console.log("YUOIO") // modify the list.. - var startBlock = this.first; + var startBlock = data.start; + var nextObject = startBlock._iNext; var previousObject = startBlock._iPrev; @@ -1151,9 +1160,8 @@ PIXI.DisplayObject.prototype.removeFilter = function() this.first = startBlock._iNext; - // remove the end filter - var lastBlock = this.last; + var lastBlock = data.end; var nextObject = lastBlock._iNext; var previousObject = lastBlock._iPrev; @@ -1162,8 +1170,6 @@ PIXI.DisplayObject.prototype.removeFilter = function() previousObject._iNext = nextObject; // this is always true too! -// if(this.last == lastBlock) - //{ var tempLast = lastBlock._iPrev; // need to make sure the parents last is updated too var updateLast = this; @@ -1174,15 +1180,11 @@ PIXI.DisplayObject.prototype.removeFilter = function() if(!updateLast)break; } - var mask = startBlock.mask - mask.renderable = true; - // if webGL... if(this.__renderGroup) { this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); } - //} } /* @@ -1194,7 +1196,7 @@ PIXI.DisplayObject.prototype.removeFilter = function() PIXI.DisplayObject.prototype.updateTransform = function() { // TODO OPTIMIZE THIS!! with dirty - if(this.rotation != this.rotationCache) + if(this.rotation !== this.rotationCache) { this.rotationCache = this.rotation; this._sr = Math.sin(this.rotation); @@ -1236,9 +1238,12 @@ PIXI.DisplayObject.prototype.updateTransform = function() // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); this.worldAlpha = this.alpha * this.parent.worldAlpha; + + this.vcount = PIXI.visibleCount; } +PIXI.visibleCount = 0; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1270,18 +1275,6 @@ PIXI.DisplayObjectContainer = function() PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObjectContainer.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - - } -});*/ - /** * Adds a child to the container. * @@ -1299,11 +1292,10 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) } child.parent = this; - child.childIndex = this.children.length; this.children.push(child); - // updae the stage refference.. + // update the stage refference.. if(this.stage) { @@ -1326,7 +1318,7 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) var previousObject; // this could be wrong if there is a filter?? - if(this.filter) + if(this._filters) { previousObject = this.last._iPrev; } @@ -1338,7 +1330,6 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) nextObject = previousObject._iNext; // always true in this case - //this.last = child.last; // need to make sure the parents last is updated too var updateLast = this; var prevLast = previousObject; @@ -1402,7 +1393,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) } // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject; var previousObject; @@ -1410,7 +1401,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) if(index == this.children.length) { previousObject = this.last; - var updateLast = this;//.parent; + var updateLast = this; var prevLast = this.last; while(updateLast) { @@ -1539,7 +1530,7 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child) { // unlink // // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject = childLast._iNext; @@ -1609,7 +1600,6 @@ PIXI.DisplayObjectContainer.prototype.updateTransform = function() this.children[i].updateTransform(); } } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1739,9 +1729,18 @@ PIXI.Sprite.prototype.setTexture = function(texture) if(this.texture.baseTexture != texture.baseTexture) { this.textureChange = true; + this.texture = texture; + + if(this.__renderGroup) + { + this.__renderGroup.updateTexture(this); + } + } + else + { + this.texture = texture; } - this.texture = texture; this.updateFrame = true; } @@ -1798,7 +1797,6 @@ PIXI.Sprite.fromImage = function(imageId) return new PIXI.Sprite(texture); } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1814,7 +1812,7 @@ PIXI.Sprite.fromImage = function(imageId) PIXI.MovieClip = function(textures) { PIXI.Sprite.call(this, textures[0]); - + /** * The array of textures that make up the animation * @@ -1822,7 +1820,7 @@ PIXI.MovieClip = function(textures) * @type Array */ this.textures = textures; - + /** * The speed that the MovieClip will play at. Higher is faster, lower is slower * @@ -1848,7 +1846,7 @@ PIXI.MovieClip = function(textures) * @type Function */ this.onComplete = null; - + /** * [read-only] The index MovieClips current frame (this may not have to be a whole number) * @@ -1857,8 +1855,8 @@ PIXI.MovieClip = function(textures) * @default 0 * @readOnly */ - this.currentFrame = 0; - + this.currentFrame = 0; + /** * [read-only] Indicates if the MovieClip is currently playing * @@ -1873,6 +1871,23 @@ PIXI.MovieClip = function(textures) PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; +/** +* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures +* assigned to the MovieClip. +* +* @property totalFrames +* @type Number +* @default 0 +* @readOnly +*/ +Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { + get: function() { + + return this.textures.length; + } +}); + + /** * Stops the MovieClip * @@ -1928,11 +1943,13 @@ PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) PIXI.MovieClip.prototype.updateTransform = function() { PIXI.Sprite.prototype.updateTransform.call(this); - + if(!this.playing)return; - + this.currentFrame += this.animationSpeed; + var round = (this.currentFrame + 0.5) | 0; + if(this.loop || round < this.textures.length) { this.setTexture(this.textures[round % this.textures.length]); @@ -1952,14 +1969,49 @@ PIXI.MovieClip.prototype.updateTransform = function() -PIXI.FilterBlock = function(mask) +PIXI.FilterBlock = function() { - this.graphics = mask this.visible = true; this.renderable = true; } +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.ColorMatrixFilter = function() +{ + // set the uniforms + this.uniforms = { + matrix: {type: 'mat4', value: [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1]}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float invert;", + "uniform mat4 matrix;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", + "gl_FragColor = gl_FragColor * vColor;", + "}" + ]; + +} +Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { + get: function() { + return this.uniforms.matrix.value; + }, + set: function(value) { + this.uniforms.matrix.value = value; + } +}); /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1988,7 +2040,7 @@ PIXI.Text = function(text, style) this.setText(text); this.setStyle(style); - + this.updateText(); this.dirty = false; }; @@ -2030,7 +2082,7 @@ PIXI.Text.prototype.setStyle = function(style) * @methos setText * @param {String} text The copy that you would like the text to display */ -PIXI.Sprite.prototype.setText = function(text) +PIXI.Text.prototype.setText = function(text) { this.text = text.toString() || " "; this.dirty = true; @@ -2045,9 +2097,9 @@ PIXI.Sprite.prototype.setText = function(text) PIXI.Text.prototype.updateText = function() { this.context.font = this.style.font; - + var outputText = this.text; - + // word wrap // preserve original text if(this.style.wordWrap)outputText = this.wordWrap(this.text); @@ -2065,7 +2117,7 @@ PIXI.Text.prototype.updateText = function() maxLineWidth = Math.max(maxLineWidth, lineWidth); } this.canvas.width = maxLineWidth + this.style.strokeThickness; - + //calculate text height var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; this.canvas.height = lineHeight * lines.length; @@ -2073,7 +2125,7 @@ PIXI.Text.prototype.updateText = function() //set canvas text styles this.context.fillStyle = this.style.fill; this.context.font = this.style.font; - + this.context.strokeStyle = this.style.stroke; this.context.lineWidth = this.style.strokeThickness; @@ -2083,7 +2135,7 @@ PIXI.Text.prototype.updateText = function() for (i = 0; i < lines.length; i++) { var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); - + if(this.style.align == "right") { linePosition.x += maxLineWidth - lineWidths[i]; @@ -2103,7 +2155,7 @@ PIXI.Text.prototype.updateText = function() this.context.fillText(lines[i], linePosition.x, linePosition.y); } } - + this.updateTexture(); }; @@ -2119,10 +2171,10 @@ PIXI.Text.prototype.updateTexture = function() this.texture.baseTexture.height = this.canvas.height; this.texture.frame.width = this.canvas.width; this.texture.frame.height = this.canvas.height; - + this._width = this.canvas.width; this._height = this.canvas.height; - + PIXI.texturesToUpdate.push(this.texture.baseTexture); }; @@ -2136,10 +2188,10 @@ PIXI.Text.prototype.updateTransform = function() { if(this.dirty) { - this.updateText(); + this.updateText(); this.dirty = false; } - + PIXI.Sprite.prototype.updateTransform.call(this); }; @@ -2151,12 +2203,12 @@ PIXI.Text.prototype.updateTransform = function() * @param fontStyle {Object} * @private */ -PIXI.Text.prototype.determineFontHeight = function(fontStyle) +PIXI.Text.prototype.determineFontHeight = function(fontStyle) { // build a little reference dictionary so if the font style has been used return a // cached version... var result = PIXI.Text.heightCache[fontStyle]; - + if(!result) { var body = document.getElementsByTagName("body")[0]; @@ -2165,13 +2217,13 @@ PIXI.Text.prototype.determineFontHeight = function(fontStyle) dummy.appendChild(dummyText); dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); body.appendChild(dummy); - + result = dummy.offsetHeight; PIXI.Text.heightCache[fontStyle] = result; - + body.removeChild(dummy); } - + return result; }; @@ -2191,7 +2243,7 @@ PIXI.Text.prototype.wordWrap = function(text) if(p == start) { return 1; } - + if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) { if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) @@ -2208,7 +2260,7 @@ PIXI.Text.prototype.wordWrap = function(text) return arguments.callee(ctx, text, start, p, wrapWidth); } }; - + var lineWrap = function(ctx, text, wrapWidth) { if(ctx.measureText(text).width <= wrapWidth || text.length < 1) @@ -2218,14 +2270,14 @@ PIXI.Text.prototype.wordWrap = function(text) var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); }; - + var result = ""; var lines = text.split("\n"); for (var i = 0; i < lines.length; i++) { result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; } - + return result; }; @@ -2241,7 +2293,7 @@ PIXI.Text.prototype.destroy = function(destroyTexture) { this.texture.destroy(); } - + }; PIXI.Text.heightCache = {}; @@ -2252,7 +2304,7 @@ PIXI.Text.heightCache = {}; /** * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" - * You can generate the fnt files using + * You can generate the fnt files using * http://www.angelcode.com/products/bmfont/ for windows or * http://www.bmglyph.com/ for mac. * @@ -2342,7 +2394,7 @@ PIXI.BitmapText.prototype.updateText = function() prevCharCode = null; continue; } - + var charData = data.chars[charCode]; if(!charData) continue; @@ -2405,7 +2457,7 @@ PIXI.BitmapText.prototype.updateTransform = function() this.dirty = false; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); }; @@ -2414,10 +2466,8 @@ PIXI.BitmapText.fonts = {}; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ - - - -/** + + /** * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive * This manager also supports multitouch. * @@ -2451,6 +2501,8 @@ PIXI.InteractionManager = function(stage) */ this.touchs = {}; + + // helpers this.tempPoint = new PIXI.Point(); //this.tempMatrix = mat3.create(); @@ -2461,7 +2513,19 @@ PIXI.InteractionManager = function(stage) this.pool = []; this.interactiveItems = []; + this.interactionDOMElement = null; + //this will make it so that you dont have to call bind all the time + this.onMouseMove = this.onMouseMove.bind( this ); + this.onMouseDown = this.onMouseDown.bind(this); + this.onMouseOut = this.onMouseOut.bind(this); + this.onMouseUp = this.onMouseUp.bind(this); + + this.onTouchStart = this.onTouchStart.bind(this); + this.onTouchEnd = this.onTouchEnd.bind(this); + this.onTouchMove = this.onTouchMove.bind(this); + + this.last = 0; } @@ -2486,7 +2550,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj { var child = children[i]; - if(child.visible) { +// if(child.visible) { // push all interactive bits if(child.interactive) { @@ -2508,7 +2572,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj this.collectInteractiveSprite(child, iParent); } } - } +// } } } @@ -2521,27 +2585,68 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj */ PIXI.InteractionManager.prototype.setTarget = function(target) { + this.target = target; + + //check if the dom element has been set. If it has don't do anything + if( this.interactionDOMElement === null ) { + + this.setTargetDomElement( target.view ); + } + + document.body.addEventListener('mouseup', this.onMouseUp, true); +} + + +/** + * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM + * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element + * to receive those events + * + * @method setTargetDomElement + * @param domElement {DOMElement} the dom element which will receive mouse and touch events + * @private + */ +PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) +{ + //remove previouse listeners + if( this.interactionDOMElement !== null ) + { + this.interactionDOMElement.style['-ms-content-zooming'] = ''; + this.interactionDOMElement.style['-ms-touch-action'] = ''; + + this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); + this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); + this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); + this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); + this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); + } + + if (window.navigator.msPointerEnabled) { // time to remove some of that zoom in ja.. - target.view.style["-ms-content-zooming"] = "none"; - target.view.style["-ms-touch-action"] = "none" + domElement.style['-ms-content-zooming'] = 'none'; + domElement.style['-ms-touch-action'] = 'none'; // DO some window specific touch! } - - this.target = target; - target.view.addEventListener('mousemove', this.onMouseMove.bind(this), true); - target.view.addEventListener('mousedown', this.onMouseDown.bind(this), true); - document.body.addEventListener('mouseup', this.onMouseUp.bind(this), true); - target.view.addEventListener('mouseout', this.onMouseUp.bind(this), true); - - // aint no multi touch just yet! - target.view.addEventListener("touchstart", this.onTouchStart.bind(this), true); - target.view.addEventListener("touchend", this.onTouchEnd.bind(this), true); - target.view.addEventListener("touchmove", this.onTouchMove.bind(this), true); + + this.interactionDOMElement = domElement; + + domElement.addEventListener('mousemove', this.onMouseMove, true); + domElement.addEventListener('mousedown', this.onMouseDown, true); + domElement.addEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + domElement.addEventListener('touchstart', this.onTouchStart, true); + domElement.addEventListener('touchend', this.onTouchEnd, true); + domElement.addEventListener('touchmove', this.onTouchMove, true); } + /** * updates the state of interactive objects * @@ -2583,12 +2688,14 @@ PIXI.InteractionManager.prototype.update = function() // loop through interactive objects! var length = this.interactiveItems.length; - this.target.view.style.cursor = "default"; + this.interactionDOMElement.style.cursor = "default"; for (var i = 0; i < length; i++) { var item = this.interactiveItems[i]; - if(!item.visible)continue; + + + //if(!item.visible)continue; // OPTIMISATION - only calculate every time if the mousemove function exists.. // OK so.. does the object have any other interactive functions? @@ -2604,7 +2711,7 @@ PIXI.InteractionManager.prototype.update = function() // loks like there was a hit! if(item.__hit) { - if(item.buttonMode)this.target.view.style.cursor = "pointer"; + if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; if(!item.__isOver) { @@ -2639,7 +2746,7 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) { this.mouse.originalEvent = event || window.event; //IE uses window.event // TODO optimize by not check EVERY TIME! maybe half as often? // - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); @@ -2669,7 +2776,6 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) */ PIXI.InteractionManager.prototype.onMouseDown = function(event) { - event.preventDefault(); this.mouse.originalEvent = event || window.event; //IE uses window.event // loop through inteaction tree... @@ -2706,6 +2812,26 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) } } + +PIXI.InteractionManager.prototype.onMouseOut = function(event) +{ + var length = this.interactiveItems.length; + + this.interactionDOMElement.style.cursor = "default"; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.__isOver) + { + this.mouse.target = item; + if(item.mouseout)item.mouseout(this.mouse); + item.__isOver = false; + } + } +} + /** * Is called when the mouse button is released on the renderer element * @@ -2770,7 +2896,7 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) { var global = interactionData.global; - if(!item.visible)return false; + if(item.vcount !== PIXI.visibleCount)return false; var isSprite = (item instanceof PIXI.Sprite), worldTransform = item.worldTransform, @@ -2840,14 +2966,14 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) */ PIXI.InteractionManager.prototype.onTouchMove = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) { var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; + touchData.originalEvent = event || window.event; // update the touch position touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); @@ -2871,10 +2997,7 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) */ PIXI.InteractionManager.prototype.onTouchStart = function(event) { - event.preventDefault(); - this.mouse.originalEvent = event || window.event; //IE uses window.event - - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2884,6 +3007,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) var touchData = this.pool.pop(); if(!touchData)touchData = new PIXI.InteractionData(); + touchData.originalEvent = event || window.event; + this.touchs[touchEvent.identifier] = touchData; touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); @@ -2921,8 +3046,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) */ PIXI.InteractionManager.prototype.onTouchEnd = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + //this.mouse.originalEvent = event || window.event; //IE uses window.event + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2943,7 +3068,7 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) if(itemTouchData == touchData) { // so this one WAS down... - + touchData.originalEvent = event || window.event; // hitTest?? if(item.touchend || item.tap) @@ -3055,9 +3180,8 @@ PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; * @constructor * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format * like: 0xFFFFFF for white - * @param interactive {Boolean} enable / disable interaction (default is false) */ -PIXI.Stage = function(backgroundColor, interactive) +PIXI.Stage = function(backgroundColor) { PIXI.DisplayObjectContainer.call( this ); @@ -3077,7 +3201,7 @@ PIXI.Stage = function(backgroundColor, interactive) * @property interactive * @type Boolean */ - this.interactive = interactive; + this.interactive = true; /** * The interaction manage for this stage, manages all interactive activity on the stage @@ -3113,6 +3237,18 @@ PIXI.Stage = function(backgroundColor, interactive) PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); PIXI.Stage.prototype.constructor = PIXI.Stage; +/** + * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. + * This is useful for when you have other DOM elements ontop of the Canvas element. + * + * @method setInteractionDelegate + * @param domElement {DOMElement} This new domElement which will receive mouse/touch events + */ +PIXI.Stage.prototype.setInteractionDelegate = function(domElement) +{ + this.interactionManager.setTargetDomElement( domElement ); +} + /* * Updates the object transform for rendering * @@ -3122,6 +3258,7 @@ PIXI.Stage.prototype.constructor = PIXI.Stage; PIXI.Stage.prototype.updateTransform = function() { this.worldAlpha = 1; + this.vcount = PIXI.visibleCount; for(var i=0,j=this.children.length; i 100) { console.log("BREAK") break } - } + } } @@ -3361,14 +3466,14 @@ PIXI.runList = function(item) PIXI.EventTarget = function () { var listeners = {}; - + this.addEventListener = this.on = function ( type, listener ) { - - + + if ( listeners[ type ] === undefined ) { listeners[ type ] = []; - + } if ( listeners[ type ].indexOf( listener ) === - 1 ) { @@ -3379,11 +3484,17 @@ PIXI.EventTarget = function () { }; this.dispatchEvent = this.emit = function ( event ) { - - for ( var listener in listeners[ event.type ] ) { - listeners[ event.type ][ listener ]( event ); - + if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { + + return; + + } + + for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { + + listeners[ event.type ][ i ]( event ); + } }; @@ -3417,8 +3528,11 @@ PIXI.EventTarget = function () { * @param height {Number} the height of the renderers view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) + * + * antialias */ -PIXI.autoDetectRenderer = function(width, height, view, transparent) +PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) { if(!width)width = 800; if(!height)height = 600; @@ -3429,7 +3543,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) //console.log(webgl); if( webgl ) { - return new PIXI.WebGLRenderer(width, height, view, transparent); + return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); } return new PIXI.CanvasRenderer(width, height, view, transparent); @@ -3441,7 +3555,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) PolyK library url: http://polyk.ivank.net Released under MIT licence. - + Copyright (c) 2012 Ivan Kuckir Permission is hereby granted, free of charge, to any person @@ -3465,8 +3579,8 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - This is an amazing lib! - + This is an amazing lib! + slightly modified by mat groves (matgroves.com); */ @@ -3482,13 +3596,13 @@ PIXI.PolyK = {}; PIXI.PolyK.Triangulate = function(p) { var sign = true; - + var n = p.length>>1; if(n<3) return []; var tgs = []; var avl = []; for(var i=0; i 3) @@ -3496,11 +3610,11 @@ PIXI.PolyK.Triangulate = function(p) var i0 = avl[(i+0)%al]; var i1 = avl[(i+1)%al]; var i2 = avl[(i+2)%al]; - + var ax = p[2*i0], ay = p[2*i0+1]; var bx = p[2*i1], by = p[2*i1+1]; var cx = p[2*i2], cy = p[2*i2+1]; - + var earFound = false; if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) { @@ -3519,7 +3633,7 @@ PIXI.PolyK.Triangulate = function(p) al--; i = 0; } - else if(i++ > 3*al) + else if(i++ > 3*al) { // need to flip flip reverse it! // reset! @@ -3528,17 +3642,17 @@ PIXI.PolyK.Triangulate = function(p) var tgs = []; avl = []; for(var i=0; i= 0) == sign; } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -3612,13 +3725,11 @@ PIXI.shaderVertexSrc = [ "attribute vec2 aVertexPosition;", "attribute vec2 aTextureCoord;", "attribute float aColor;", - //"uniform mat4 uMVMatrix;", "uniform vec2 projectionVector;", "varying vec2 vTextureCoord;", "varying float vColor;", "void main(void) {", - // "gl_Position = uMVMatrix * vec4(aVertexPosition, 1.0, 1.0);", "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", "vTextureCoord = aTextureCoord;", "vColor = aColor;", @@ -3658,7 +3769,6 @@ PIXI.stripShaderVertexSrc = [ "}" ]; - /* * primitive shader.. */ @@ -3685,6 +3795,8 @@ PIXI.primitiveShaderVertexSrc = [ "}" ]; +PIXI.shaderStack = []; + PIXI.initPrimitiveShader = function() { var gl = PIXI.gl; @@ -3699,27 +3811,26 @@ PIXI.initPrimitiveShader = function() shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); + + //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(shaderProgram.colorAttribute); +//gl.enableVertexAttribArray(program.textureCoordAttribute); + shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); PIXI.primitiveProgram = shaderProgram; + + } PIXI.initDefaultShader = function() { - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.shaderVertexSrc, PIXI.shaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - // shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.shaderProgram = shaderProgram; + PIXI.defaultShader = new PIXI.PixiShader(); + PIXI.defaultShader.init(); + PIXI.activateShader(PIXI.defaultShader); + /* + PIXI.shaderStack.push(PIXI.defaultShader); + PIXI.current*/ } PIXI.initDefaultStripShader = function() @@ -3736,9 +3847,7 @@ PIXI.initDefaultStripShader = function() shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); PIXI.stripShaderProgram = shaderProgram; @@ -3789,35 +3898,135 @@ PIXI.compileProgram = function(vertexSrc, fragmentSrc) return shaderProgram; } +PIXI.activateShader = function(shader) +{ + PIXI.shaderStack.push(shader); + + //console.log(">>>") + var gl = PIXI.gl; + + var shaderProgram = shader.program; + + // map uniforms.. + gl.useProgram(shaderProgram); + + gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + gl.enableVertexAttribArray(shaderProgram.colorAttribute); + gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); -PIXI.activateDefaultShader = function() + shader.syncUniforms(); + + PIXI.currentShader = shaderProgram; +} + + +PIXI.popShader = function() { var gl = PIXI.gl; - var shaderProgram = PIXI.shaderProgram; + // activate last program.. + var lastProgram = PIXI.shaderStack.pop(); + + var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); + PIXI.currentShader = shaderProgram; } - - PIXI.activatePrimitiveShader = function() { var gl = PIXI.gl; - gl.disableVertexAttribArray(PIXI.shaderProgram.textureCoordAttribute); - gl.disableVertexAttribArray(PIXI.shaderProgram.colorAttribute); - gl.useProgram(PIXI.primitiveProgram); - gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); + gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + + //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); } +PIXI.deactivatePrimitiveShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.currentShader); + + gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.PixiShader = function() +{ + // the webGL program.. + this.program; + + this.fragmentSrc = [ + "precision lowp float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", + "}" + ]; + +} + +PIXI.PixiShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get the default shader bits! + program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); + program.colorAttribute = gl.getAttribLocation(program, "aColor"); + program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); + + program.projectionVector = gl.getUniformLocation(program, "projectionVector"); + program.samplerUniform = gl.getUniformLocation(program, "uSampler"); + + // add those custom shaders! + for (var key in this.uniforms) + { + // get the uniform locations.. + program[key] = gl.getUniformLocation(program, key); + } + + this.program = program; +} + +PIXI.PixiShader.prototype.syncUniforms = function() +{ + var gl = PIXI.gl; + + for (var key in this.uniforms) + { + //var + var type = this.uniforms[key].type; + + // need to grow this! + if(type == "f") + { + gl.uniform1f(this.program[key], this.uniforms[key].value); + } + else if(type == "mat4") + { + gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); + } + } + +} + /** * @author Mat Groves http://matgroves.com/ @Doormat23 @@ -3887,7 +4096,7 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); // WHY DOES THIS LINE NEED TO BE THERE??? - gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // its not even used.. but need to be set or it breaks? // only on pc though.. @@ -3899,8 +4108,10 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); + PIXI.deactivatePrimitiveShader(); + // return to default shader... - PIXI.activateDefaultShader(); +// PIXI.activateShader(PIXI.defaultShader); } /** @@ -4243,7 +4454,7 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) verts.push(px , py); verts.push(r, g, b, alpha); - verts.push(p2x - (px-p2x), p2y - (py - p2y));//, 4); + verts.push(p2x - (px-p2x), p2y - (py - p2y)); verts.push(r, g, b, alpha); } } @@ -4356,9 +4567,10 @@ PIXI.gl; * @param height=0 {Number} the height of the canvas view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) * */ -PIXI.WebGLRenderer = function(width, height, view, transparent) +PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) { // do a catch.. only 1 webGL renderer.. @@ -4382,7 +4594,7 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) { PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { alpha: this.transparent, - antialias:true, // SPEED UP?? + antialias:!!antialias, // SPEED UP?? premultipliedAlpha:false, stencil:true }); @@ -4392,11 +4604,12 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); } - PIXI.initPrimitiveShader(); PIXI.initDefaultShader(); + PIXI.initPrimitiveShader(); PIXI.initDefaultStripShader(); - PIXI.activateDefaultShader(); + +// PIXI.activateDefaultShader(); var gl = this.gl; PIXI.WebGLRenderer.gl = gl; @@ -4413,7 +4626,10 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) this.resize(this.width, this.height); this.contextLost = false; + PIXI.activateShader(PIXI.defaultShader); + this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); + } // constructor @@ -4469,8 +4685,6 @@ PIXI.WebGLRenderer.prototype.render = function(stage) { // TODO make this work // dont think this is needed any more? - //if(this.__stage)this.checkVisibility(this.__stage, false) - this.__stage = stage; this.stageRenderGroup.setRenderable(stage); } @@ -4487,10 +4701,8 @@ PIXI.WebGLRenderer.prototype.render = function(stage) // update any textures PIXI.WebGLRenderer.updateTextures(); - // recursivly loop through all items! - //this.checkVisibility(stage, true); - // update the scene graph + PIXI.visibleCount++; stage.updateTransform(); var gl = this.gl; @@ -4499,16 +4711,12 @@ PIXI.WebGLRenderer.prototype.render = function(stage) gl.colorMask(true, true, true, this.transparent); gl.viewport(0, 0, this.width, this.height); - // set the correct matrix.. - // gl.uniformMatrix4fv(this.shaderProgram.mvMatrixUniform, false, this.projectionMatrix); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); gl.clear(gl.COLOR_BUFFER_BIT); // HACK TO TEST - //PIXI.projectionMatrix = this.projectionMatrix; this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; this.stageRenderGroup.render(PIXI.projection); @@ -4546,8 +4754,9 @@ PIXI.WebGLRenderer.prototype.render = function(stage) */ PIXI.WebGLRenderer.updateTextures = function() { - for (var i=0; i < PIXI.texturesToUpdate.length; i++) this.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) this.destroyTexture(PIXI.texturesToDestroy[i]); + //TODO break this out into a texture manager... + for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); + for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; } @@ -4562,6 +4771,7 @@ PIXI.WebGLRenderer.updateTextures = function() */ PIXI.WebGLRenderer.updateTexture = function(texture) { + //TODO break this out into a texture manager... var gl = PIXI.gl; if(!texture._glTexture) @@ -4602,9 +4812,10 @@ PIXI.WebGLRenderer.updateTexture = function(texture) * @param texture {Texture} The texture to update * @private */ -PIXI.WebGLRenderer.prototype.destroyTexture = function(texture) +PIXI.WebGLRenderer.destroyTexture = function(texture) { - var gl = this.gl; + //TODO break this out into a texture manager... + var gl = PIXI.gl; if(texture._glTexture) { @@ -4768,7 +4979,6 @@ PIXI.WebGLBatch.prototype.clean = function() this.uvs = []; this.indices = []; this.colors = []; - //this.sprites = []; this.dynamicSize = 1; this.texture = null; this.last = null; @@ -4805,7 +5015,6 @@ PIXI.WebGLBatch.prototype.init = function(sprite) this.dirty = true; this.blendMode = sprite.blendMode; this.texture = sprite.texture.baseTexture; -// this.sprites.push(sprite); this.head = sprite; this.tail = sprite; this.size = 1; @@ -4838,7 +5047,6 @@ PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) else { this.head = sprite; - //this.head.__prev = null } } @@ -4926,7 +5134,7 @@ PIXI.WebGLBatch.prototype.split = function(sprite) { this.dirty = true; - var batch = new PIXI.WebGLBatch(this.gl);//PIXI._getBatch(this.gl); + var batch = new PIXI.WebGLBatch(this.gl); batch.init(sprite); batch.texture = this.texture; batch.tail = this.tail; @@ -4936,8 +5144,6 @@ PIXI.WebGLBatch.prototype.split = function(sprite) sprite.__prev = null; // return a splite batch! - //sprite.__prev.__next = null; - //sprite.__prev = null; // TODO this size is wrong! // need to recalculate :/ problem with a linked list! @@ -5007,13 +5213,13 @@ PIXI.WebGLBatch.prototype.growBatch = function() gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); - this.uvs = new Float32Array( this.dynamicSize * 8 ) + this.uvs = new Float32Array( this.dynamicSize * 8 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); this.dirtyUVS = true; - this.colors = new Float32Array( this.dynamicSize * 4 ) + this.colors = new Float32Array( this.dynamicSize * 4 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); @@ -5112,7 +5318,7 @@ PIXI.WebGLBatch.prototype.update = function() while(displayObject) { - if(displayObject.worldVisible) + if(displayObject.vcount === PIXI.visibleCount) { width = displayObject.texture.frame.width; height = displayObject.texture.frame.height; @@ -5214,7 +5420,7 @@ PIXI.WebGLBatch.prototype.update = function() PIXI.WebGLBatch.prototype.render = function(start, end) { start = start || 0; - //end = end || this.size; + if(end == undefined)end = this.size; if(this.dirty) @@ -5230,8 +5436,9 @@ PIXI.WebGLBatch.prototype.render = function(start, end) //TODO optimize this! - var shaderProgram = PIXI.shaderProgram; - gl.useProgram(shaderProgram); + var shaderProgram = PIXI.currentShader; + + //gl.useProgram(shaderProgram); // update the verts.. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); @@ -5239,6 +5446,8 @@ PIXI.WebGLBatch.prototype.render = function(start, end) gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // update the uvs + var isDefault = (shaderProgram == PIXI.shaderProgram) + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); if(this.dirtyUVS) @@ -5262,13 +5471,11 @@ PIXI.WebGLBatch.prototype.render = function(start, end) } gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - //var startIndex = 0//1; var len = end - start; - // console.log(this.size) + // DRAW THAT this! gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); } @@ -5336,77 +5543,45 @@ PIXI.WebGLRenderGroup.prototype.render = function(projection) PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - // TODO remove this by replacing visible with getter setters.. - this.checkVisibility(this.root, this.root.visible); - // will render all the elements in the group var renderable; - - for (var i=0; i < this.batchs.length; i++) { + renderable = this.batchs[i]; if(renderable instanceof PIXI.WebGLBatch) { this.batchs[i].render(); + continue; } - else if(renderable instanceof PIXI.TilingSprite) + + // non sprite batch.. + var worldVisible = renderable.vcount === PIXI.visibleCount; + + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ - if(renderable.open) - { - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - gl.colorMask(true, true, true, false); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - else - { - gl.disable(gl.STENCIL_TEST); - } + this.handleFilterBlock(renderable, projection); } } } -/** - * Renders the stage to its webgl view - * - * @method handleFilter - * @param filter {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.handleFilter = function(filter, projection) -{ - -} - /** * Renders a specific displayObject * @@ -5420,11 +5595,8 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - this.checkVisibility(displayObject, displayObject.visible); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); -// gl.uniformMatrix4fv(PIXI.shaderProgram.mvMatrixUniform, false, projectionMatrix); - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); - // to do! // render part of the scene... @@ -5483,7 +5655,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project while(lastItem.children.length > 0) { lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem; + if(lastItem.renderable)lastRenderable = lastItem.last; } if(lastRenderable instanceof PIXI.Sprite) @@ -5577,45 +5749,80 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project */ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) { + var sta = PIXI.shaderStack.length; + + var worldVisible = renderable.vcount === PIXI.visibleCount + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.CustomRenderable) { - if(renderable.visible) renderable.renderWebGL(this, projection); + if(worldVisible) renderable.renderWebGL(this, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ + this.handleFilterBlock(renderable, projection); + } +} - var gl = PIXI.gl; +PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) +{ + /* + * for now only masks are supported.. + */ + var gl = PIXI.gl; - if(renderable.open) + if(renderable.open) + { + if(renderable.data instanceof Array) + { + var filter = renderable.data[0]; + + if(!filter.shader) + { + var shader = new PIXI.PixiShader(); + + shader.fragmentSrc = filter.fragmentSrc; + shader.uniforms = filter.uniforms; + shader.init(); + + filter.shader = shader + } + + PIXI.activateShader(filter.shader); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } + else { gl.enable(gl.STENCIL_TEST); gl.colorMask(false, false, false, false); gl.stencilFunc(gl.ALWAYS,1,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - // we know this is a render texture so enable alpha too.. + PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); + gl.colorMask(true, true, true, true); gl.stencilFunc(gl.NOTEQUAL,0,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); } + } + else + { + if(renderable.data instanceof Array) + { + PIXI.popShader(); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } else { gl.disable(gl.STENCIL_TEST); @@ -5623,42 +5830,6 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) } } -/** - * Checks the visibility of a displayObject - * - * @method checkVisibility - * @param displayObject {DisplayObject} - * @param globalVisible {Boolean} - * @private - */ -PIXI.WebGLRenderGroup.prototype.checkVisibility = function(displayObject, globalVisible) -{ - // give the dp a reference to its renderGroup... - var children = displayObject.children; - //displayObject.worldVisible = globalVisible; - for (var i=0; i < children.length; i++) - { - var child = children[i]; - - // TODO optimize... should'nt need to loop through everything all the time - child.worldVisible = child.visible && globalVisible; - - // everything should have a batch! - // time to see whats new! - if(child.textureChange) - { - child.textureChange = false; - if(child.worldVisible)this.updateTexture(child); - // update texture!! - } - - if(child.children.length > 0) - { - this.checkVisibility(child, child.worldVisible); - } - }; -} - /** * Updates a webgl texture * @@ -5719,7 +5890,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * It keeps going back until it finds a sprite or the stage */ var previousRenderable = start; - while(previousRenderable != this.root) + while(previousRenderable != this.root.first) { previousRenderable = previousRenderable._iPrev; if(previousRenderable.renderable && previousRenderable.__renderGroup)break; @@ -5733,7 +5904,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * scene graph */ var previousRenderable2 = end; - while(previousRenderable2 != this.root) + while(previousRenderable2 != this.root.first) { previousRenderable2 = previousRenderable2._iPrev; if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; @@ -6105,6 +6276,7 @@ PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) } } + /** * Initializes a tiling sprite * @@ -6175,23 +6347,19 @@ PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) { var gl = this.gl; - var shaderProgram = PIXI.shaderProgram; -// mat - //var mat4Real = PIXI.mat3.toMat4(strip.worldTransform); - //PIXI.mat4.transpose(mat4Real); - //PIXI.mat4.multiply(projectionMatrix, mat4Real, mat4Real ) - + var shaderProgram = PIXI.stripShaderProgram; - gl.useProgram(PIXI.stripShaderProgram); + + gl.useProgram(shaderProgram); var m = PIXI.mat3.clone(strip.worldTransform); PIXI.mat3.transpose(m); // set the matrix transform for the - gl.uniformMatrix3fv(PIXI.stripShaderProgram.translationMatrix, false, m); - gl.uniform2f(PIXI.stripShaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(PIXI.stripShaderProgram.alpha, strip.worldAlpha); + gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); + gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); /* if(strip.blendMode == PIXI.blendModes.NORMAL) @@ -6249,11 +6417,10 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } - //console.log(gl.TRIANGLE_STRIP); gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - gl.useProgram(PIXI.shaderProgram); + gl.useProgram(PIXI.currentProgram); } /** @@ -6328,6 +6495,7 @@ PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } + /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -6401,7 +6569,6 @@ PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; */ PIXI.CanvasRenderer.prototype.render = function(stage) { - // update children if need be //stage.__childrenAdded = []; //stage.__childrenRemoved = []; @@ -6410,6 +6577,7 @@ PIXI.CanvasRenderer.prototype.render = function(stage) PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; + PIXI.visibleCount++; stage.updateTransform(); // update the background color @@ -6496,7 +6664,7 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) var frame = displayObject.texture.frame; - if(frame) + if(frame && frame.width && frame.height) { context.globalAlpha = displayObject.worldAlpha; @@ -6534,31 +6702,34 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) } else if(displayObject instanceof PIXI.FilterBlock) { - if(displayObject.open) + if(PIXI.FilterBlock.data instanceof PIXI.Graphics) { - context.save(); - - var cacheAlpha = displayObject.mask.alpha; - var maskTransform = displayObject.mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - displayObject.mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); - // context.fillStyle = 0xFF0000; - // context.fillRect(0, 0, 200, 200); - context.clip(); - - displayObject.mask.worldAlpha = cacheAlpha; - //context.globalCompositeOperation = 'lighter'; + if(displayObject.open) + { + context.save(); + + var cacheAlpha = displayObject.mask.alpha; + var maskTransform = displayObject.mask.worldTransform; + + context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) + + displayObject.mask.worldAlpha = 0.5; + + context.worldAlpha = 0; + + PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); + context.clip(); + + displayObject.mask.worldAlpha = cacheAlpha; + } + else + { + context.restore(); + } } else { - //context.globalCompositeOperation = 'source-over'; - context.restore(); + // only masks supported right now! } } // count++ @@ -6651,7 +6822,7 @@ PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) PIXI.CanvasRenderer.prototype.renderStrip = function(strip) { var context = this.context; - //context.globalCompositeOperation = 'lighter'; + // draw triangles!! var verticies = strip.verticies; var uvs = strip.uvs; @@ -6678,8 +6849,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.lineTo(x2, y2); context.closePath(); - // context.fillStyle = "white"//rgb(1, 1, 1,1)); - // context.fill(); context.clip(); @@ -6703,7 +6872,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.restore(); }; -// context.globalCompositeOperation = 'source-over'; } /** @@ -6718,7 +6886,7 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) */ PIXI.CanvasGraphics = function() { - + } @@ -6734,35 +6902,33 @@ PIXI.CanvasGraphics = function() PIXI.CanvasGraphics.renderGraphics = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - - for (var i=0; i < graphics.graphicsData.length; i++) + + for (var i=0; i < graphics.graphicsData.length; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); context.lineWidth = data.lineWidth; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); - + context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6777,21 +6943,20 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.RECT) { - - // TODO - need to be Undefined! - if(data.fillColor) + + if(data.fillColor || data.fillColor === 0) { context.globalAlpha = data.fillAlpha * worldAlpha; context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); context.fillRect(points[0], points[1], points[2], points[3]); - + } if(data.lineWidth) { context.globalAlpha = data.lineAlpha * worldAlpha; context.strokeRect(points[0], points[1], points[2], points[3]); } - + } else if(data.type == PIXI.Graphics.CIRC) { @@ -6799,7 +6964,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.beginPath(); context.arc(points[0], points[1], points[2],0,2*Math.PI); context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6814,19 +6979,19 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - + var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6834,15 +6999,15 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - + context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6855,7 +7020,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.stroke(); } } - + }; } @@ -6871,37 +7036,35 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - + var len = graphics.graphicsData.length; if(len > 1) { len = 1; console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") } - - for (var i=0; i < 1; i++) + + for (var i=0; i < 1; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + } else if(data.type == PIXI.Graphics.RECT) { @@ -6918,18 +7081,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6937,7 +7100,7 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); @@ -6945,8 +7108,8 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); context.closePath(); } - - + + }; } @@ -6956,18 +7119,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) /** - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. + * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. * It is important to know that with the webGL renderer only simple polys can be filled at this stage * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png * - * @class Graphics + * @class Graphics * @extends DisplayObjectContainer * @constructor */ PIXI.Graphics = function() { PIXI.DisplayObjectContainer.call( this ); - + this.renderable = true; /** @@ -7028,14 +7191,14 @@ PIXI.Graphics.prototype.constructor = PIXI.Graphics; PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - + this.lineWidth = lineWidth || 0; this.lineColor = color || 0; this.lineAlpha = (alpha == undefined) ? 1 : alpha; - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.graphicsData.push(this.currentPath); } @@ -7049,12 +7212,12 @@ PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) PIXI.Graphics.prototype.moveTo = function(x, y) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.currentPath.points.push(x, y); - + this.graphicsData.push(this.currentPath); } @@ -7084,7 +7247,7 @@ PIXI.Graphics.prototype.beginFill = function(color, alpha) { this.filling = true; this.fillColor = color || 0; - this.fillAlpha = alpha || 1; + this.fillAlpha = (alpha == undefined) ? 1 : alpha; } /** @@ -7110,11 +7273,11 @@ PIXI.Graphics.prototype.endFill = function() PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.RECT}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7130,11 +7293,11 @@ PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) PIXI.Graphics.prototype.drawCircle = function( x, y, radius) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7151,11 +7314,11 @@ PIXI.Graphics.prototype.drawCircle = function( x, y, radius) PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.ELIP}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7169,7 +7332,7 @@ PIXI.Graphics.prototype.clear = function() { this.lineWidth = 0; this.filling = false; - + this.dirty = true; this.clearDirty = true; this.graphicsData = []; @@ -7190,20 +7353,20 @@ PIXI.Strip = function(texture, width, height) PIXI.DisplayObjectContainer.call( this ); this.texture = texture; this.blendMode = PIXI.blendModes.NORMAL; - + try { this.uvs = new Float32Array([0, 1, 1, 1, 1, 0, 0,1]); - + this.verticies = new Float32Array([0, 0, 0,0, 0,0, 0, 0, 0]); - + this.colors = new Float32Array([1, 1, 1, 1]); - + this.indices = new Uint16Array([0, 1, 2, 3]); } catch(error) @@ -7211,18 +7374,18 @@ PIXI.Strip = function(texture, width, height) this.uvs = [0, 1, 1, 1, 1, 0, 0,1]; - + this.verticies = [0, 0, 0,0, 0,0, 0, 0, 0]; - + this.colors = [1, 1, 1, 1]; - + this.indices = [0, 1, 2, 3]; } - - + + /* this.uvs = new Float32Array() this.verticies = new Float32Array() @@ -7231,7 +7394,7 @@ PIXI.Strip = function(texture, width, height) */ this.width = width; this.height = height; - + // load the texture! if(texture.baseTexture.hasLoaded) { @@ -7244,7 +7407,7 @@ PIXI.Strip = function(texture, width, height) this.onTextureUpdateBind = this.onTextureUpdate.bind(this); this.texture.addEventListener( 'update', this.onTextureUpdateBind ); } - + this.renderable = true; } @@ -7256,8 +7419,8 @@ PIXI.Strip.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.width = texture.frame.width; this.height = texture.frame.height; @@ -7280,7 +7443,7 @@ PIXI.Rope = function(texture, points) { PIXI.Strip.call( this, texture ); this.points = points; - + try { this.verticies = new Float32Array( points.length * 4); @@ -7291,12 +7454,12 @@ PIXI.Rope = function(texture, points) catch(error) { this.verticies = verticies - + this.uvs = uvs this.colors = colors this.indices = indices } - + this.refresh(); } @@ -7309,99 +7472,99 @@ PIXI.Rope.prototype.refresh = function() { var points = this.points; if(points.length < 1)return; - + var uvs = this.uvs var indices = this.indices; var colors = this.colors; - + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - + + uvs[0] = 0 uvs[1] = 1 uvs[2] = 0 uvs[3] = 1 - + colors[0] = 1; colors[1] = 1; - + indices[0] = 0; indices[1] = 1; - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; // time to do some smart drawing! var 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; } } PIXI.Rope.prototype.updateTransform = function() { - + var points = this.points; if(points.length < 1)return; - - var verticies = this.verticies - + + var verticies = this.verticies + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - verticies[0] = point.x + perp.x + + verticies[0] = point.x + perp.x verticies[1] = point.y + perp.y //+ 200 - verticies[2] = point.x - perp.x + verticies[2] = point.x - perp.x verticies[3] = point.y - perp.y//+200 // time to do some smart drawing! - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; - + if(i < points.length-1) { nextPoint = points[i+1]; @@ -7410,35 +7573,35 @@ PIXI.Rope.prototype.updateTransform = function() { nextPoint = point } - + perp.y = -(nextPoint.x - lastPoint.x); perp.x = nextPoint.y - lastPoint.y; - + var ratio = (1 - (i / (total-1))) * 10; if(ratio > 1)ratio = 1; - + var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); var 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; - - verticies[index] = point.x + perp.x + + verticies[index] = point.x + perp.x verticies[index+1] = point.y + perp.y - verticies[index+2] = point.x - perp.x + verticies[index+2] = point.x - perp.x verticies[index+3] = point.y - perp.y lastPoint = point; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); } PIXI.Rope.prototype.setTexture = function(texture) { - // stop current texture + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7494,7 +7657,7 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tileScale * @type Point - */ + */ this.tileScale = new PIXI.Point(1,1); /** @@ -7502,11 +7665,11 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tilePosition * @type Point - */ + */ this.tilePosition = new PIXI.Point(0,0); this.renderable = true; - + this.blendMode = PIXI.blendModes.NORMAL } @@ -7524,8 +7687,8 @@ PIXI.TilingSprite.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7546,10 +7709,10 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) /** * @author Mat Groves http://matgroves.com/ @Doormat23 * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * + * * Awesome JS run time provided by EsotericSoftware * https://github.com/EsotericSoftware/spine-runtimes - * + * */ /** @@ -7562,48 +7725,41 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) * @constructor * @param url {String} The url of the spine anim file to be used */ -PIXI.Spine = function(url) -{ +PIXI.Spine = function (url) { PIXI.DisplayObjectContainer.call(this); - + this.spineData = PIXI.AnimCache[url]; - - if(!this.spineData) - { + + if (!this.spineData) { throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: " + url); - return; } - - this.count = 0; - - this.sprites = []; - + this.skeleton = new spine.Skeleton(this.spineData); this.skeleton.updateWorldTransform(); - this.stateData = new spine.AnimationStateData(this.spineData); + this.stateData = new spine.AnimationStateData(this.spineData); this.state = new spine.AnimationState(this.stateData); - - // add the sprites.. - for (var i = 0; i < this.skeleton.drawOrder.length; i++) { - - var attachmentName = this.skeleton.drawOrder[i].data.attachmentName; - - // kind of an assumtion here. that its a png - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; - } - - - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(attachmentName)); - sprite.anchor.x = sprite.anchor.y = 0.5; - this.addChild(sprite); - this.sprites.push(sprite); - }; -} -PIXI.Spine.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); + 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)) { + continue; + } + var spriteName = attachment.rendererObject.name; + var sprite = this.createSprite(slot, attachment.rendererObject); + slot.currentSprite = sprite; + slot.currentSpriteName = spriteName; + slotContainer.addChild(sprite); + } +}; + +PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); PIXI.Spine.prototype.constructor = PIXI.Spine; /* @@ -7612,55 +7768,74 @@ PIXI.Spine.prototype.constructor = PIXI.Spine; * @method updateTransform * @private */ -PIXI.Spine.prototype.updateTransform = function() -{ - // TODO should make this time based really.. - this.state.update(1/60); +PIXI.Spine.prototype.updateTransform = function () { + this.lastTime = this.lastTime || Date.now(); + var timeDelta = (Date.now() - this.lastTime) * 0.001; + this.lastTime = Date.now(); + this.state.update(timeDelta); this.state.apply(this.skeleton); this.skeleton.updateWorldTransform(); - - for (var i = 0; i < this.skeleton.drawOrder.length; i++) - { - var slot = this.skeleton.drawOrder[i]; + 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 instanceof spine.RegionAttachment)) { + slotContainer.visible = false; + continue; + } - var x = slot.bone.worldX + slot.attachment.x * slot.bone.m00 + slot.attachment.y * slot.bone.m01 + slot.attachment.width * 0.5; - var y = slot.bone.worldY + slot.attachment.x * slot.bone.m10 + slot.attachment.y * slot.bone.m11 + slot.attachment.height * 0.5; - //console.log(x + ' : ' + y); - - - //console.log(slot.attachment.name) - if(slot.cacheName != slot.attachment.name) - { - var attachmentName = slot.attachment.name; - - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; + if (attachment.rendererObject) { + if (!slot.currentSpriteName || slot.currentSpriteName != attachment.name) { + var spriteName = attachment.rendererObject.name; + if (slot.currentSprite !== undefined) { + slot.currentSprite.visible = false; } - - this.sprites[i].setTexture(PIXI.TextureCache[attachmentName]); - - slot.cacheName = slot.attachment.name; + slot.sprites = slot.sprites || {}; + if (slot.sprites[spriteName] !== undefined) { + slot.sprites[spriteName].visible = true; + } else { + var sprite = this.createSprite(slot, attachment.rendererObject); + slotContainer.addChild(sprite); + } + slot.currentSprite = slot.sprites[spriteName]; + slot.currentSpriteName = spriteName; } - - x += -((slot.attachment.width * (slot.bone.worldScaleX + slot.attachment.scaleX - 1))>>1); - y += -((slot.attachment.height * (slot.bone.worldScaleY + slot.attachment.scaleY - 1))>>1); - - - this.sprites[i].position.x = x; - this.sprites[i].position.y = y; - this.sprites[i].rotation = (-(slot.bone.worldRotation + slot.attachment.rotation)) * (Math.PI/180); - } - + } + slotContainer.visible = true; + + 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 * Math.PI / 180); + } + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -} +}; + + +PIXI.Spine.prototype.createSprite = function (slot, descriptor) { + var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; + var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); + sprite.scale = descriptor.scale; + sprite.rotation = descriptor.rotation; + sprite.anchor.x = sprite.anchor.y = 0.5; + + slot.sprites = slot.sprites || {}; + slot.sprites[descriptor.name] = sprite; + return sprite; +}; /* * Awesome JS run time provided by EsotericSoftware - * + * * https://github.com/EsotericSoftware/spine-runtimes - * + * */ var spine = {}; @@ -7770,7 +7945,7 @@ spine.Slot.prototype = { this.g = data.g; this.b = data.b; this.a = data.a; - + var slotDatas = this.skeleton.data.slots; for (var i = 0, n = slotDatas.length; i < n; i++) { if (slotDatas[i] == data) { @@ -8001,6 +8176,7 @@ spine.TranslateTimeline.prototype = { var frameTime = frames[frameIndex]; var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); + bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; } @@ -8025,14 +8201,12 @@ spine.ScaleTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. - + var bone = skeleton.bones[this.boneIndex]; if (time >= frames[frames.length - 3]) { // Time is after last frame. bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - - return; } @@ -8070,6 +8244,7 @@ spine.ColorTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. + var slot = skeleton.slots[this.slotIndex]; if (time >= frames[frames.length - 5]) { // Time is after last frame. @@ -8119,7 +8294,7 @@ spine.AttachmentTimeline = function (frameCount) { spine.AttachmentTimeline.prototype = { slotIndex: 0, getFrameCount: function () { - return this.frames.length / 2; + return this.frames.length; }, setFrame: function (frameIndex, time, attachmentName) { this.frames[frameIndex] = time; @@ -8136,11 +8311,6 @@ spine.AttachmentTimeline.prototype = { frameIndex = spine.binarySearch(frames, time, 1) - 1; var attachmentName = this.attachmentNames[frameIndex]; - //console.log(skeleton.slots[this.slotIndex]) - - // change the name! - // skeleton.slots[this.slotIndex].attachmentName = attachmentName; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); } }; @@ -8312,11 +8482,9 @@ spine.Skeleton.prototype = { if (slot.data.name == slotName) { var attachment = null; if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; } - slot.setAttachment(attachment); return; } @@ -8398,7 +8566,6 @@ spine.RegionAttachment.prototype = { offset[7/*Y4*/] = localYCos + localX2Sin; }, computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; y += bone.worldY; var m00 = bone.m00; @@ -8422,6 +8589,7 @@ spine.AnimationStateData = function (skeletonData) { this.animationToMixTime = {}; }; spine.AnimationStateData.prototype = { + defaultMix: 0, setMixByName: function (fromName, toName, duration) { var from = this.skeletonData.findAnimation(fromName); if (!from) throw "Animation not found: " + fromName; @@ -8434,7 +8602,7 @@ spine.AnimationStateData.prototype = { }, getMix: function (from, to) { var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : 0; + return time ? time : this.defaultMix; } }; @@ -8474,7 +8642,7 @@ spine.AnimationState.prototype = { this.previous = null; } this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else + } else this.current.apply(skeleton, this.currentTime, this.currentLoop); }, clearAnimation: function () { @@ -8620,16 +8788,9 @@ spine.SkeletonJson.prototype = { name = map["name"] || name; var type = spine.AttachmentType[map["type"] || "region"]; - - // @ekelokorpi - // var attachment = this.attachmentLoader.newAttachment(skin, type, name); - var attachment = new spine.RegionAttachment(); - - // @Doormat23 - // add the name of the attachment - attachment.name = name; - + if (type == spine.AttachmentType.region) { + var attachment = new spine.RegionAttachment(); attachment.x = (map["x"] || 0) * this.scale; attachment.y = (map["y"] || 0) * this.scale; attachment.scaleX = map["scaleX"] || 1; @@ -8638,10 +8799,19 @@ spine.SkeletonJson.prototype = { attachment.width = (map["width"] || 32) * this.scale; attachment.height = (map["height"] || 32) * this.scale; attachment.updateOffset(); + + attachment.rendererObject = {}; + attachment.rendererObject.name = name; + attachment.rendererObject.scale = {}; + attachment.rendererObject.scale.x = attachment.scaleX; + attachment.rendererObject.scale.y = attachment.scaleY; + attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; + return attachment; } - return attachment; + throw "Unknown attachment type: " + type; }, + readAnimation: function (name, map, skeletonData) { var timelines = []; var duration = 0; @@ -8692,7 +8862,7 @@ spine.SkeletonJson.prototype = { } timelines.push(timeline); duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - + } else throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; } @@ -8735,8 +8905,8 @@ spine.SkeletonJson.prototype = { timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); } timelines.push(timeline); - // PIXI FIX - duration = Math.max(duration, timeline.frames[Math.floor(timeline.getFrameCount()) - 1]); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } else throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; } @@ -9005,14 +9175,14 @@ spine.Bone.yDown = true; /** * This object is one that will allow you to specify custom rendering functions based on render type * - * @class CustomRenderable + * @class CustomRenderable * @extends DisplayObject * @constructor */ PIXI.CustomRenderable = function() { PIXI.DisplayObject.call( this ); - + } // constructor @@ -9118,19 +9288,19 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } else { - + var scope = this; this.source.onload = function(){ - + scope.hasLoaded = true; scope.width = scope.source.width; scope.height = scope.source.height; - + // add it to somewhere... PIXI.texturesToUpdate.push(scope); scope.dispatchEvent( { type: 'loaded', content: scope } ); @@ -9143,7 +9313,7 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } @@ -9183,7 +9353,7 @@ PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) { // new Image() breaks tex loading in some versions of Chrome. // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); + var image = new Image();//document.createElement('img'); if (crossorigin) { image.crossOrigin = ''; @@ -9211,7 +9381,7 @@ PIXI.FrameCache = {}; * @uses EventTarget * @constructor * @param baseTexture {BaseTexture} The base texture source to create the texture from - * @param frmae {Rectangle} The rectangle frame of the texture to show + * @param frame {Rectangle} The rectangle frame of the texture to show */ PIXI.Texture = function(baseTexture, frame) { @@ -9256,7 +9426,7 @@ PIXI.Texture = function(baseTexture, frame) { if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); //console.log(frame) - + this.setFrame(frame); } else @@ -9335,13 +9505,13 @@ PIXI.Texture.prototype.setFrame = function(frame) PIXI.Texture.fromImage = function(imageUrl, crossorigin) { var texture = PIXI.TextureCache[imageUrl]; - + if(!texture) { texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); PIXI.TextureCache[imageUrl] = texture; } - + return texture; } @@ -9391,7 +9561,7 @@ PIXI.Texture.addTextureToCache = function(texture, id) } /** - * Remove a texture from the textureCache. + * Remove a texture from the textureCache. * * @static * @method removeTextureFromCache @@ -9503,15 +9673,7 @@ PIXI.RenderTexture.prototype.initWebGL = function() // create a projection matrix.. this.projection = new PIXI.Point(this.width/2 , this.height/2); -/* - this.projectionMatrix = PIXI.mat4.create(); - this.projectionMatrix[5] = 2/this.height// * 0.5; - this.projectionMatrix[13] = -1; - - this.projectionMatrix[0] = 2/this.width; - this.projectionMatrix[12] = -1; -*/ // set the correct render function.. this.render = this.renderWebGL; @@ -9525,10 +9687,6 @@ PIXI.RenderTexture.prototype.resize = function(width, height) this.width = width; this.height = height; - //this.frame.width = this.width - //this.frame.height = this.height; - - if(PIXI.gl) { this.projection.x = this.width/2 @@ -9592,6 +9750,7 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle var children = displayObject.children; //TODO -? create a new one??? dont think so! + var originalWorldTransform = displayObject.worldTransform; displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; // modify to flip... displayObject.worldTransform[4] = -1; @@ -9604,8 +9763,9 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle displayObject.worldTransform[5] -= position.y; } - - + PIXI.visibleCount++; + displayObject.vcount = PIXI.visibleCount; + for(var i=0,j=children.length; i- format + */ +PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) +{ + this.frames = []; + var cols = Math.floor(this.texture.width / frameWidth); + var rows = Math.floor(this.texture.height / frameHeight); + + var i=0; + for (var y=0; y x1 && x < x1 + this.width) + if(x >= x1 && x <= x1 + this.width) { var y1 = this.y; - - if(y > y1 && y < y1 + this.height) + + if(y >= y1 && y <= y1 + this.height) { return true; } @@ -165,7 +165,7 @@ PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; * @class Polygon * @constructor * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, - * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arugments passed can be + * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are * Numbers. @@ -232,9 +232,9 @@ PIXI.Polygon.prototype.contains = function(x, y) return inside; } +// constructor PIXI.Polygon.prototype.constructor = PIXI.Polygon; - /** * @author Chad Engler */ @@ -256,7 +256,7 @@ PIXI.Circle = function(x, y, radius) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number @@ -306,6 +306,7 @@ PIXI.Circle.prototype.contains = function(x, y) return (dx + dy <= r2); } +// constructor PIXI.Circle.prototype.constructor = PIXI.Circle; @@ -320,8 +321,8 @@ PIXI.Circle.prototype.constructor = PIXI.Circle; * @constructor * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse - * @param width {Number} The overall height of this ellipse - * @param height {Number} The overall width of this ellipse + * @param width {Number} The overall width of this ellipse + * @param height {Number} The overall height of this ellipse */ PIXI.Ellipse = function(x, y, width, height) { @@ -331,21 +332,21 @@ PIXI.Ellipse = function(x, y, width, height) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number * @default 0 */ this.y = y || 0; - + /** * @property width * @type Number * @default 0 */ this.width = width || 0; - + /** * @property height * @type Number @@ -394,11 +395,11 @@ PIXI.Ellipse.getBounds = function() return new PIXI.Rectangle(this.x, this.y, this.width, this.height); } +// constructor PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; - /* * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV * you both rock! @@ -426,7 +427,7 @@ PIXI.mat3.create = function() matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -442,7 +443,7 @@ PIXI.mat3.identity = function(matrix) matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -469,35 +470,35 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat3.multiply = function (mat, mat2, dest) +PIXI.mat3.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[0], a01 = mat[1], a02 = mat[2], a10 = mat[3], a11 = mat[4], a12 = mat[5], a20 = mat[6], a21 = mat[7], a22 = mat[8], - + b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; - + dest[0] = b00 * a00 + b01 * a10 + b02 * a20; dest[1] = b00 * a01 + b01 * a11 + b02 * a21; dest[2] = b00 * a02 + b01 * a12 + b02 * a22; - + dest[3] = b10 * a00 + b11 * a10 + b12 * a20; dest[4] = b10 * a01 + b11 * a11 + b12 * a21; dest[5] = b10 * a02 + b11 * a12 + b12 * a22; - + dest[6] = b20 * a00 + b21 * a10 + b22 * a20; dest[7] = b20 * a01 + b21 * a11 + b22 * a21; dest[8] = b20 * a02 + b21 * a12 + b22 * a22; - + return dest; } @@ -514,11 +515,11 @@ PIXI.mat3.clone = function(mat) matrix[6] = mat[6]; matrix[7] = mat[7]; matrix[8] = mat[8]; - + return matrix; } -PIXI.mat3.transpose = function (mat, dest) +PIXI.mat3.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values if (!dest || mat === dest) { @@ -546,30 +547,30 @@ PIXI.mat3.transpose = function (mat, dest) return dest; } -PIXI.mat3.toMat4 = function (mat, dest) +PIXI.mat3.toMat4 = function (mat, dest) { if (!dest) { dest = PIXI.mat4.create(); } - + dest[15] = 1; dest[14] = 0; dest[13] = 0; dest[12] = 0; - + dest[11] = 0; dest[10] = mat[8]; dest[9] = mat[7]; dest[8] = mat[6]; - + dest[7] = 0; dest[6] = mat[5]; dest[5] = mat[4]; dest[4] = mat[3]; - + dest[3] = 0; dest[2] = mat[2]; dest[1] = mat[1]; dest[0] = mat[0]; - + return dest; } @@ -597,19 +598,19 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat4.transpose = function (mat, dest) +PIXI.mat4.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) + if (!dest || mat === dest) { var a01 = mat[1], a02 = mat[2], a03 = mat[3], a12 = mat[6], a13 = mat[7], a23 = mat[11]; - + mat[1] = mat[4]; mat[2] = mat[8]; mat[3] = mat[12]; @@ -624,7 +625,7 @@ PIXI.mat4.transpose = function (mat, dest) mat[14] = a23; return mat; } - + dest[0] = mat[0]; dest[1] = mat[4]; dest[2] = mat[8]; @@ -644,18 +645,18 @@ PIXI.mat4.transpose = function (mat, dest) return dest; } -PIXI.mat4.multiply = function (mat, mat2, dest) +PIXI.mat4.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - + // Cache only the current line of the second matrix - var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; + var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; @@ -705,7 +706,6 @@ PIXI.DisplayObject = function() { this.last = this; this.first = this; - /** * The coordinate of the object relative to the local coordinates of the parent. * @@ -779,15 +779,6 @@ PIXI.DisplayObject = function() */ this.renderable = false; - /** - * [read-only] The visibility of the object based on world (parent) factors. - * - * @property worldVisible - * @type Boolean - * @readOnly - */ - this.worldVisible = false; - /** * [read-only] The display object container that contains this display object. * @@ -806,15 +797,6 @@ PIXI.DisplayObject = function() */ this.stage = null; - /** - * [read-only] The index of this object in the parent's `children` array - * - * @property childIndex - * @type Number - * @readOnly - */ - this.childIndex = 0; - /** * [read-only] The multiplied alpha of the displayobject * @@ -953,17 +935,6 @@ PIXI.DisplayObject = function() // constructor PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObject.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - } -});*/ - /** * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default * Instead of using this function you can now simply set the interactive property to true or false @@ -1011,16 +982,57 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { }, set: function(value) { - this._mask = value; - + if(value) { + if(this._mask) + { + value.start = this._mask.start; + value.end = this._mask.end; + } + else + { + this.addFilter(value); + value.renderable = false; + } + } + else + { + this.removeFilter(this._mask); + this._mask.renderable = true; + } + + this._mask = value; + } +}); + +/** + * Sets the filters for the displayObject. Currently there's a few limitations. + * 1: At the moment only one filter can be applied at a time.. + * 2: They cannot be nested. + * 3: There's no padding yet. + * 4: this is a webGL only feature. + * @property filters + * @type Array + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { + get: function() { + return this._filters; + }, + set: function(value) { + + //if(value == ) + if(value) + { + if(this._filters)this.removeFilter(this._filters); this.addFilter(value) } else { - this.removeFilter(); + if(this._filters)this.removeFilter(this._filters); } + + this._filters = value; } }); @@ -1031,19 +1043,21 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { * @param mask {Graphics} the graphics object to use as a filter * @private */ -PIXI.DisplayObject.prototype.addFilter = function(mask) +PIXI.DisplayObject.prototype.addFilter = function(data) { - if(this.filter)return; - this.filter = true; - + //if(this.filter)return; + //this.filter = true; // insert a filter block.. + // TODO Onject pool thease bad boys.. var start = new PIXI.FilterBlock(); var end = new PIXI.FilterBlock(); + data.start = start; + data.end = end; - start.mask = mask; - end.mask = mask; + start.data = data; + end.data = data; start.first = start.last = this; end.first = end.last = this; @@ -1051,9 +1065,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) start.open = true; /* - * * insert start - * */ var childFirst = start @@ -1084,9 +1096,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) // now insert the end filter block.. /* - * * insert end filter - * */ var childFirst = end var childLast = end @@ -1125,8 +1135,6 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) this.__renderGroup.addFilterBlocks(start, end); } - mask.renderable = false; - } /* @@ -1135,13 +1143,14 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) * @method removeFilter * @private */ -PIXI.DisplayObject.prototype.removeFilter = function() +PIXI.DisplayObject.prototype.removeFilter = function(data) { - if(!this.filter)return; - this.filter = false; - + //if(!this.filter)return; + //this.filter = false; + console.log("YUOIO") // modify the list.. - var startBlock = this.first; + var startBlock = data.start; + var nextObject = startBlock._iNext; var previousObject = startBlock._iPrev; @@ -1151,9 +1160,8 @@ PIXI.DisplayObject.prototype.removeFilter = function() this.first = startBlock._iNext; - // remove the end filter - var lastBlock = this.last; + var lastBlock = data.end; var nextObject = lastBlock._iNext; var previousObject = lastBlock._iPrev; @@ -1162,8 +1170,6 @@ PIXI.DisplayObject.prototype.removeFilter = function() previousObject._iNext = nextObject; // this is always true too! -// if(this.last == lastBlock) - //{ var tempLast = lastBlock._iPrev; // need to make sure the parents last is updated too var updateLast = this; @@ -1174,15 +1180,11 @@ PIXI.DisplayObject.prototype.removeFilter = function() if(!updateLast)break; } - var mask = startBlock.mask - mask.renderable = true; - // if webGL... if(this.__renderGroup) { this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); } - //} } /* @@ -1194,7 +1196,7 @@ PIXI.DisplayObject.prototype.removeFilter = function() PIXI.DisplayObject.prototype.updateTransform = function() { // TODO OPTIMIZE THIS!! with dirty - if(this.rotation != this.rotationCache) + if(this.rotation !== this.rotationCache) { this.rotationCache = this.rotation; this._sr = Math.sin(this.rotation); @@ -1236,9 +1238,12 @@ PIXI.DisplayObject.prototype.updateTransform = function() // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); this.worldAlpha = this.alpha * this.parent.worldAlpha; + + this.vcount = PIXI.visibleCount; } +PIXI.visibleCount = 0; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1270,18 +1275,6 @@ PIXI.DisplayObjectContainer = function() PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObjectContainer.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - - } -});*/ - /** * Adds a child to the container. * @@ -1299,11 +1292,10 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) } child.parent = this; - child.childIndex = this.children.length; this.children.push(child); - // updae the stage refference.. + // update the stage refference.. if(this.stage) { @@ -1326,7 +1318,7 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) var previousObject; // this could be wrong if there is a filter?? - if(this.filter) + if(this._filters) { previousObject = this.last._iPrev; } @@ -1338,7 +1330,6 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) nextObject = previousObject._iNext; // always true in this case - //this.last = child.last; // need to make sure the parents last is updated too var updateLast = this; var prevLast = previousObject; @@ -1402,7 +1393,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) } // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject; var previousObject; @@ -1410,7 +1401,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) if(index == this.children.length) { previousObject = this.last; - var updateLast = this;//.parent; + var updateLast = this; var prevLast = this.last; while(updateLast) { @@ -1539,7 +1530,7 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child) { // unlink // // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject = childLast._iNext; @@ -1609,7 +1600,6 @@ PIXI.DisplayObjectContainer.prototype.updateTransform = function() this.children[i].updateTransform(); } } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1739,9 +1729,18 @@ PIXI.Sprite.prototype.setTexture = function(texture) if(this.texture.baseTexture != texture.baseTexture) { this.textureChange = true; + this.texture = texture; + + if(this.__renderGroup) + { + this.__renderGroup.updateTexture(this); + } + } + else + { + this.texture = texture; } - this.texture = texture; this.updateFrame = true; } @@ -1798,7 +1797,6 @@ PIXI.Sprite.fromImage = function(imageId) return new PIXI.Sprite(texture); } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1814,7 +1812,7 @@ PIXI.Sprite.fromImage = function(imageId) PIXI.MovieClip = function(textures) { PIXI.Sprite.call(this, textures[0]); - + /** * The array of textures that make up the animation * @@ -1822,7 +1820,7 @@ PIXI.MovieClip = function(textures) * @type Array */ this.textures = textures; - + /** * The speed that the MovieClip will play at. Higher is faster, lower is slower * @@ -1848,7 +1846,7 @@ PIXI.MovieClip = function(textures) * @type Function */ this.onComplete = null; - + /** * [read-only] The index MovieClips current frame (this may not have to be a whole number) * @@ -1857,8 +1855,8 @@ PIXI.MovieClip = function(textures) * @default 0 * @readOnly */ - this.currentFrame = 0; - + this.currentFrame = 0; + /** * [read-only] Indicates if the MovieClip is currently playing * @@ -1873,6 +1871,23 @@ PIXI.MovieClip = function(textures) PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; +/** +* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures +* assigned to the MovieClip. +* +* @property totalFrames +* @type Number +* @default 0 +* @readOnly +*/ +Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { + get: function() { + + return this.textures.length; + } +}); + + /** * Stops the MovieClip * @@ -1928,11 +1943,13 @@ PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) PIXI.MovieClip.prototype.updateTransform = function() { PIXI.Sprite.prototype.updateTransform.call(this); - + if(!this.playing)return; - + this.currentFrame += this.animationSpeed; + var round = (this.currentFrame + 0.5) | 0; + if(this.loop || round < this.textures.length) { this.setTexture(this.textures[round % this.textures.length]); @@ -1952,14 +1969,49 @@ PIXI.MovieClip.prototype.updateTransform = function() -PIXI.FilterBlock = function(mask) +PIXI.FilterBlock = function() { - this.graphics = mask this.visible = true; this.renderable = true; } +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.ColorMatrixFilter = function() +{ + // set the uniforms + this.uniforms = { + matrix: {type: 'mat4', value: [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1]}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float invert;", + "uniform mat4 matrix;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", + "gl_FragColor = gl_FragColor * vColor;", + "}" + ]; + +} +Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { + get: function() { + return this.uniforms.matrix.value; + }, + set: function(value) { + this.uniforms.matrix.value = value; + } +}); /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1988,7 +2040,7 @@ PIXI.Text = function(text, style) this.setText(text); this.setStyle(style); - + this.updateText(); this.dirty = false; }; @@ -2030,7 +2082,7 @@ PIXI.Text.prototype.setStyle = function(style) * @methos setText * @param {String} text The copy that you would like the text to display */ -PIXI.Sprite.prototype.setText = function(text) +PIXI.Text.prototype.setText = function(text) { this.text = text.toString() || " "; this.dirty = true; @@ -2045,9 +2097,9 @@ PIXI.Sprite.prototype.setText = function(text) PIXI.Text.prototype.updateText = function() { this.context.font = this.style.font; - + var outputText = this.text; - + // word wrap // preserve original text if(this.style.wordWrap)outputText = this.wordWrap(this.text); @@ -2065,7 +2117,7 @@ PIXI.Text.prototype.updateText = function() maxLineWidth = Math.max(maxLineWidth, lineWidth); } this.canvas.width = maxLineWidth + this.style.strokeThickness; - + //calculate text height var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; this.canvas.height = lineHeight * lines.length; @@ -2073,7 +2125,7 @@ PIXI.Text.prototype.updateText = function() //set canvas text styles this.context.fillStyle = this.style.fill; this.context.font = this.style.font; - + this.context.strokeStyle = this.style.stroke; this.context.lineWidth = this.style.strokeThickness; @@ -2083,7 +2135,7 @@ PIXI.Text.prototype.updateText = function() for (i = 0; i < lines.length; i++) { var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); - + if(this.style.align == "right") { linePosition.x += maxLineWidth - lineWidths[i]; @@ -2103,7 +2155,7 @@ PIXI.Text.prototype.updateText = function() this.context.fillText(lines[i], linePosition.x, linePosition.y); } } - + this.updateTexture(); }; @@ -2119,10 +2171,10 @@ PIXI.Text.prototype.updateTexture = function() this.texture.baseTexture.height = this.canvas.height; this.texture.frame.width = this.canvas.width; this.texture.frame.height = this.canvas.height; - + this._width = this.canvas.width; this._height = this.canvas.height; - + PIXI.texturesToUpdate.push(this.texture.baseTexture); }; @@ -2136,10 +2188,10 @@ PIXI.Text.prototype.updateTransform = function() { if(this.dirty) { - this.updateText(); + this.updateText(); this.dirty = false; } - + PIXI.Sprite.prototype.updateTransform.call(this); }; @@ -2151,12 +2203,12 @@ PIXI.Text.prototype.updateTransform = function() * @param fontStyle {Object} * @private */ -PIXI.Text.prototype.determineFontHeight = function(fontStyle) +PIXI.Text.prototype.determineFontHeight = function(fontStyle) { // build a little reference dictionary so if the font style has been used return a // cached version... var result = PIXI.Text.heightCache[fontStyle]; - + if(!result) { var body = document.getElementsByTagName("body")[0]; @@ -2165,13 +2217,13 @@ PIXI.Text.prototype.determineFontHeight = function(fontStyle) dummy.appendChild(dummyText); dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); body.appendChild(dummy); - + result = dummy.offsetHeight; PIXI.Text.heightCache[fontStyle] = result; - + body.removeChild(dummy); } - + return result; }; @@ -2191,7 +2243,7 @@ PIXI.Text.prototype.wordWrap = function(text) if(p == start) { return 1; } - + if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) { if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) @@ -2208,7 +2260,7 @@ PIXI.Text.prototype.wordWrap = function(text) return arguments.callee(ctx, text, start, p, wrapWidth); } }; - + var lineWrap = function(ctx, text, wrapWidth) { if(ctx.measureText(text).width <= wrapWidth || text.length < 1) @@ -2218,14 +2270,14 @@ PIXI.Text.prototype.wordWrap = function(text) var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); }; - + var result = ""; var lines = text.split("\n"); for (var i = 0; i < lines.length; i++) { result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; } - + return result; }; @@ -2241,7 +2293,7 @@ PIXI.Text.prototype.destroy = function(destroyTexture) { this.texture.destroy(); } - + }; PIXI.Text.heightCache = {}; @@ -2252,7 +2304,7 @@ PIXI.Text.heightCache = {}; /** * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" - * You can generate the fnt files using + * You can generate the fnt files using * http://www.angelcode.com/products/bmfont/ for windows or * http://www.bmglyph.com/ for mac. * @@ -2342,7 +2394,7 @@ PIXI.BitmapText.prototype.updateText = function() prevCharCode = null; continue; } - + var charData = data.chars[charCode]; if(!charData) continue; @@ -2405,7 +2457,7 @@ PIXI.BitmapText.prototype.updateTransform = function() this.dirty = false; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); }; @@ -2414,10 +2466,8 @@ PIXI.BitmapText.fonts = {}; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ - - - -/** + + /** * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive * This manager also supports multitouch. * @@ -2451,6 +2501,8 @@ PIXI.InteractionManager = function(stage) */ this.touchs = {}; + + // helpers this.tempPoint = new PIXI.Point(); //this.tempMatrix = mat3.create(); @@ -2461,7 +2513,19 @@ PIXI.InteractionManager = function(stage) this.pool = []; this.interactiveItems = []; + this.interactionDOMElement = null; + //this will make it so that you dont have to call bind all the time + this.onMouseMove = this.onMouseMove.bind( this ); + this.onMouseDown = this.onMouseDown.bind(this); + this.onMouseOut = this.onMouseOut.bind(this); + this.onMouseUp = this.onMouseUp.bind(this); + + this.onTouchStart = this.onTouchStart.bind(this); + this.onTouchEnd = this.onTouchEnd.bind(this); + this.onTouchMove = this.onTouchMove.bind(this); + + this.last = 0; } @@ -2486,7 +2550,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj { var child = children[i]; - if(child.visible) { +// if(child.visible) { // push all interactive bits if(child.interactive) { @@ -2508,7 +2572,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj this.collectInteractiveSprite(child, iParent); } } - } +// } } } @@ -2521,27 +2585,68 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj */ PIXI.InteractionManager.prototype.setTarget = function(target) { + this.target = target; + + //check if the dom element has been set. If it has don't do anything + if( this.interactionDOMElement === null ) { + + this.setTargetDomElement( target.view ); + } + + document.body.addEventListener('mouseup', this.onMouseUp, true); +} + + +/** + * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM + * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element + * to receive those events + * + * @method setTargetDomElement + * @param domElement {DOMElement} the dom element which will receive mouse and touch events + * @private + */ +PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) +{ + //remove previouse listeners + if( this.interactionDOMElement !== null ) + { + this.interactionDOMElement.style['-ms-content-zooming'] = ''; + this.interactionDOMElement.style['-ms-touch-action'] = ''; + + this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); + this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); + this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); + this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); + this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); + } + + if (window.navigator.msPointerEnabled) { // time to remove some of that zoom in ja.. - target.view.style["-ms-content-zooming"] = "none"; - target.view.style["-ms-touch-action"] = "none" + domElement.style['-ms-content-zooming'] = 'none'; + domElement.style['-ms-touch-action'] = 'none'; // DO some window specific touch! } - - this.target = target; - target.view.addEventListener('mousemove', this.onMouseMove.bind(this), true); - target.view.addEventListener('mousedown', this.onMouseDown.bind(this), true); - document.body.addEventListener('mouseup', this.onMouseUp.bind(this), true); - target.view.addEventListener('mouseout', this.onMouseUp.bind(this), true); - - // aint no multi touch just yet! - target.view.addEventListener("touchstart", this.onTouchStart.bind(this), true); - target.view.addEventListener("touchend", this.onTouchEnd.bind(this), true); - target.view.addEventListener("touchmove", this.onTouchMove.bind(this), true); + + this.interactionDOMElement = domElement; + + domElement.addEventListener('mousemove', this.onMouseMove, true); + domElement.addEventListener('mousedown', this.onMouseDown, true); + domElement.addEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + domElement.addEventListener('touchstart', this.onTouchStart, true); + domElement.addEventListener('touchend', this.onTouchEnd, true); + domElement.addEventListener('touchmove', this.onTouchMove, true); } + /** * updates the state of interactive objects * @@ -2583,12 +2688,14 @@ PIXI.InteractionManager.prototype.update = function() // loop through interactive objects! var length = this.interactiveItems.length; - this.target.view.style.cursor = "default"; + this.interactionDOMElement.style.cursor = "default"; for (var i = 0; i < length; i++) { var item = this.interactiveItems[i]; - if(!item.visible)continue; + + + //if(!item.visible)continue; // OPTIMISATION - only calculate every time if the mousemove function exists.. // OK so.. does the object have any other interactive functions? @@ -2604,7 +2711,7 @@ PIXI.InteractionManager.prototype.update = function() // loks like there was a hit! if(item.__hit) { - if(item.buttonMode)this.target.view.style.cursor = "pointer"; + if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; if(!item.__isOver) { @@ -2639,7 +2746,7 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) { this.mouse.originalEvent = event || window.event; //IE uses window.event // TODO optimize by not check EVERY TIME! maybe half as often? // - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); @@ -2669,7 +2776,6 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) */ PIXI.InteractionManager.prototype.onMouseDown = function(event) { - event.preventDefault(); this.mouse.originalEvent = event || window.event; //IE uses window.event // loop through inteaction tree... @@ -2706,6 +2812,26 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) } } + +PIXI.InteractionManager.prototype.onMouseOut = function(event) +{ + var length = this.interactiveItems.length; + + this.interactionDOMElement.style.cursor = "default"; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.__isOver) + { + this.mouse.target = item; + if(item.mouseout)item.mouseout(this.mouse); + item.__isOver = false; + } + } +} + /** * Is called when the mouse button is released on the renderer element * @@ -2770,7 +2896,7 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) { var global = interactionData.global; - if(!item.visible)return false; + if(item.vcount !== PIXI.visibleCount)return false; var isSprite = (item instanceof PIXI.Sprite), worldTransform = item.worldTransform, @@ -2840,14 +2966,14 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) */ PIXI.InteractionManager.prototype.onTouchMove = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) { var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; + touchData.originalEvent = event || window.event; // update the touch position touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); @@ -2871,10 +2997,7 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) */ PIXI.InteractionManager.prototype.onTouchStart = function(event) { - event.preventDefault(); - this.mouse.originalEvent = event || window.event; //IE uses window.event - - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2884,6 +3007,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) var touchData = this.pool.pop(); if(!touchData)touchData = new PIXI.InteractionData(); + touchData.originalEvent = event || window.event; + this.touchs[touchEvent.identifier] = touchData; touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); @@ -2921,8 +3046,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) */ PIXI.InteractionManager.prototype.onTouchEnd = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + //this.mouse.originalEvent = event || window.event; //IE uses window.event + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2943,7 +3068,7 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) if(itemTouchData == touchData) { // so this one WAS down... - + touchData.originalEvent = event || window.event; // hitTest?? if(item.touchend || item.tap) @@ -3055,9 +3180,8 @@ PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; * @constructor * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format * like: 0xFFFFFF for white - * @param interactive {Boolean} enable / disable interaction (default is false) */ -PIXI.Stage = function(backgroundColor, interactive) +PIXI.Stage = function(backgroundColor) { PIXI.DisplayObjectContainer.call( this ); @@ -3077,7 +3201,7 @@ PIXI.Stage = function(backgroundColor, interactive) * @property interactive * @type Boolean */ - this.interactive = interactive; + this.interactive = true; /** * The interaction manage for this stage, manages all interactive activity on the stage @@ -3113,6 +3237,18 @@ PIXI.Stage = function(backgroundColor, interactive) PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); PIXI.Stage.prototype.constructor = PIXI.Stage; +/** + * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. + * This is useful for when you have other DOM elements ontop of the Canvas element. + * + * @method setInteractionDelegate + * @param domElement {DOMElement} This new domElement which will receive mouse/touch events + */ +PIXI.Stage.prototype.setInteractionDelegate = function(domElement) +{ + this.interactionManager.setTargetDomElement( domElement ); +} + /* * Updates the object transform for rendering * @@ -3122,6 +3258,7 @@ PIXI.Stage.prototype.constructor = PIXI.Stage; PIXI.Stage.prototype.updateTransform = function() { this.worldAlpha = 1; + this.vcount = PIXI.visibleCount; for(var i=0,j=this.children.length; i 100) { console.log("BREAK") break } - } + } } @@ -3361,14 +3466,14 @@ PIXI.runList = function(item) PIXI.EventTarget = function () { var listeners = {}; - + this.addEventListener = this.on = function ( type, listener ) { - - + + if ( listeners[ type ] === undefined ) { listeners[ type ] = []; - + } if ( listeners[ type ].indexOf( listener ) === - 1 ) { @@ -3379,11 +3484,17 @@ PIXI.EventTarget = function () { }; this.dispatchEvent = this.emit = function ( event ) { - - for ( var listener in listeners[ event.type ] ) { - listeners[ event.type ][ listener ]( event ); - + if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { + + return; + + } + + for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { + + listeners[ event.type ][ i ]( event ); + } }; @@ -3417,8 +3528,11 @@ PIXI.EventTarget = function () { * @param height {Number} the height of the renderers view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) + * + * antialias */ -PIXI.autoDetectRenderer = function(width, height, view, transparent) +PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) { if(!width)width = 800; if(!height)height = 600; @@ -3429,7 +3543,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) //console.log(webgl); if( webgl ) { - return new PIXI.WebGLRenderer(width, height, view, transparent); + return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); } return new PIXI.CanvasRenderer(width, height, view, transparent); @@ -3441,7 +3555,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) PolyK library url: http://polyk.ivank.net Released under MIT licence. - + Copyright (c) 2012 Ivan Kuckir Permission is hereby granted, free of charge, to any person @@ -3465,8 +3579,8 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - This is an amazing lib! - + This is an amazing lib! + slightly modified by mat groves (matgroves.com); */ @@ -3482,13 +3596,13 @@ PIXI.PolyK = {}; PIXI.PolyK.Triangulate = function(p) { var sign = true; - + var n = p.length>>1; if(n<3) return []; var tgs = []; var avl = []; for(var i=0; i 3) @@ -3496,11 +3610,11 @@ PIXI.PolyK.Triangulate = function(p) var i0 = avl[(i+0)%al]; var i1 = avl[(i+1)%al]; var i2 = avl[(i+2)%al]; - + var ax = p[2*i0], ay = p[2*i0+1]; var bx = p[2*i1], by = p[2*i1+1]; var cx = p[2*i2], cy = p[2*i2+1]; - + var earFound = false; if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) { @@ -3519,7 +3633,7 @@ PIXI.PolyK.Triangulate = function(p) al--; i = 0; } - else if(i++ > 3*al) + else if(i++ > 3*al) { // need to flip flip reverse it! // reset! @@ -3528,17 +3642,17 @@ PIXI.PolyK.Triangulate = function(p) var tgs = []; avl = []; for(var i=0; i= 0) == sign; } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -3612,13 +3725,11 @@ PIXI.shaderVertexSrc = [ "attribute vec2 aVertexPosition;", "attribute vec2 aTextureCoord;", "attribute float aColor;", - //"uniform mat4 uMVMatrix;", "uniform vec2 projectionVector;", "varying vec2 vTextureCoord;", "varying float vColor;", "void main(void) {", - // "gl_Position = uMVMatrix * vec4(aVertexPosition, 1.0, 1.0);", "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", "vTextureCoord = aTextureCoord;", "vColor = aColor;", @@ -3658,7 +3769,6 @@ PIXI.stripShaderVertexSrc = [ "}" ]; - /* * primitive shader.. */ @@ -3685,6 +3795,8 @@ PIXI.primitiveShaderVertexSrc = [ "}" ]; +PIXI.shaderStack = []; + PIXI.initPrimitiveShader = function() { var gl = PIXI.gl; @@ -3699,27 +3811,26 @@ PIXI.initPrimitiveShader = function() shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); + + //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(shaderProgram.colorAttribute); +//gl.enableVertexAttribArray(program.textureCoordAttribute); + shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); PIXI.primitiveProgram = shaderProgram; + + } PIXI.initDefaultShader = function() { - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.shaderVertexSrc, PIXI.shaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - // shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.shaderProgram = shaderProgram; + PIXI.defaultShader = new PIXI.PixiShader(); + PIXI.defaultShader.init(); + PIXI.activateShader(PIXI.defaultShader); + /* + PIXI.shaderStack.push(PIXI.defaultShader); + PIXI.current*/ } PIXI.initDefaultStripShader = function() @@ -3736,9 +3847,7 @@ PIXI.initDefaultStripShader = function() shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); PIXI.stripShaderProgram = shaderProgram; @@ -3789,35 +3898,135 @@ PIXI.compileProgram = function(vertexSrc, fragmentSrc) return shaderProgram; } +PIXI.activateShader = function(shader) +{ + PIXI.shaderStack.push(shader); + + //console.log(">>>") + var gl = PIXI.gl; + + var shaderProgram = shader.program; + + // map uniforms.. + gl.useProgram(shaderProgram); + + gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + gl.enableVertexAttribArray(shaderProgram.colorAttribute); + gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); -PIXI.activateDefaultShader = function() + shader.syncUniforms(); + + PIXI.currentShader = shaderProgram; +} + + +PIXI.popShader = function() { var gl = PIXI.gl; - var shaderProgram = PIXI.shaderProgram; + // activate last program.. + var lastProgram = PIXI.shaderStack.pop(); + + var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); + PIXI.currentShader = shaderProgram; } - - PIXI.activatePrimitiveShader = function() { var gl = PIXI.gl; - gl.disableVertexAttribArray(PIXI.shaderProgram.textureCoordAttribute); - gl.disableVertexAttribArray(PIXI.shaderProgram.colorAttribute); - gl.useProgram(PIXI.primitiveProgram); - gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); + gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + + //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); } +PIXI.deactivatePrimitiveShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.currentShader); + + gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.PixiShader = function() +{ + // the webGL program.. + this.program; + + this.fragmentSrc = [ + "precision lowp float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", + "}" + ]; + +} + +PIXI.PixiShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get the default shader bits! + program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); + program.colorAttribute = gl.getAttribLocation(program, "aColor"); + program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); + + program.projectionVector = gl.getUniformLocation(program, "projectionVector"); + program.samplerUniform = gl.getUniformLocation(program, "uSampler"); + + // add those custom shaders! + for (var key in this.uniforms) + { + // get the uniform locations.. + program[key] = gl.getUniformLocation(program, key); + } + + this.program = program; +} + +PIXI.PixiShader.prototype.syncUniforms = function() +{ + var gl = PIXI.gl; + + for (var key in this.uniforms) + { + //var + var type = this.uniforms[key].type; + + // need to grow this! + if(type == "f") + { + gl.uniform1f(this.program[key], this.uniforms[key].value); + } + else if(type == "mat4") + { + gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); + } + } + +} + /** * @author Mat Groves http://matgroves.com/ @Doormat23 @@ -3887,7 +4096,7 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); // WHY DOES THIS LINE NEED TO BE THERE??? - gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // its not even used.. but need to be set or it breaks? // only on pc though.. @@ -3899,8 +4108,10 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); + PIXI.deactivatePrimitiveShader(); + // return to default shader... - PIXI.activateDefaultShader(); +// PIXI.activateShader(PIXI.defaultShader); } /** @@ -4243,7 +4454,7 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) verts.push(px , py); verts.push(r, g, b, alpha); - verts.push(p2x - (px-p2x), p2y - (py - p2y));//, 4); + verts.push(p2x - (px-p2x), p2y - (py - p2y)); verts.push(r, g, b, alpha); } } @@ -4356,9 +4567,10 @@ PIXI.gl; * @param height=0 {Number} the height of the canvas view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) * */ -PIXI.WebGLRenderer = function(width, height, view, transparent) +PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) { // do a catch.. only 1 webGL renderer.. @@ -4382,7 +4594,7 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) { PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { alpha: this.transparent, - antialias:true, // SPEED UP?? + antialias:!!antialias, // SPEED UP?? premultipliedAlpha:false, stencil:true }); @@ -4392,11 +4604,12 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); } - PIXI.initPrimitiveShader(); PIXI.initDefaultShader(); + PIXI.initPrimitiveShader(); PIXI.initDefaultStripShader(); - PIXI.activateDefaultShader(); + +// PIXI.activateDefaultShader(); var gl = this.gl; PIXI.WebGLRenderer.gl = gl; @@ -4413,7 +4626,10 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) this.resize(this.width, this.height); this.contextLost = false; + PIXI.activateShader(PIXI.defaultShader); + this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); + } // constructor @@ -4469,8 +4685,6 @@ PIXI.WebGLRenderer.prototype.render = function(stage) { // TODO make this work // dont think this is needed any more? - //if(this.__stage)this.checkVisibility(this.__stage, false) - this.__stage = stage; this.stageRenderGroup.setRenderable(stage); } @@ -4487,10 +4701,8 @@ PIXI.WebGLRenderer.prototype.render = function(stage) // update any textures PIXI.WebGLRenderer.updateTextures(); - // recursivly loop through all items! - //this.checkVisibility(stage, true); - // update the scene graph + PIXI.visibleCount++; stage.updateTransform(); var gl = this.gl; @@ -4499,16 +4711,12 @@ PIXI.WebGLRenderer.prototype.render = function(stage) gl.colorMask(true, true, true, this.transparent); gl.viewport(0, 0, this.width, this.height); - // set the correct matrix.. - // gl.uniformMatrix4fv(this.shaderProgram.mvMatrixUniform, false, this.projectionMatrix); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); gl.clear(gl.COLOR_BUFFER_BIT); // HACK TO TEST - //PIXI.projectionMatrix = this.projectionMatrix; this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; this.stageRenderGroup.render(PIXI.projection); @@ -4546,8 +4754,9 @@ PIXI.WebGLRenderer.prototype.render = function(stage) */ PIXI.WebGLRenderer.updateTextures = function() { - for (var i=0; i < PIXI.texturesToUpdate.length; i++) this.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) this.destroyTexture(PIXI.texturesToDestroy[i]); + //TODO break this out into a texture manager... + for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); + for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; } @@ -4562,6 +4771,7 @@ PIXI.WebGLRenderer.updateTextures = function() */ PIXI.WebGLRenderer.updateTexture = function(texture) { + //TODO break this out into a texture manager... var gl = PIXI.gl; if(!texture._glTexture) @@ -4602,9 +4812,10 @@ PIXI.WebGLRenderer.updateTexture = function(texture) * @param texture {Texture} The texture to update * @private */ -PIXI.WebGLRenderer.prototype.destroyTexture = function(texture) +PIXI.WebGLRenderer.destroyTexture = function(texture) { - var gl = this.gl; + //TODO break this out into a texture manager... + var gl = PIXI.gl; if(texture._glTexture) { @@ -4768,7 +4979,6 @@ PIXI.WebGLBatch.prototype.clean = function() this.uvs = []; this.indices = []; this.colors = []; - //this.sprites = []; this.dynamicSize = 1; this.texture = null; this.last = null; @@ -4805,7 +5015,6 @@ PIXI.WebGLBatch.prototype.init = function(sprite) this.dirty = true; this.blendMode = sprite.blendMode; this.texture = sprite.texture.baseTexture; -// this.sprites.push(sprite); this.head = sprite; this.tail = sprite; this.size = 1; @@ -4838,7 +5047,6 @@ PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) else { this.head = sprite; - //this.head.__prev = null } } @@ -4926,7 +5134,7 @@ PIXI.WebGLBatch.prototype.split = function(sprite) { this.dirty = true; - var batch = new PIXI.WebGLBatch(this.gl);//PIXI._getBatch(this.gl); + var batch = new PIXI.WebGLBatch(this.gl); batch.init(sprite); batch.texture = this.texture; batch.tail = this.tail; @@ -4936,8 +5144,6 @@ PIXI.WebGLBatch.prototype.split = function(sprite) sprite.__prev = null; // return a splite batch! - //sprite.__prev.__next = null; - //sprite.__prev = null; // TODO this size is wrong! // need to recalculate :/ problem with a linked list! @@ -5007,13 +5213,13 @@ PIXI.WebGLBatch.prototype.growBatch = function() gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); - this.uvs = new Float32Array( this.dynamicSize * 8 ) + this.uvs = new Float32Array( this.dynamicSize * 8 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); this.dirtyUVS = true; - this.colors = new Float32Array( this.dynamicSize * 4 ) + this.colors = new Float32Array( this.dynamicSize * 4 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); @@ -5112,7 +5318,7 @@ PIXI.WebGLBatch.prototype.update = function() while(displayObject) { - if(displayObject.worldVisible) + if(displayObject.vcount === PIXI.visibleCount) { width = displayObject.texture.frame.width; height = displayObject.texture.frame.height; @@ -5214,7 +5420,7 @@ PIXI.WebGLBatch.prototype.update = function() PIXI.WebGLBatch.prototype.render = function(start, end) { start = start || 0; - //end = end || this.size; + if(end == undefined)end = this.size; if(this.dirty) @@ -5230,8 +5436,9 @@ PIXI.WebGLBatch.prototype.render = function(start, end) //TODO optimize this! - var shaderProgram = PIXI.shaderProgram; - gl.useProgram(shaderProgram); + var shaderProgram = PIXI.currentShader; + + //gl.useProgram(shaderProgram); // update the verts.. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); @@ -5239,6 +5446,8 @@ PIXI.WebGLBatch.prototype.render = function(start, end) gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // update the uvs + var isDefault = (shaderProgram == PIXI.shaderProgram) + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); if(this.dirtyUVS) @@ -5262,13 +5471,11 @@ PIXI.WebGLBatch.prototype.render = function(start, end) } gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - //var startIndex = 0//1; var len = end - start; - // console.log(this.size) + // DRAW THAT this! gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); } @@ -5336,77 +5543,45 @@ PIXI.WebGLRenderGroup.prototype.render = function(projection) PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - // TODO remove this by replacing visible with getter setters.. - this.checkVisibility(this.root, this.root.visible); - // will render all the elements in the group var renderable; - - for (var i=0; i < this.batchs.length; i++) { + renderable = this.batchs[i]; if(renderable instanceof PIXI.WebGLBatch) { this.batchs[i].render(); + continue; } - else if(renderable instanceof PIXI.TilingSprite) + + // non sprite batch.. + var worldVisible = renderable.vcount === PIXI.visibleCount; + + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ - if(renderable.open) - { - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - gl.colorMask(true, true, true, false); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - else - { - gl.disable(gl.STENCIL_TEST); - } + this.handleFilterBlock(renderable, projection); } } } -/** - * Renders the stage to its webgl view - * - * @method handleFilter - * @param filter {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.handleFilter = function(filter, projection) -{ - -} - /** * Renders a specific displayObject * @@ -5420,11 +5595,8 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - this.checkVisibility(displayObject, displayObject.visible); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); -// gl.uniformMatrix4fv(PIXI.shaderProgram.mvMatrixUniform, false, projectionMatrix); - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); - // to do! // render part of the scene... @@ -5483,7 +5655,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project while(lastItem.children.length > 0) { lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem; + if(lastItem.renderable)lastRenderable = lastItem.last; } if(lastRenderable instanceof PIXI.Sprite) @@ -5577,45 +5749,80 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project */ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) { + var sta = PIXI.shaderStack.length; + + var worldVisible = renderable.vcount === PIXI.visibleCount + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.CustomRenderable) { - if(renderable.visible) renderable.renderWebGL(this, projection); + if(worldVisible) renderable.renderWebGL(this, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ + this.handleFilterBlock(renderable, projection); + } +} - var gl = PIXI.gl; +PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) +{ + /* + * for now only masks are supported.. + */ + var gl = PIXI.gl; - if(renderable.open) + if(renderable.open) + { + if(renderable.data instanceof Array) + { + var filter = renderable.data[0]; + + if(!filter.shader) + { + var shader = new PIXI.PixiShader(); + + shader.fragmentSrc = filter.fragmentSrc; + shader.uniforms = filter.uniforms; + shader.init(); + + filter.shader = shader + } + + PIXI.activateShader(filter.shader); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } + else { gl.enable(gl.STENCIL_TEST); gl.colorMask(false, false, false, false); gl.stencilFunc(gl.ALWAYS,1,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - // we know this is a render texture so enable alpha too.. + PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); + gl.colorMask(true, true, true, true); gl.stencilFunc(gl.NOTEQUAL,0,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); } + } + else + { + if(renderable.data instanceof Array) + { + PIXI.popShader(); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } else { gl.disable(gl.STENCIL_TEST); @@ -5623,42 +5830,6 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) } } -/** - * Checks the visibility of a displayObject - * - * @method checkVisibility - * @param displayObject {DisplayObject} - * @param globalVisible {Boolean} - * @private - */ -PIXI.WebGLRenderGroup.prototype.checkVisibility = function(displayObject, globalVisible) -{ - // give the dp a reference to its renderGroup... - var children = displayObject.children; - //displayObject.worldVisible = globalVisible; - for (var i=0; i < children.length; i++) - { - var child = children[i]; - - // TODO optimize... should'nt need to loop through everything all the time - child.worldVisible = child.visible && globalVisible; - - // everything should have a batch! - // time to see whats new! - if(child.textureChange) - { - child.textureChange = false; - if(child.worldVisible)this.updateTexture(child); - // update texture!! - } - - if(child.children.length > 0) - { - this.checkVisibility(child, child.worldVisible); - } - }; -} - /** * Updates a webgl texture * @@ -5719,7 +5890,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * It keeps going back until it finds a sprite or the stage */ var previousRenderable = start; - while(previousRenderable != this.root) + while(previousRenderable != this.root.first) { previousRenderable = previousRenderable._iPrev; if(previousRenderable.renderable && previousRenderable.__renderGroup)break; @@ -5733,7 +5904,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * scene graph */ var previousRenderable2 = end; - while(previousRenderable2 != this.root) + while(previousRenderable2 != this.root.first) { previousRenderable2 = previousRenderable2._iPrev; if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; @@ -6105,6 +6276,7 @@ PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) } } + /** * Initializes a tiling sprite * @@ -6175,23 +6347,19 @@ PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) { var gl = this.gl; - var shaderProgram = PIXI.shaderProgram; -// mat - //var mat4Real = PIXI.mat3.toMat4(strip.worldTransform); - //PIXI.mat4.transpose(mat4Real); - //PIXI.mat4.multiply(projectionMatrix, mat4Real, mat4Real ) - + var shaderProgram = PIXI.stripShaderProgram; - gl.useProgram(PIXI.stripShaderProgram); + + gl.useProgram(shaderProgram); var m = PIXI.mat3.clone(strip.worldTransform); PIXI.mat3.transpose(m); // set the matrix transform for the - gl.uniformMatrix3fv(PIXI.stripShaderProgram.translationMatrix, false, m); - gl.uniform2f(PIXI.stripShaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(PIXI.stripShaderProgram.alpha, strip.worldAlpha); + gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); + gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); /* if(strip.blendMode == PIXI.blendModes.NORMAL) @@ -6249,11 +6417,10 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } - //console.log(gl.TRIANGLE_STRIP); gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - gl.useProgram(PIXI.shaderProgram); + gl.useProgram(PIXI.currentProgram); } /** @@ -6328,6 +6495,7 @@ PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } + /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -6401,7 +6569,6 @@ PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; */ PIXI.CanvasRenderer.prototype.render = function(stage) { - // update children if need be //stage.__childrenAdded = []; //stage.__childrenRemoved = []; @@ -6410,6 +6577,7 @@ PIXI.CanvasRenderer.prototype.render = function(stage) PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; + PIXI.visibleCount++; stage.updateTransform(); // update the background color @@ -6496,7 +6664,7 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) var frame = displayObject.texture.frame; - if(frame) + if(frame && frame.width && frame.height) { context.globalAlpha = displayObject.worldAlpha; @@ -6534,31 +6702,34 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) } else if(displayObject instanceof PIXI.FilterBlock) { - if(displayObject.open) + if(PIXI.FilterBlock.data instanceof PIXI.Graphics) { - context.save(); - - var cacheAlpha = displayObject.mask.alpha; - var maskTransform = displayObject.mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - displayObject.mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); - // context.fillStyle = 0xFF0000; - // context.fillRect(0, 0, 200, 200); - context.clip(); - - displayObject.mask.worldAlpha = cacheAlpha; - //context.globalCompositeOperation = 'lighter'; + if(displayObject.open) + { + context.save(); + + var cacheAlpha = displayObject.mask.alpha; + var maskTransform = displayObject.mask.worldTransform; + + context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) + + displayObject.mask.worldAlpha = 0.5; + + context.worldAlpha = 0; + + PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); + context.clip(); + + displayObject.mask.worldAlpha = cacheAlpha; + } + else + { + context.restore(); + } } else { - //context.globalCompositeOperation = 'source-over'; - context.restore(); + // only masks supported right now! } } // count++ @@ -6651,7 +6822,7 @@ PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) PIXI.CanvasRenderer.prototype.renderStrip = function(strip) { var context = this.context; - //context.globalCompositeOperation = 'lighter'; + // draw triangles!! var verticies = strip.verticies; var uvs = strip.uvs; @@ -6678,8 +6849,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.lineTo(x2, y2); context.closePath(); - // context.fillStyle = "white"//rgb(1, 1, 1,1)); - // context.fill(); context.clip(); @@ -6703,7 +6872,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.restore(); }; -// context.globalCompositeOperation = 'source-over'; } /** @@ -6718,7 +6886,7 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) */ PIXI.CanvasGraphics = function() { - + } @@ -6734,35 +6902,33 @@ PIXI.CanvasGraphics = function() PIXI.CanvasGraphics.renderGraphics = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - - for (var i=0; i < graphics.graphicsData.length; i++) + + for (var i=0; i < graphics.graphicsData.length; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); context.lineWidth = data.lineWidth; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); - + context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6777,21 +6943,20 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.RECT) { - - // TODO - need to be Undefined! - if(data.fillColor) + + if(data.fillColor || data.fillColor === 0) { context.globalAlpha = data.fillAlpha * worldAlpha; context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); context.fillRect(points[0], points[1], points[2], points[3]); - + } if(data.lineWidth) { context.globalAlpha = data.lineAlpha * worldAlpha; context.strokeRect(points[0], points[1], points[2], points[3]); } - + } else if(data.type == PIXI.Graphics.CIRC) { @@ -6799,7 +6964,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.beginPath(); context.arc(points[0], points[1], points[2],0,2*Math.PI); context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6814,19 +6979,19 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - + var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6834,15 +6999,15 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - + context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6855,7 +7020,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.stroke(); } } - + }; } @@ -6871,37 +7036,35 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - + var len = graphics.graphicsData.length; if(len > 1) { len = 1; console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") } - - for (var i=0; i < 1; i++) + + for (var i=0; i < 1; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + } else if(data.type == PIXI.Graphics.RECT) { @@ -6918,18 +7081,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6937,7 +7100,7 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); @@ -6945,8 +7108,8 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); context.closePath(); } - - + + }; } @@ -6956,18 +7119,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) /** - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. + * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. * It is important to know that with the webGL renderer only simple polys can be filled at this stage * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png * - * @class Graphics + * @class Graphics * @extends DisplayObjectContainer * @constructor */ PIXI.Graphics = function() { PIXI.DisplayObjectContainer.call( this ); - + this.renderable = true; /** @@ -7028,14 +7191,14 @@ PIXI.Graphics.prototype.constructor = PIXI.Graphics; PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - + this.lineWidth = lineWidth || 0; this.lineColor = color || 0; this.lineAlpha = (alpha == undefined) ? 1 : alpha; - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.graphicsData.push(this.currentPath); } @@ -7049,12 +7212,12 @@ PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) PIXI.Graphics.prototype.moveTo = function(x, y) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.currentPath.points.push(x, y); - + this.graphicsData.push(this.currentPath); } @@ -7084,7 +7247,7 @@ PIXI.Graphics.prototype.beginFill = function(color, alpha) { this.filling = true; this.fillColor = color || 0; - this.fillAlpha = alpha || 1; + this.fillAlpha = (alpha == undefined) ? 1 : alpha; } /** @@ -7110,11 +7273,11 @@ PIXI.Graphics.prototype.endFill = function() PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.RECT}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7130,11 +7293,11 @@ PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) PIXI.Graphics.prototype.drawCircle = function( x, y, radius) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7151,11 +7314,11 @@ PIXI.Graphics.prototype.drawCircle = function( x, y, radius) PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.ELIP}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7169,7 +7332,7 @@ PIXI.Graphics.prototype.clear = function() { this.lineWidth = 0; this.filling = false; - + this.dirty = true; this.clearDirty = true; this.graphicsData = []; @@ -7190,20 +7353,20 @@ PIXI.Strip = function(texture, width, height) PIXI.DisplayObjectContainer.call( this ); this.texture = texture; this.blendMode = PIXI.blendModes.NORMAL; - + try { this.uvs = new Float32Array([0, 1, 1, 1, 1, 0, 0,1]); - + this.verticies = new Float32Array([0, 0, 0,0, 0,0, 0, 0, 0]); - + this.colors = new Float32Array([1, 1, 1, 1]); - + this.indices = new Uint16Array([0, 1, 2, 3]); } catch(error) @@ -7211,18 +7374,18 @@ PIXI.Strip = function(texture, width, height) this.uvs = [0, 1, 1, 1, 1, 0, 0,1]; - + this.verticies = [0, 0, 0,0, 0,0, 0, 0, 0]; - + this.colors = [1, 1, 1, 1]; - + this.indices = [0, 1, 2, 3]; } - - + + /* this.uvs = new Float32Array() this.verticies = new Float32Array() @@ -7231,7 +7394,7 @@ PIXI.Strip = function(texture, width, height) */ this.width = width; this.height = height; - + // load the texture! if(texture.baseTexture.hasLoaded) { @@ -7244,7 +7407,7 @@ PIXI.Strip = function(texture, width, height) this.onTextureUpdateBind = this.onTextureUpdate.bind(this); this.texture.addEventListener( 'update', this.onTextureUpdateBind ); } - + this.renderable = true; } @@ -7256,8 +7419,8 @@ PIXI.Strip.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.width = texture.frame.width; this.height = texture.frame.height; @@ -7280,7 +7443,7 @@ PIXI.Rope = function(texture, points) { PIXI.Strip.call( this, texture ); this.points = points; - + try { this.verticies = new Float32Array( points.length * 4); @@ -7291,12 +7454,12 @@ PIXI.Rope = function(texture, points) catch(error) { this.verticies = verticies - + this.uvs = uvs this.colors = colors this.indices = indices } - + this.refresh(); } @@ -7309,99 +7472,99 @@ PIXI.Rope.prototype.refresh = function() { var points = this.points; if(points.length < 1)return; - + var uvs = this.uvs var indices = this.indices; var colors = this.colors; - + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - + + uvs[0] = 0 uvs[1] = 1 uvs[2] = 0 uvs[3] = 1 - + colors[0] = 1; colors[1] = 1; - + indices[0] = 0; indices[1] = 1; - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; // time to do some smart drawing! var 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; } } PIXI.Rope.prototype.updateTransform = function() { - + var points = this.points; if(points.length < 1)return; - - var verticies = this.verticies - + + var verticies = this.verticies + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - verticies[0] = point.x + perp.x + + verticies[0] = point.x + perp.x verticies[1] = point.y + perp.y //+ 200 - verticies[2] = point.x - perp.x + verticies[2] = point.x - perp.x verticies[3] = point.y - perp.y//+200 // time to do some smart drawing! - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; - + if(i < points.length-1) { nextPoint = points[i+1]; @@ -7410,35 +7573,35 @@ PIXI.Rope.prototype.updateTransform = function() { nextPoint = point } - + perp.y = -(nextPoint.x - lastPoint.x); perp.x = nextPoint.y - lastPoint.y; - + var ratio = (1 - (i / (total-1))) * 10; if(ratio > 1)ratio = 1; - + var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); var 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; - - verticies[index] = point.x + perp.x + + verticies[index] = point.x + perp.x verticies[index+1] = point.y + perp.y - verticies[index+2] = point.x - perp.x + verticies[index+2] = point.x - perp.x verticies[index+3] = point.y - perp.y lastPoint = point; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); } PIXI.Rope.prototype.setTexture = function(texture) { - // stop current texture + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7494,7 +7657,7 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tileScale * @type Point - */ + */ this.tileScale = new PIXI.Point(1,1); /** @@ -7502,11 +7665,11 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tilePosition * @type Point - */ + */ this.tilePosition = new PIXI.Point(0,0); this.renderable = true; - + this.blendMode = PIXI.blendModes.NORMAL } @@ -7524,8 +7687,8 @@ PIXI.TilingSprite.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7546,10 +7709,10 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) /** * @author Mat Groves http://matgroves.com/ @Doormat23 * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * + * * Awesome JS run time provided by EsotericSoftware * https://github.com/EsotericSoftware/spine-runtimes - * + * */ /** @@ -7562,48 +7725,41 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) * @constructor * @param url {String} The url of the spine anim file to be used */ -PIXI.Spine = function(url) -{ +PIXI.Spine = function (url) { PIXI.DisplayObjectContainer.call(this); - + this.spineData = PIXI.AnimCache[url]; - - if(!this.spineData) - { + + if (!this.spineData) { throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: " + url); - return; } - - this.count = 0; - - this.sprites = []; - + this.skeleton = new spine.Skeleton(this.spineData); this.skeleton.updateWorldTransform(); - this.stateData = new spine.AnimationStateData(this.spineData); + this.stateData = new spine.AnimationStateData(this.spineData); this.state = new spine.AnimationState(this.stateData); - - // add the sprites.. - for (var i = 0; i < this.skeleton.drawOrder.length; i++) { - - var attachmentName = this.skeleton.drawOrder[i].data.attachmentName; - - // kind of an assumtion here. that its a png - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; - } - - - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(attachmentName)); - sprite.anchor.x = sprite.anchor.y = 0.5; - this.addChild(sprite); - this.sprites.push(sprite); - }; -} -PIXI.Spine.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); + 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)) { + continue; + } + var spriteName = attachment.rendererObject.name; + var sprite = this.createSprite(slot, attachment.rendererObject); + slot.currentSprite = sprite; + slot.currentSpriteName = spriteName; + slotContainer.addChild(sprite); + } +}; + +PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); PIXI.Spine.prototype.constructor = PIXI.Spine; /* @@ -7612,55 +7768,74 @@ PIXI.Spine.prototype.constructor = PIXI.Spine; * @method updateTransform * @private */ -PIXI.Spine.prototype.updateTransform = function() -{ - // TODO should make this time based really.. - this.state.update(1/60); +PIXI.Spine.prototype.updateTransform = function () { + this.lastTime = this.lastTime || Date.now(); + var timeDelta = (Date.now() - this.lastTime) * 0.001; + this.lastTime = Date.now(); + this.state.update(timeDelta); this.state.apply(this.skeleton); this.skeleton.updateWorldTransform(); - - for (var i = 0; i < this.skeleton.drawOrder.length; i++) - { - var slot = this.skeleton.drawOrder[i]; + 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 instanceof spine.RegionAttachment)) { + slotContainer.visible = false; + continue; + } - var x = slot.bone.worldX + slot.attachment.x * slot.bone.m00 + slot.attachment.y * slot.bone.m01 + slot.attachment.width * 0.5; - var y = slot.bone.worldY + slot.attachment.x * slot.bone.m10 + slot.attachment.y * slot.bone.m11 + slot.attachment.height * 0.5; - //console.log(x + ' : ' + y); - - - //console.log(slot.attachment.name) - if(slot.cacheName != slot.attachment.name) - { - var attachmentName = slot.attachment.name; - - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; + if (attachment.rendererObject) { + if (!slot.currentSpriteName || slot.currentSpriteName != attachment.name) { + var spriteName = attachment.rendererObject.name; + if (slot.currentSprite !== undefined) { + slot.currentSprite.visible = false; } - - this.sprites[i].setTexture(PIXI.TextureCache[attachmentName]); - - slot.cacheName = slot.attachment.name; + slot.sprites = slot.sprites || {}; + if (slot.sprites[spriteName] !== undefined) { + slot.sprites[spriteName].visible = true; + } else { + var sprite = this.createSprite(slot, attachment.rendererObject); + slotContainer.addChild(sprite); + } + slot.currentSprite = slot.sprites[spriteName]; + slot.currentSpriteName = spriteName; } - - x += -((slot.attachment.width * (slot.bone.worldScaleX + slot.attachment.scaleX - 1))>>1); - y += -((slot.attachment.height * (slot.bone.worldScaleY + slot.attachment.scaleY - 1))>>1); - - - this.sprites[i].position.x = x; - this.sprites[i].position.y = y; - this.sprites[i].rotation = (-(slot.bone.worldRotation + slot.attachment.rotation)) * (Math.PI/180); - } - + } + slotContainer.visible = true; + + 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 * Math.PI / 180); + } + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -} +}; + + +PIXI.Spine.prototype.createSprite = function (slot, descriptor) { + var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; + var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); + sprite.scale = descriptor.scale; + sprite.rotation = descriptor.rotation; + sprite.anchor.x = sprite.anchor.y = 0.5; + + slot.sprites = slot.sprites || {}; + slot.sprites[descriptor.name] = sprite; + return sprite; +}; /* * Awesome JS run time provided by EsotericSoftware - * + * * https://github.com/EsotericSoftware/spine-runtimes - * + * */ var spine = {}; @@ -7770,7 +7945,7 @@ spine.Slot.prototype = { this.g = data.g; this.b = data.b; this.a = data.a; - + var slotDatas = this.skeleton.data.slots; for (var i = 0, n = slotDatas.length; i < n; i++) { if (slotDatas[i] == data) { @@ -8001,6 +8176,7 @@ spine.TranslateTimeline.prototype = { var frameTime = frames[frameIndex]; var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); + bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; } @@ -8025,14 +8201,12 @@ spine.ScaleTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. - + var bone = skeleton.bones[this.boneIndex]; if (time >= frames[frames.length - 3]) { // Time is after last frame. bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - - return; } @@ -8070,6 +8244,7 @@ spine.ColorTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. + var slot = skeleton.slots[this.slotIndex]; if (time >= frames[frames.length - 5]) { // Time is after last frame. @@ -8119,7 +8294,7 @@ spine.AttachmentTimeline = function (frameCount) { spine.AttachmentTimeline.prototype = { slotIndex: 0, getFrameCount: function () { - return this.frames.length / 2; + return this.frames.length; }, setFrame: function (frameIndex, time, attachmentName) { this.frames[frameIndex] = time; @@ -8136,11 +8311,6 @@ spine.AttachmentTimeline.prototype = { frameIndex = spine.binarySearch(frames, time, 1) - 1; var attachmentName = this.attachmentNames[frameIndex]; - //console.log(skeleton.slots[this.slotIndex]) - - // change the name! - // skeleton.slots[this.slotIndex].attachmentName = attachmentName; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); } }; @@ -8312,11 +8482,9 @@ spine.Skeleton.prototype = { if (slot.data.name == slotName) { var attachment = null; if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; } - slot.setAttachment(attachment); return; } @@ -8398,7 +8566,6 @@ spine.RegionAttachment.prototype = { offset[7/*Y4*/] = localYCos + localX2Sin; }, computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; y += bone.worldY; var m00 = bone.m00; @@ -8422,6 +8589,7 @@ spine.AnimationStateData = function (skeletonData) { this.animationToMixTime = {}; }; spine.AnimationStateData.prototype = { + defaultMix: 0, setMixByName: function (fromName, toName, duration) { var from = this.skeletonData.findAnimation(fromName); if (!from) throw "Animation not found: " + fromName; @@ -8434,7 +8602,7 @@ spine.AnimationStateData.prototype = { }, getMix: function (from, to) { var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : 0; + return time ? time : this.defaultMix; } }; @@ -8474,7 +8642,7 @@ spine.AnimationState.prototype = { this.previous = null; } this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else + } else this.current.apply(skeleton, this.currentTime, this.currentLoop); }, clearAnimation: function () { @@ -8620,16 +8788,9 @@ spine.SkeletonJson.prototype = { name = map["name"] || name; var type = spine.AttachmentType[map["type"] || "region"]; - - // @ekelokorpi - // var attachment = this.attachmentLoader.newAttachment(skin, type, name); - var attachment = new spine.RegionAttachment(); - - // @Doormat23 - // add the name of the attachment - attachment.name = name; - + if (type == spine.AttachmentType.region) { + var attachment = new spine.RegionAttachment(); attachment.x = (map["x"] || 0) * this.scale; attachment.y = (map["y"] || 0) * this.scale; attachment.scaleX = map["scaleX"] || 1; @@ -8638,10 +8799,19 @@ spine.SkeletonJson.prototype = { attachment.width = (map["width"] || 32) * this.scale; attachment.height = (map["height"] || 32) * this.scale; attachment.updateOffset(); + + attachment.rendererObject = {}; + attachment.rendererObject.name = name; + attachment.rendererObject.scale = {}; + attachment.rendererObject.scale.x = attachment.scaleX; + attachment.rendererObject.scale.y = attachment.scaleY; + attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; + return attachment; } - return attachment; + throw "Unknown attachment type: " + type; }, + readAnimation: function (name, map, skeletonData) { var timelines = []; var duration = 0; @@ -8692,7 +8862,7 @@ spine.SkeletonJson.prototype = { } timelines.push(timeline); duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - + } else throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; } @@ -8735,8 +8905,8 @@ spine.SkeletonJson.prototype = { timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); } timelines.push(timeline); - // PIXI FIX - duration = Math.max(duration, timeline.frames[Math.floor(timeline.getFrameCount()) - 1]); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } else throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; } @@ -9005,14 +9175,14 @@ spine.Bone.yDown = true; /** * This object is one that will allow you to specify custom rendering functions based on render type * - * @class CustomRenderable + * @class CustomRenderable * @extends DisplayObject * @constructor */ PIXI.CustomRenderable = function() { PIXI.DisplayObject.call( this ); - + } // constructor @@ -9118,19 +9288,19 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } else { - + var scope = this; this.source.onload = function(){ - + scope.hasLoaded = true; scope.width = scope.source.width; scope.height = scope.source.height; - + // add it to somewhere... PIXI.texturesToUpdate.push(scope); scope.dispatchEvent( { type: 'loaded', content: scope } ); @@ -9143,7 +9313,7 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } @@ -9183,7 +9353,7 @@ PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) { // new Image() breaks tex loading in some versions of Chrome. // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); + var image = new Image();//document.createElement('img'); if (crossorigin) { image.crossOrigin = ''; @@ -9211,7 +9381,7 @@ PIXI.FrameCache = {}; * @uses EventTarget * @constructor * @param baseTexture {BaseTexture} The base texture source to create the texture from - * @param frmae {Rectangle} The rectangle frame of the texture to show + * @param frame {Rectangle} The rectangle frame of the texture to show */ PIXI.Texture = function(baseTexture, frame) { @@ -9256,7 +9426,7 @@ PIXI.Texture = function(baseTexture, frame) { if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); //console.log(frame) - + this.setFrame(frame); } else @@ -9335,13 +9505,13 @@ PIXI.Texture.prototype.setFrame = function(frame) PIXI.Texture.fromImage = function(imageUrl, crossorigin) { var texture = PIXI.TextureCache[imageUrl]; - + if(!texture) { texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); PIXI.TextureCache[imageUrl] = texture; } - + return texture; } @@ -9391,7 +9561,7 @@ PIXI.Texture.addTextureToCache = function(texture, id) } /** - * Remove a texture from the textureCache. + * Remove a texture from the textureCache. * * @static * @method removeTextureFromCache @@ -9503,15 +9673,7 @@ PIXI.RenderTexture.prototype.initWebGL = function() // create a projection matrix.. this.projection = new PIXI.Point(this.width/2 , this.height/2); -/* - this.projectionMatrix = PIXI.mat4.create(); - this.projectionMatrix[5] = 2/this.height// * 0.5; - this.projectionMatrix[13] = -1; - - this.projectionMatrix[0] = 2/this.width; - this.projectionMatrix[12] = -1; -*/ // set the correct render function.. this.render = this.renderWebGL; @@ -9525,10 +9687,6 @@ PIXI.RenderTexture.prototype.resize = function(width, height) this.width = width; this.height = height; - //this.frame.width = this.width - //this.frame.height = this.height; - - if(PIXI.gl) { this.projection.x = this.width/2 @@ -9592,6 +9750,7 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle var children = displayObject.children; //TODO -? create a new one??? dont think so! + var originalWorldTransform = displayObject.worldTransform; displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; // modify to flip... displayObject.worldTransform[4] = -1; @@ -9604,8 +9763,9 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle displayObject.worldTransform[5] -= position.y; } - - + PIXI.visibleCount++; + displayObject.vcount = PIXI.visibleCount; + for(var i=0,j=children.length; i- format + */ +PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) +{ + this.frames = []; + var cols = Math.floor(this.texture.width / frameWidth); + var rows = Math.floor(this.texture.height / frameHeight); + + var i=0; + for (var y=0; y x1 && x < x1 + this.width) + if(x >= x1 && x <= x1 + this.width) { var y1 = this.y; - - if(y > y1 && y < y1 + this.height) + + if(y >= y1 && y <= y1 + this.height) { return true; } @@ -165,7 +165,7 @@ PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; * @class Polygon * @constructor * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, - * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arugments passed can be + * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are * Numbers. @@ -232,9 +232,9 @@ PIXI.Polygon.prototype.contains = function(x, y) return inside; } +// constructor PIXI.Polygon.prototype.constructor = PIXI.Polygon; - /** * @author Chad Engler */ @@ -256,7 +256,7 @@ PIXI.Circle = function(x, y, radius) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number @@ -306,6 +306,7 @@ PIXI.Circle.prototype.contains = function(x, y) return (dx + dy <= r2); } +// constructor PIXI.Circle.prototype.constructor = PIXI.Circle; @@ -320,8 +321,8 @@ PIXI.Circle.prototype.constructor = PIXI.Circle; * @constructor * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse - * @param width {Number} The overall height of this ellipse - * @param height {Number} The overall width of this ellipse + * @param width {Number} The overall width of this ellipse + * @param height {Number} The overall height of this ellipse */ PIXI.Ellipse = function(x, y, width, height) { @@ -331,21 +332,21 @@ PIXI.Ellipse = function(x, y, width, height) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number * @default 0 */ this.y = y || 0; - + /** * @property width * @type Number * @default 0 */ this.width = width || 0; - + /** * @property height * @type Number @@ -394,11 +395,11 @@ PIXI.Ellipse.getBounds = function() return new PIXI.Rectangle(this.x, this.y, this.width, this.height); } +// constructor PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; - /* * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV * you both rock! @@ -426,7 +427,7 @@ PIXI.mat3.create = function() matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -442,7 +443,7 @@ PIXI.mat3.identity = function(matrix) matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -469,35 +470,35 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat3.multiply = function (mat, mat2, dest) +PIXI.mat3.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[0], a01 = mat[1], a02 = mat[2], a10 = mat[3], a11 = mat[4], a12 = mat[5], a20 = mat[6], a21 = mat[7], a22 = mat[8], - + b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; - + dest[0] = b00 * a00 + b01 * a10 + b02 * a20; dest[1] = b00 * a01 + b01 * a11 + b02 * a21; dest[2] = b00 * a02 + b01 * a12 + b02 * a22; - + dest[3] = b10 * a00 + b11 * a10 + b12 * a20; dest[4] = b10 * a01 + b11 * a11 + b12 * a21; dest[5] = b10 * a02 + b11 * a12 + b12 * a22; - + dest[6] = b20 * a00 + b21 * a10 + b22 * a20; dest[7] = b20 * a01 + b21 * a11 + b22 * a21; dest[8] = b20 * a02 + b21 * a12 + b22 * a22; - + return dest; } @@ -514,11 +515,11 @@ PIXI.mat3.clone = function(mat) matrix[6] = mat[6]; matrix[7] = mat[7]; matrix[8] = mat[8]; - + return matrix; } -PIXI.mat3.transpose = function (mat, dest) +PIXI.mat3.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values if (!dest || mat === dest) { @@ -546,30 +547,30 @@ PIXI.mat3.transpose = function (mat, dest) return dest; } -PIXI.mat3.toMat4 = function (mat, dest) +PIXI.mat3.toMat4 = function (mat, dest) { if (!dest) { dest = PIXI.mat4.create(); } - + dest[15] = 1; dest[14] = 0; dest[13] = 0; dest[12] = 0; - + dest[11] = 0; dest[10] = mat[8]; dest[9] = mat[7]; dest[8] = mat[6]; - + dest[7] = 0; dest[6] = mat[5]; dest[5] = mat[4]; dest[4] = mat[3]; - + dest[3] = 0; dest[2] = mat[2]; dest[1] = mat[1]; dest[0] = mat[0]; - + return dest; } @@ -597,19 +598,19 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat4.transpose = function (mat, dest) +PIXI.mat4.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) + if (!dest || mat === dest) { var a01 = mat[1], a02 = mat[2], a03 = mat[3], a12 = mat[6], a13 = mat[7], a23 = mat[11]; - + mat[1] = mat[4]; mat[2] = mat[8]; mat[3] = mat[12]; @@ -624,7 +625,7 @@ PIXI.mat4.transpose = function (mat, dest) mat[14] = a23; return mat; } - + dest[0] = mat[0]; dest[1] = mat[4]; dest[2] = mat[8]; @@ -644,18 +645,18 @@ PIXI.mat4.transpose = function (mat, dest) return dest; } -PIXI.mat4.multiply = function (mat, mat2, dest) +PIXI.mat4.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - + // Cache only the current line of the second matrix - var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; + var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; @@ -705,7 +706,6 @@ PIXI.DisplayObject = function() { this.last = this; this.first = this; - /** * The coordinate of the object relative to the local coordinates of the parent. * @@ -779,15 +779,6 @@ PIXI.DisplayObject = function() */ this.renderable = false; - /** - * [read-only] The visibility of the object based on world (parent) factors. - * - * @property worldVisible - * @type Boolean - * @readOnly - */ - this.worldVisible = false; - /** * [read-only] The display object container that contains this display object. * @@ -806,15 +797,6 @@ PIXI.DisplayObject = function() */ this.stage = null; - /** - * [read-only] The index of this object in the parent's `children` array - * - * @property childIndex - * @type Number - * @readOnly - */ - this.childIndex = 0; - /** * [read-only] The multiplied alpha of the displayobject * @@ -953,17 +935,6 @@ PIXI.DisplayObject = function() // constructor PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObject.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - } -});*/ - /** * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default * Instead of using this function you can now simply set the interactive property to true or false @@ -1011,16 +982,57 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { }, set: function(value) { - this._mask = value; - + if(value) { + if(this._mask) + { + value.start = this._mask.start; + value.end = this._mask.end; + } + else + { + this.addFilter(value); + value.renderable = false; + } + } + else + { + this.removeFilter(this._mask); + this._mask.renderable = true; + } + + this._mask = value; + } +}); + +/** + * Sets the filters for the displayObject. Currently there's a few limitations. + * 1: At the moment only one filter can be applied at a time.. + * 2: They cannot be nested. + * 3: There's no padding yet. + * 4: this is a webGL only feature. + * @property filters + * @type Array + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { + get: function() { + return this._filters; + }, + set: function(value) { + + //if(value == ) + if(value) + { + if(this._filters)this.removeFilter(this._filters); this.addFilter(value) } else { - this.removeFilter(); + if(this._filters)this.removeFilter(this._filters); } + + this._filters = value; } }); @@ -1031,19 +1043,21 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { * @param mask {Graphics} the graphics object to use as a filter * @private */ -PIXI.DisplayObject.prototype.addFilter = function(mask) +PIXI.DisplayObject.prototype.addFilter = function(data) { - if(this.filter)return; - this.filter = true; - + //if(this.filter)return; + //this.filter = true; // insert a filter block.. + // TODO Onject pool thease bad boys.. var start = new PIXI.FilterBlock(); var end = new PIXI.FilterBlock(); + data.start = start; + data.end = end; - start.mask = mask; - end.mask = mask; + start.data = data; + end.data = data; start.first = start.last = this; end.first = end.last = this; @@ -1051,9 +1065,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) start.open = true; /* - * * insert start - * */ var childFirst = start @@ -1084,9 +1096,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) // now insert the end filter block.. /* - * * insert end filter - * */ var childFirst = end var childLast = end @@ -1125,8 +1135,6 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) this.__renderGroup.addFilterBlocks(start, end); } - mask.renderable = false; - } /* @@ -1135,13 +1143,14 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) * @method removeFilter * @private */ -PIXI.DisplayObject.prototype.removeFilter = function() +PIXI.DisplayObject.prototype.removeFilter = function(data) { - if(!this.filter)return; - this.filter = false; - + //if(!this.filter)return; + //this.filter = false; + console.log("YUOIO") // modify the list.. - var startBlock = this.first; + var startBlock = data.start; + var nextObject = startBlock._iNext; var previousObject = startBlock._iPrev; @@ -1151,9 +1160,8 @@ PIXI.DisplayObject.prototype.removeFilter = function() this.first = startBlock._iNext; - // remove the end filter - var lastBlock = this.last; + var lastBlock = data.end; var nextObject = lastBlock._iNext; var previousObject = lastBlock._iPrev; @@ -1162,8 +1170,6 @@ PIXI.DisplayObject.prototype.removeFilter = function() previousObject._iNext = nextObject; // this is always true too! -// if(this.last == lastBlock) - //{ var tempLast = lastBlock._iPrev; // need to make sure the parents last is updated too var updateLast = this; @@ -1174,15 +1180,11 @@ PIXI.DisplayObject.prototype.removeFilter = function() if(!updateLast)break; } - var mask = startBlock.mask - mask.renderable = true; - // if webGL... if(this.__renderGroup) { this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); } - //} } /* @@ -1194,7 +1196,7 @@ PIXI.DisplayObject.prototype.removeFilter = function() PIXI.DisplayObject.prototype.updateTransform = function() { // TODO OPTIMIZE THIS!! with dirty - if(this.rotation != this.rotationCache) + if(this.rotation !== this.rotationCache) { this.rotationCache = this.rotation; this._sr = Math.sin(this.rotation); @@ -1236,9 +1238,12 @@ PIXI.DisplayObject.prototype.updateTransform = function() // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); this.worldAlpha = this.alpha * this.parent.worldAlpha; + + this.vcount = PIXI.visibleCount; } +PIXI.visibleCount = 0; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1270,18 +1275,6 @@ PIXI.DisplayObjectContainer = function() PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObjectContainer.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - - } -});*/ - /** * Adds a child to the container. * @@ -1299,11 +1292,10 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) } child.parent = this; - child.childIndex = this.children.length; this.children.push(child); - // updae the stage refference.. + // update the stage refference.. if(this.stage) { @@ -1326,7 +1318,7 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) var previousObject; // this could be wrong if there is a filter?? - if(this.filter) + if(this._filters) { previousObject = this.last._iPrev; } @@ -1338,7 +1330,6 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) nextObject = previousObject._iNext; // always true in this case - //this.last = child.last; // need to make sure the parents last is updated too var updateLast = this; var prevLast = previousObject; @@ -1402,7 +1393,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) } // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject; var previousObject; @@ -1410,7 +1401,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) if(index == this.children.length) { previousObject = this.last; - var updateLast = this;//.parent; + var updateLast = this; var prevLast = this.last; while(updateLast) { @@ -1539,7 +1530,7 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child) { // unlink // // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject = childLast._iNext; @@ -1609,7 +1600,6 @@ PIXI.DisplayObjectContainer.prototype.updateTransform = function() this.children[i].updateTransform(); } } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1739,9 +1729,18 @@ PIXI.Sprite.prototype.setTexture = function(texture) if(this.texture.baseTexture != texture.baseTexture) { this.textureChange = true; + this.texture = texture; + + if(this.__renderGroup) + { + this.__renderGroup.updateTexture(this); + } + } + else + { + this.texture = texture; } - this.texture = texture; this.updateFrame = true; } @@ -1798,7 +1797,6 @@ PIXI.Sprite.fromImage = function(imageId) return new PIXI.Sprite(texture); } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1814,7 +1812,7 @@ PIXI.Sprite.fromImage = function(imageId) PIXI.MovieClip = function(textures) { PIXI.Sprite.call(this, textures[0]); - + /** * The array of textures that make up the animation * @@ -1822,7 +1820,7 @@ PIXI.MovieClip = function(textures) * @type Array */ this.textures = textures; - + /** * The speed that the MovieClip will play at. Higher is faster, lower is slower * @@ -1848,7 +1846,7 @@ PIXI.MovieClip = function(textures) * @type Function */ this.onComplete = null; - + /** * [read-only] The index MovieClips current frame (this may not have to be a whole number) * @@ -1857,8 +1855,8 @@ PIXI.MovieClip = function(textures) * @default 0 * @readOnly */ - this.currentFrame = 0; - + this.currentFrame = 0; + /** * [read-only] Indicates if the MovieClip is currently playing * @@ -1873,6 +1871,23 @@ PIXI.MovieClip = function(textures) PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; +/** +* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures +* assigned to the MovieClip. +* +* @property totalFrames +* @type Number +* @default 0 +* @readOnly +*/ +Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { + get: function() { + + return this.textures.length; + } +}); + + /** * Stops the MovieClip * @@ -1928,11 +1943,13 @@ PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) PIXI.MovieClip.prototype.updateTransform = function() { PIXI.Sprite.prototype.updateTransform.call(this); - + if(!this.playing)return; - + this.currentFrame += this.animationSpeed; + var round = (this.currentFrame + 0.5) | 0; + if(this.loop || round < this.textures.length) { this.setTexture(this.textures[round % this.textures.length]); @@ -1952,14 +1969,49 @@ PIXI.MovieClip.prototype.updateTransform = function() -PIXI.FilterBlock = function(mask) +PIXI.FilterBlock = function() { - this.graphics = mask this.visible = true; this.renderable = true; } +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.ColorMatrixFilter = function() +{ + // set the uniforms + this.uniforms = { + matrix: {type: 'mat4', value: [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1]}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float invert;", + "uniform mat4 matrix;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", + "gl_FragColor = gl_FragColor * vColor;", + "}" + ]; + +} +Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { + get: function() { + return this.uniforms.matrix.value; + }, + set: function(value) { + this.uniforms.matrix.value = value; + } +}); /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1988,7 +2040,7 @@ PIXI.Text = function(text, style) this.setText(text); this.setStyle(style); - + this.updateText(); this.dirty = false; }; @@ -2030,7 +2082,7 @@ PIXI.Text.prototype.setStyle = function(style) * @methos setText * @param {String} text The copy that you would like the text to display */ -PIXI.Sprite.prototype.setText = function(text) +PIXI.Text.prototype.setText = function(text) { this.text = text.toString() || " "; this.dirty = true; @@ -2045,9 +2097,9 @@ PIXI.Sprite.prototype.setText = function(text) PIXI.Text.prototype.updateText = function() { this.context.font = this.style.font; - + var outputText = this.text; - + // word wrap // preserve original text if(this.style.wordWrap)outputText = this.wordWrap(this.text); @@ -2065,7 +2117,7 @@ PIXI.Text.prototype.updateText = function() maxLineWidth = Math.max(maxLineWidth, lineWidth); } this.canvas.width = maxLineWidth + this.style.strokeThickness; - + //calculate text height var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; this.canvas.height = lineHeight * lines.length; @@ -2073,7 +2125,7 @@ PIXI.Text.prototype.updateText = function() //set canvas text styles this.context.fillStyle = this.style.fill; this.context.font = this.style.font; - + this.context.strokeStyle = this.style.stroke; this.context.lineWidth = this.style.strokeThickness; @@ -2083,7 +2135,7 @@ PIXI.Text.prototype.updateText = function() for (i = 0; i < lines.length; i++) { var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); - + if(this.style.align == "right") { linePosition.x += maxLineWidth - lineWidths[i]; @@ -2103,7 +2155,7 @@ PIXI.Text.prototype.updateText = function() this.context.fillText(lines[i], linePosition.x, linePosition.y); } } - + this.updateTexture(); }; @@ -2119,10 +2171,10 @@ PIXI.Text.prototype.updateTexture = function() this.texture.baseTexture.height = this.canvas.height; this.texture.frame.width = this.canvas.width; this.texture.frame.height = this.canvas.height; - + this._width = this.canvas.width; this._height = this.canvas.height; - + PIXI.texturesToUpdate.push(this.texture.baseTexture); }; @@ -2136,10 +2188,10 @@ PIXI.Text.prototype.updateTransform = function() { if(this.dirty) { - this.updateText(); + this.updateText(); this.dirty = false; } - + PIXI.Sprite.prototype.updateTransform.call(this); }; @@ -2151,12 +2203,12 @@ PIXI.Text.prototype.updateTransform = function() * @param fontStyle {Object} * @private */ -PIXI.Text.prototype.determineFontHeight = function(fontStyle) +PIXI.Text.prototype.determineFontHeight = function(fontStyle) { // build a little reference dictionary so if the font style has been used return a // cached version... var result = PIXI.Text.heightCache[fontStyle]; - + if(!result) { var body = document.getElementsByTagName("body")[0]; @@ -2165,13 +2217,13 @@ PIXI.Text.prototype.determineFontHeight = function(fontStyle) dummy.appendChild(dummyText); dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); body.appendChild(dummy); - + result = dummy.offsetHeight; PIXI.Text.heightCache[fontStyle] = result; - + body.removeChild(dummy); } - + return result; }; @@ -2191,7 +2243,7 @@ PIXI.Text.prototype.wordWrap = function(text) if(p == start) { return 1; } - + if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) { if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) @@ -2208,7 +2260,7 @@ PIXI.Text.prototype.wordWrap = function(text) return arguments.callee(ctx, text, start, p, wrapWidth); } }; - + var lineWrap = function(ctx, text, wrapWidth) { if(ctx.measureText(text).width <= wrapWidth || text.length < 1) @@ -2218,14 +2270,14 @@ PIXI.Text.prototype.wordWrap = function(text) var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); }; - + var result = ""; var lines = text.split("\n"); for (var i = 0; i < lines.length; i++) { result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; } - + return result; }; @@ -2241,7 +2293,7 @@ PIXI.Text.prototype.destroy = function(destroyTexture) { this.texture.destroy(); } - + }; PIXI.Text.heightCache = {}; @@ -2252,7 +2304,7 @@ PIXI.Text.heightCache = {}; /** * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" - * You can generate the fnt files using + * You can generate the fnt files using * http://www.angelcode.com/products/bmfont/ for windows or * http://www.bmglyph.com/ for mac. * @@ -2342,7 +2394,7 @@ PIXI.BitmapText.prototype.updateText = function() prevCharCode = null; continue; } - + var charData = data.chars[charCode]; if(!charData) continue; @@ -2405,7 +2457,7 @@ PIXI.BitmapText.prototype.updateTransform = function() this.dirty = false; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); }; @@ -2414,10 +2466,8 @@ PIXI.BitmapText.fonts = {}; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ - - - -/** + + /** * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive * This manager also supports multitouch. * @@ -2451,6 +2501,8 @@ PIXI.InteractionManager = function(stage) */ this.touchs = {}; + + // helpers this.tempPoint = new PIXI.Point(); //this.tempMatrix = mat3.create(); @@ -2461,7 +2513,19 @@ PIXI.InteractionManager = function(stage) this.pool = []; this.interactiveItems = []; + this.interactionDOMElement = null; + //this will make it so that you dont have to call bind all the time + this.onMouseMove = this.onMouseMove.bind( this ); + this.onMouseDown = this.onMouseDown.bind(this); + this.onMouseOut = this.onMouseOut.bind(this); + this.onMouseUp = this.onMouseUp.bind(this); + + this.onTouchStart = this.onTouchStart.bind(this); + this.onTouchEnd = this.onTouchEnd.bind(this); + this.onTouchMove = this.onTouchMove.bind(this); + + this.last = 0; } @@ -2486,7 +2550,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj { var child = children[i]; - if(child.visible) { +// if(child.visible) { // push all interactive bits if(child.interactive) { @@ -2508,7 +2572,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj this.collectInteractiveSprite(child, iParent); } } - } +// } } } @@ -2521,27 +2585,68 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj */ PIXI.InteractionManager.prototype.setTarget = function(target) { + this.target = target; + + //check if the dom element has been set. If it has don't do anything + if( this.interactionDOMElement === null ) { + + this.setTargetDomElement( target.view ); + } + + document.body.addEventListener('mouseup', this.onMouseUp, true); +} + + +/** + * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM + * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element + * to receive those events + * + * @method setTargetDomElement + * @param domElement {DOMElement} the dom element which will receive mouse and touch events + * @private + */ +PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) +{ + //remove previouse listeners + if( this.interactionDOMElement !== null ) + { + this.interactionDOMElement.style['-ms-content-zooming'] = ''; + this.interactionDOMElement.style['-ms-touch-action'] = ''; + + this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); + this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); + this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); + this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); + this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); + } + + if (window.navigator.msPointerEnabled) { // time to remove some of that zoom in ja.. - target.view.style["-ms-content-zooming"] = "none"; - target.view.style["-ms-touch-action"] = "none" + domElement.style['-ms-content-zooming'] = 'none'; + domElement.style['-ms-touch-action'] = 'none'; // DO some window specific touch! } - - this.target = target; - target.view.addEventListener('mousemove', this.onMouseMove.bind(this), true); - target.view.addEventListener('mousedown', this.onMouseDown.bind(this), true); - document.body.addEventListener('mouseup', this.onMouseUp.bind(this), true); - target.view.addEventListener('mouseout', this.onMouseUp.bind(this), true); - - // aint no multi touch just yet! - target.view.addEventListener("touchstart", this.onTouchStart.bind(this), true); - target.view.addEventListener("touchend", this.onTouchEnd.bind(this), true); - target.view.addEventListener("touchmove", this.onTouchMove.bind(this), true); + + this.interactionDOMElement = domElement; + + domElement.addEventListener('mousemove', this.onMouseMove, true); + domElement.addEventListener('mousedown', this.onMouseDown, true); + domElement.addEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + domElement.addEventListener('touchstart', this.onTouchStart, true); + domElement.addEventListener('touchend', this.onTouchEnd, true); + domElement.addEventListener('touchmove', this.onTouchMove, true); } + /** * updates the state of interactive objects * @@ -2583,12 +2688,14 @@ PIXI.InteractionManager.prototype.update = function() // loop through interactive objects! var length = this.interactiveItems.length; - this.target.view.style.cursor = "default"; + this.interactionDOMElement.style.cursor = "default"; for (var i = 0; i < length; i++) { var item = this.interactiveItems[i]; - if(!item.visible)continue; + + + //if(!item.visible)continue; // OPTIMISATION - only calculate every time if the mousemove function exists.. // OK so.. does the object have any other interactive functions? @@ -2604,7 +2711,7 @@ PIXI.InteractionManager.prototype.update = function() // loks like there was a hit! if(item.__hit) { - if(item.buttonMode)this.target.view.style.cursor = "pointer"; + if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; if(!item.__isOver) { @@ -2639,7 +2746,7 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) { this.mouse.originalEvent = event || window.event; //IE uses window.event // TODO optimize by not check EVERY TIME! maybe half as often? // - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); @@ -2669,7 +2776,6 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) */ PIXI.InteractionManager.prototype.onMouseDown = function(event) { - event.preventDefault(); this.mouse.originalEvent = event || window.event; //IE uses window.event // loop through inteaction tree... @@ -2706,6 +2812,26 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) } } + +PIXI.InteractionManager.prototype.onMouseOut = function(event) +{ + var length = this.interactiveItems.length; + + this.interactionDOMElement.style.cursor = "default"; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.__isOver) + { + this.mouse.target = item; + if(item.mouseout)item.mouseout(this.mouse); + item.__isOver = false; + } + } +} + /** * Is called when the mouse button is released on the renderer element * @@ -2770,7 +2896,7 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) { var global = interactionData.global; - if(!item.visible)return false; + if(item.vcount !== PIXI.visibleCount)return false; var isSprite = (item instanceof PIXI.Sprite), worldTransform = item.worldTransform, @@ -2840,14 +2966,14 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) */ PIXI.InteractionManager.prototype.onTouchMove = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) { var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; + touchData.originalEvent = event || window.event; // update the touch position touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); @@ -2871,10 +2997,7 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) */ PIXI.InteractionManager.prototype.onTouchStart = function(event) { - event.preventDefault(); - this.mouse.originalEvent = event || window.event; //IE uses window.event - - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2884,6 +3007,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) var touchData = this.pool.pop(); if(!touchData)touchData = new PIXI.InteractionData(); + touchData.originalEvent = event || window.event; + this.touchs[touchEvent.identifier] = touchData; touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); @@ -2921,8 +3046,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) */ PIXI.InteractionManager.prototype.onTouchEnd = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + //this.mouse.originalEvent = event || window.event; //IE uses window.event + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2943,7 +3068,7 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) if(itemTouchData == touchData) { // so this one WAS down... - + touchData.originalEvent = event || window.event; // hitTest?? if(item.touchend || item.tap) @@ -3055,9 +3180,8 @@ PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; * @constructor * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format * like: 0xFFFFFF for white - * @param interactive {Boolean} enable / disable interaction (default is false) */ -PIXI.Stage = function(backgroundColor, interactive) +PIXI.Stage = function(backgroundColor) { PIXI.DisplayObjectContainer.call( this ); @@ -3077,7 +3201,7 @@ PIXI.Stage = function(backgroundColor, interactive) * @property interactive * @type Boolean */ - this.interactive = interactive; + this.interactive = true; /** * The interaction manage for this stage, manages all interactive activity on the stage @@ -3113,6 +3237,18 @@ PIXI.Stage = function(backgroundColor, interactive) PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); PIXI.Stage.prototype.constructor = PIXI.Stage; +/** + * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. + * This is useful for when you have other DOM elements ontop of the Canvas element. + * + * @method setInteractionDelegate + * @param domElement {DOMElement} This new domElement which will receive mouse/touch events + */ +PIXI.Stage.prototype.setInteractionDelegate = function(domElement) +{ + this.interactionManager.setTargetDomElement( domElement ); +} + /* * Updates the object transform for rendering * @@ -3122,6 +3258,7 @@ PIXI.Stage.prototype.constructor = PIXI.Stage; PIXI.Stage.prototype.updateTransform = function() { this.worldAlpha = 1; + this.vcount = PIXI.visibleCount; for(var i=0,j=this.children.length; i 100) { console.log("BREAK") break } - } + } } @@ -3361,14 +3466,14 @@ PIXI.runList = function(item) PIXI.EventTarget = function () { var listeners = {}; - + this.addEventListener = this.on = function ( type, listener ) { - - + + if ( listeners[ type ] === undefined ) { listeners[ type ] = []; - + } if ( listeners[ type ].indexOf( listener ) === - 1 ) { @@ -3379,11 +3484,17 @@ PIXI.EventTarget = function () { }; this.dispatchEvent = this.emit = function ( event ) { - - for ( var listener in listeners[ event.type ] ) { - listeners[ event.type ][ listener ]( event ); - + if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { + + return; + + } + + for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { + + listeners[ event.type ][ i ]( event ); + } }; @@ -3417,8 +3528,11 @@ PIXI.EventTarget = function () { * @param height {Number} the height of the renderers view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) + * + * antialias */ -PIXI.autoDetectRenderer = function(width, height, view, transparent) +PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) { if(!width)width = 800; if(!height)height = 600; @@ -3429,7 +3543,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) //console.log(webgl); if( webgl ) { - return new PIXI.WebGLRenderer(width, height, view, transparent); + return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); } return new PIXI.CanvasRenderer(width, height, view, transparent); @@ -3441,7 +3555,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) PolyK library url: http://polyk.ivank.net Released under MIT licence. - + Copyright (c) 2012 Ivan Kuckir Permission is hereby granted, free of charge, to any person @@ -3465,8 +3579,8 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - This is an amazing lib! - + This is an amazing lib! + slightly modified by mat groves (matgroves.com); */ @@ -3482,13 +3596,13 @@ PIXI.PolyK = {}; PIXI.PolyK.Triangulate = function(p) { var sign = true; - + var n = p.length>>1; if(n<3) return []; var tgs = []; var avl = []; for(var i=0; i 3) @@ -3496,11 +3610,11 @@ PIXI.PolyK.Triangulate = function(p) var i0 = avl[(i+0)%al]; var i1 = avl[(i+1)%al]; var i2 = avl[(i+2)%al]; - + var ax = p[2*i0], ay = p[2*i0+1]; var bx = p[2*i1], by = p[2*i1+1]; var cx = p[2*i2], cy = p[2*i2+1]; - + var earFound = false; if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) { @@ -3519,7 +3633,7 @@ PIXI.PolyK.Triangulate = function(p) al--; i = 0; } - else if(i++ > 3*al) + else if(i++ > 3*al) { // need to flip flip reverse it! // reset! @@ -3528,17 +3642,17 @@ PIXI.PolyK.Triangulate = function(p) var tgs = []; avl = []; for(var i=0; i= 0) == sign; } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -3612,13 +3725,11 @@ PIXI.shaderVertexSrc = [ "attribute vec2 aVertexPosition;", "attribute vec2 aTextureCoord;", "attribute float aColor;", - //"uniform mat4 uMVMatrix;", "uniform vec2 projectionVector;", "varying vec2 vTextureCoord;", "varying float vColor;", "void main(void) {", - // "gl_Position = uMVMatrix * vec4(aVertexPosition, 1.0, 1.0);", "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", "vTextureCoord = aTextureCoord;", "vColor = aColor;", @@ -3658,7 +3769,6 @@ PIXI.stripShaderVertexSrc = [ "}" ]; - /* * primitive shader.. */ @@ -3685,6 +3795,8 @@ PIXI.primitiveShaderVertexSrc = [ "}" ]; +PIXI.shaderStack = []; + PIXI.initPrimitiveShader = function() { var gl = PIXI.gl; @@ -3699,27 +3811,26 @@ PIXI.initPrimitiveShader = function() shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); + + //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(shaderProgram.colorAttribute); +//gl.enableVertexAttribArray(program.textureCoordAttribute); + shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); PIXI.primitiveProgram = shaderProgram; + + } PIXI.initDefaultShader = function() { - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.shaderVertexSrc, PIXI.shaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - // shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.shaderProgram = shaderProgram; + PIXI.defaultShader = new PIXI.PixiShader(); + PIXI.defaultShader.init(); + PIXI.activateShader(PIXI.defaultShader); + /* + PIXI.shaderStack.push(PIXI.defaultShader); + PIXI.current*/ } PIXI.initDefaultStripShader = function() @@ -3736,9 +3847,7 @@ PIXI.initDefaultStripShader = function() shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); PIXI.stripShaderProgram = shaderProgram; @@ -3789,35 +3898,135 @@ PIXI.compileProgram = function(vertexSrc, fragmentSrc) return shaderProgram; } +PIXI.activateShader = function(shader) +{ + PIXI.shaderStack.push(shader); + + //console.log(">>>") + var gl = PIXI.gl; + + var shaderProgram = shader.program; + + // map uniforms.. + gl.useProgram(shaderProgram); + + gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + gl.enableVertexAttribArray(shaderProgram.colorAttribute); + gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); -PIXI.activateDefaultShader = function() + shader.syncUniforms(); + + PIXI.currentShader = shaderProgram; +} + + +PIXI.popShader = function() { var gl = PIXI.gl; - var shaderProgram = PIXI.shaderProgram; + // activate last program.. + var lastProgram = PIXI.shaderStack.pop(); + + var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); + PIXI.currentShader = shaderProgram; } - - PIXI.activatePrimitiveShader = function() { var gl = PIXI.gl; - gl.disableVertexAttribArray(PIXI.shaderProgram.textureCoordAttribute); - gl.disableVertexAttribArray(PIXI.shaderProgram.colorAttribute); - gl.useProgram(PIXI.primitiveProgram); - gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); + gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + + //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); } +PIXI.deactivatePrimitiveShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.currentShader); + + gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.PixiShader = function() +{ + // the webGL program.. + this.program; + + this.fragmentSrc = [ + "precision lowp float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", + "}" + ]; + +} + +PIXI.PixiShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get the default shader bits! + program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); + program.colorAttribute = gl.getAttribLocation(program, "aColor"); + program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); + + program.projectionVector = gl.getUniformLocation(program, "projectionVector"); + program.samplerUniform = gl.getUniformLocation(program, "uSampler"); + + // add those custom shaders! + for (var key in this.uniforms) + { + // get the uniform locations.. + program[key] = gl.getUniformLocation(program, key); + } + + this.program = program; +} + +PIXI.PixiShader.prototype.syncUniforms = function() +{ + var gl = PIXI.gl; + + for (var key in this.uniforms) + { + //var + var type = this.uniforms[key].type; + + // need to grow this! + if(type == "f") + { + gl.uniform1f(this.program[key], this.uniforms[key].value); + } + else if(type == "mat4") + { + gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); + } + } + +} + /** * @author Mat Groves http://matgroves.com/ @Doormat23 @@ -3887,7 +4096,7 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); // WHY DOES THIS LINE NEED TO BE THERE??? - gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // its not even used.. but need to be set or it breaks? // only on pc though.. @@ -3899,8 +4108,10 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); + PIXI.deactivatePrimitiveShader(); + // return to default shader... - PIXI.activateDefaultShader(); +// PIXI.activateShader(PIXI.defaultShader); } /** @@ -4243,7 +4454,7 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) verts.push(px , py); verts.push(r, g, b, alpha); - verts.push(p2x - (px-p2x), p2y - (py - p2y));//, 4); + verts.push(p2x - (px-p2x), p2y - (py - p2y)); verts.push(r, g, b, alpha); } } @@ -4356,9 +4567,10 @@ PIXI.gl; * @param height=0 {Number} the height of the canvas view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) * */ -PIXI.WebGLRenderer = function(width, height, view, transparent) +PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) { // do a catch.. only 1 webGL renderer.. @@ -4382,7 +4594,7 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) { PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { alpha: this.transparent, - antialias:true, // SPEED UP?? + antialias:!!antialias, // SPEED UP?? premultipliedAlpha:false, stencil:true }); @@ -4392,11 +4604,12 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); } - PIXI.initPrimitiveShader(); PIXI.initDefaultShader(); + PIXI.initPrimitiveShader(); PIXI.initDefaultStripShader(); - PIXI.activateDefaultShader(); + +// PIXI.activateDefaultShader(); var gl = this.gl; PIXI.WebGLRenderer.gl = gl; @@ -4413,7 +4626,10 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) this.resize(this.width, this.height); this.contextLost = false; + PIXI.activateShader(PIXI.defaultShader); + this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); + } // constructor @@ -4469,8 +4685,6 @@ PIXI.WebGLRenderer.prototype.render = function(stage) { // TODO make this work // dont think this is needed any more? - //if(this.__stage)this.checkVisibility(this.__stage, false) - this.__stage = stage; this.stageRenderGroup.setRenderable(stage); } @@ -4487,10 +4701,8 @@ PIXI.WebGLRenderer.prototype.render = function(stage) // update any textures PIXI.WebGLRenderer.updateTextures(); - // recursivly loop through all items! - //this.checkVisibility(stage, true); - // update the scene graph + PIXI.visibleCount++; stage.updateTransform(); var gl = this.gl; @@ -4499,16 +4711,12 @@ PIXI.WebGLRenderer.prototype.render = function(stage) gl.colorMask(true, true, true, this.transparent); gl.viewport(0, 0, this.width, this.height); - // set the correct matrix.. - // gl.uniformMatrix4fv(this.shaderProgram.mvMatrixUniform, false, this.projectionMatrix); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); gl.clear(gl.COLOR_BUFFER_BIT); // HACK TO TEST - //PIXI.projectionMatrix = this.projectionMatrix; this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; this.stageRenderGroup.render(PIXI.projection); @@ -4546,8 +4754,9 @@ PIXI.WebGLRenderer.prototype.render = function(stage) */ PIXI.WebGLRenderer.updateTextures = function() { - for (var i=0; i < PIXI.texturesToUpdate.length; i++) this.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) this.destroyTexture(PIXI.texturesToDestroy[i]); + //TODO break this out into a texture manager... + for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); + for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; } @@ -4562,6 +4771,7 @@ PIXI.WebGLRenderer.updateTextures = function() */ PIXI.WebGLRenderer.updateTexture = function(texture) { + //TODO break this out into a texture manager... var gl = PIXI.gl; if(!texture._glTexture) @@ -4602,9 +4812,10 @@ PIXI.WebGLRenderer.updateTexture = function(texture) * @param texture {Texture} The texture to update * @private */ -PIXI.WebGLRenderer.prototype.destroyTexture = function(texture) +PIXI.WebGLRenderer.destroyTexture = function(texture) { - var gl = this.gl; + //TODO break this out into a texture manager... + var gl = PIXI.gl; if(texture._glTexture) { @@ -4768,7 +4979,6 @@ PIXI.WebGLBatch.prototype.clean = function() this.uvs = []; this.indices = []; this.colors = []; - //this.sprites = []; this.dynamicSize = 1; this.texture = null; this.last = null; @@ -4805,7 +5015,6 @@ PIXI.WebGLBatch.prototype.init = function(sprite) this.dirty = true; this.blendMode = sprite.blendMode; this.texture = sprite.texture.baseTexture; -// this.sprites.push(sprite); this.head = sprite; this.tail = sprite; this.size = 1; @@ -4838,7 +5047,6 @@ PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) else { this.head = sprite; - //this.head.__prev = null } } @@ -4926,7 +5134,7 @@ PIXI.WebGLBatch.prototype.split = function(sprite) { this.dirty = true; - var batch = new PIXI.WebGLBatch(this.gl);//PIXI._getBatch(this.gl); + var batch = new PIXI.WebGLBatch(this.gl); batch.init(sprite); batch.texture = this.texture; batch.tail = this.tail; @@ -4936,8 +5144,6 @@ PIXI.WebGLBatch.prototype.split = function(sprite) sprite.__prev = null; // return a splite batch! - //sprite.__prev.__next = null; - //sprite.__prev = null; // TODO this size is wrong! // need to recalculate :/ problem with a linked list! @@ -5007,13 +5213,13 @@ PIXI.WebGLBatch.prototype.growBatch = function() gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); - this.uvs = new Float32Array( this.dynamicSize * 8 ) + this.uvs = new Float32Array( this.dynamicSize * 8 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); this.dirtyUVS = true; - this.colors = new Float32Array( this.dynamicSize * 4 ) + this.colors = new Float32Array( this.dynamicSize * 4 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); @@ -5112,7 +5318,7 @@ PIXI.WebGLBatch.prototype.update = function() while(displayObject) { - if(displayObject.worldVisible) + if(displayObject.vcount === PIXI.visibleCount) { width = displayObject.texture.frame.width; height = displayObject.texture.frame.height; @@ -5214,7 +5420,7 @@ PIXI.WebGLBatch.prototype.update = function() PIXI.WebGLBatch.prototype.render = function(start, end) { start = start || 0; - //end = end || this.size; + if(end == undefined)end = this.size; if(this.dirty) @@ -5230,8 +5436,9 @@ PIXI.WebGLBatch.prototype.render = function(start, end) //TODO optimize this! - var shaderProgram = PIXI.shaderProgram; - gl.useProgram(shaderProgram); + var shaderProgram = PIXI.currentShader; + + //gl.useProgram(shaderProgram); // update the verts.. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); @@ -5239,6 +5446,8 @@ PIXI.WebGLBatch.prototype.render = function(start, end) gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // update the uvs + var isDefault = (shaderProgram == PIXI.shaderProgram) + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); if(this.dirtyUVS) @@ -5262,13 +5471,11 @@ PIXI.WebGLBatch.prototype.render = function(start, end) } gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - //var startIndex = 0//1; var len = end - start; - // console.log(this.size) + // DRAW THAT this! gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); } @@ -5336,77 +5543,45 @@ PIXI.WebGLRenderGroup.prototype.render = function(projection) PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - // TODO remove this by replacing visible with getter setters.. - this.checkVisibility(this.root, this.root.visible); - // will render all the elements in the group var renderable; - - for (var i=0; i < this.batchs.length; i++) { + renderable = this.batchs[i]; if(renderable instanceof PIXI.WebGLBatch) { this.batchs[i].render(); + continue; } - else if(renderable instanceof PIXI.TilingSprite) + + // non sprite batch.. + var worldVisible = renderable.vcount === PIXI.visibleCount; + + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ - if(renderable.open) - { - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - gl.colorMask(true, true, true, false); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - else - { - gl.disable(gl.STENCIL_TEST); - } + this.handleFilterBlock(renderable, projection); } } } -/** - * Renders the stage to its webgl view - * - * @method handleFilter - * @param filter {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.handleFilter = function(filter, projection) -{ - -} - /** * Renders a specific displayObject * @@ -5420,11 +5595,8 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - this.checkVisibility(displayObject, displayObject.visible); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); -// gl.uniformMatrix4fv(PIXI.shaderProgram.mvMatrixUniform, false, projectionMatrix); - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); - // to do! // render part of the scene... @@ -5483,7 +5655,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project while(lastItem.children.length > 0) { lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem; + if(lastItem.renderable)lastRenderable = lastItem.last; } if(lastRenderable instanceof PIXI.Sprite) @@ -5577,45 +5749,80 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project */ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) { + var sta = PIXI.shaderStack.length; + + var worldVisible = renderable.vcount === PIXI.visibleCount + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.CustomRenderable) { - if(renderable.visible) renderable.renderWebGL(this, projection); + if(worldVisible) renderable.renderWebGL(this, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ + this.handleFilterBlock(renderable, projection); + } +} - var gl = PIXI.gl; +PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) +{ + /* + * for now only masks are supported.. + */ + var gl = PIXI.gl; - if(renderable.open) + if(renderable.open) + { + if(renderable.data instanceof Array) + { + var filter = renderable.data[0]; + + if(!filter.shader) + { + var shader = new PIXI.PixiShader(); + + shader.fragmentSrc = filter.fragmentSrc; + shader.uniforms = filter.uniforms; + shader.init(); + + filter.shader = shader + } + + PIXI.activateShader(filter.shader); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } + else { gl.enable(gl.STENCIL_TEST); gl.colorMask(false, false, false, false); gl.stencilFunc(gl.ALWAYS,1,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - // we know this is a render texture so enable alpha too.. + PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); + gl.colorMask(true, true, true, true); gl.stencilFunc(gl.NOTEQUAL,0,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); } + } + else + { + if(renderable.data instanceof Array) + { + PIXI.popShader(); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } else { gl.disable(gl.STENCIL_TEST); @@ -5623,42 +5830,6 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) } } -/** - * Checks the visibility of a displayObject - * - * @method checkVisibility - * @param displayObject {DisplayObject} - * @param globalVisible {Boolean} - * @private - */ -PIXI.WebGLRenderGroup.prototype.checkVisibility = function(displayObject, globalVisible) -{ - // give the dp a reference to its renderGroup... - var children = displayObject.children; - //displayObject.worldVisible = globalVisible; - for (var i=0; i < children.length; i++) - { - var child = children[i]; - - // TODO optimize... should'nt need to loop through everything all the time - child.worldVisible = child.visible && globalVisible; - - // everything should have a batch! - // time to see whats new! - if(child.textureChange) - { - child.textureChange = false; - if(child.worldVisible)this.updateTexture(child); - // update texture!! - } - - if(child.children.length > 0) - { - this.checkVisibility(child, child.worldVisible); - } - }; -} - /** * Updates a webgl texture * @@ -5719,7 +5890,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * It keeps going back until it finds a sprite or the stage */ var previousRenderable = start; - while(previousRenderable != this.root) + while(previousRenderable != this.root.first) { previousRenderable = previousRenderable._iPrev; if(previousRenderable.renderable && previousRenderable.__renderGroup)break; @@ -5733,7 +5904,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * scene graph */ var previousRenderable2 = end; - while(previousRenderable2 != this.root) + while(previousRenderable2 != this.root.first) { previousRenderable2 = previousRenderable2._iPrev; if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; @@ -6105,6 +6276,7 @@ PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) } } + /** * Initializes a tiling sprite * @@ -6175,23 +6347,19 @@ PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) { var gl = this.gl; - var shaderProgram = PIXI.shaderProgram; -// mat - //var mat4Real = PIXI.mat3.toMat4(strip.worldTransform); - //PIXI.mat4.transpose(mat4Real); - //PIXI.mat4.multiply(projectionMatrix, mat4Real, mat4Real ) - + var shaderProgram = PIXI.stripShaderProgram; - gl.useProgram(PIXI.stripShaderProgram); + + gl.useProgram(shaderProgram); var m = PIXI.mat3.clone(strip.worldTransform); PIXI.mat3.transpose(m); // set the matrix transform for the - gl.uniformMatrix3fv(PIXI.stripShaderProgram.translationMatrix, false, m); - gl.uniform2f(PIXI.stripShaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(PIXI.stripShaderProgram.alpha, strip.worldAlpha); + gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); + gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); /* if(strip.blendMode == PIXI.blendModes.NORMAL) @@ -6249,11 +6417,10 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } - //console.log(gl.TRIANGLE_STRIP); gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - gl.useProgram(PIXI.shaderProgram); + gl.useProgram(PIXI.currentProgram); } /** @@ -6328,6 +6495,7 @@ PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } + /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -6401,7 +6569,6 @@ PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; */ PIXI.CanvasRenderer.prototype.render = function(stage) { - // update children if need be //stage.__childrenAdded = []; //stage.__childrenRemoved = []; @@ -6410,6 +6577,7 @@ PIXI.CanvasRenderer.prototype.render = function(stage) PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; + PIXI.visibleCount++; stage.updateTransform(); // update the background color @@ -6496,7 +6664,7 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) var frame = displayObject.texture.frame; - if(frame) + if(frame && frame.width && frame.height) { context.globalAlpha = displayObject.worldAlpha; @@ -6534,31 +6702,34 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) } else if(displayObject instanceof PIXI.FilterBlock) { - if(displayObject.open) + if(PIXI.FilterBlock.data instanceof PIXI.Graphics) { - context.save(); - - var cacheAlpha = displayObject.mask.alpha; - var maskTransform = displayObject.mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - displayObject.mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); - // context.fillStyle = 0xFF0000; - // context.fillRect(0, 0, 200, 200); - context.clip(); - - displayObject.mask.worldAlpha = cacheAlpha; - //context.globalCompositeOperation = 'lighter'; + if(displayObject.open) + { + context.save(); + + var cacheAlpha = displayObject.mask.alpha; + var maskTransform = displayObject.mask.worldTransform; + + context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) + + displayObject.mask.worldAlpha = 0.5; + + context.worldAlpha = 0; + + PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); + context.clip(); + + displayObject.mask.worldAlpha = cacheAlpha; + } + else + { + context.restore(); + } } else { - //context.globalCompositeOperation = 'source-over'; - context.restore(); + // only masks supported right now! } } // count++ @@ -6651,7 +6822,7 @@ PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) PIXI.CanvasRenderer.prototype.renderStrip = function(strip) { var context = this.context; - //context.globalCompositeOperation = 'lighter'; + // draw triangles!! var verticies = strip.verticies; var uvs = strip.uvs; @@ -6678,8 +6849,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.lineTo(x2, y2); context.closePath(); - // context.fillStyle = "white"//rgb(1, 1, 1,1)); - // context.fill(); context.clip(); @@ -6703,7 +6872,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.restore(); }; -// context.globalCompositeOperation = 'source-over'; } /** @@ -6718,7 +6886,7 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) */ PIXI.CanvasGraphics = function() { - + } @@ -6734,35 +6902,33 @@ PIXI.CanvasGraphics = function() PIXI.CanvasGraphics.renderGraphics = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - - for (var i=0; i < graphics.graphicsData.length; i++) + + for (var i=0; i < graphics.graphicsData.length; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); context.lineWidth = data.lineWidth; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); - + context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6777,21 +6943,20 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.RECT) { - - // TODO - need to be Undefined! - if(data.fillColor) + + if(data.fillColor || data.fillColor === 0) { context.globalAlpha = data.fillAlpha * worldAlpha; context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); context.fillRect(points[0], points[1], points[2], points[3]); - + } if(data.lineWidth) { context.globalAlpha = data.lineAlpha * worldAlpha; context.strokeRect(points[0], points[1], points[2], points[3]); } - + } else if(data.type == PIXI.Graphics.CIRC) { @@ -6799,7 +6964,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.beginPath(); context.arc(points[0], points[1], points[2],0,2*Math.PI); context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6814,19 +6979,19 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - + var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6834,15 +6999,15 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - + context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6855,7 +7020,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.stroke(); } } - + }; } @@ -6871,37 +7036,35 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - + var len = graphics.graphicsData.length; if(len > 1) { len = 1; console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") } - - for (var i=0; i < 1; i++) + + for (var i=0; i < 1; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + } else if(data.type == PIXI.Graphics.RECT) { @@ -6918,18 +7081,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6937,7 +7100,7 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); @@ -6945,8 +7108,8 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); context.closePath(); } - - + + }; } @@ -6956,18 +7119,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) /** - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. + * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. * It is important to know that with the webGL renderer only simple polys can be filled at this stage * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png * - * @class Graphics + * @class Graphics * @extends DisplayObjectContainer * @constructor */ PIXI.Graphics = function() { PIXI.DisplayObjectContainer.call( this ); - + this.renderable = true; /** @@ -7028,14 +7191,14 @@ PIXI.Graphics.prototype.constructor = PIXI.Graphics; PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - + this.lineWidth = lineWidth || 0; this.lineColor = color || 0; this.lineAlpha = (alpha == undefined) ? 1 : alpha; - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.graphicsData.push(this.currentPath); } @@ -7049,12 +7212,12 @@ PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) PIXI.Graphics.prototype.moveTo = function(x, y) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.currentPath.points.push(x, y); - + this.graphicsData.push(this.currentPath); } @@ -7084,7 +7247,7 @@ PIXI.Graphics.prototype.beginFill = function(color, alpha) { this.filling = true; this.fillColor = color || 0; - this.fillAlpha = alpha || 1; + this.fillAlpha = (alpha == undefined) ? 1 : alpha; } /** @@ -7110,11 +7273,11 @@ PIXI.Graphics.prototype.endFill = function() PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.RECT}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7130,11 +7293,11 @@ PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) PIXI.Graphics.prototype.drawCircle = function( x, y, radius) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7151,11 +7314,11 @@ PIXI.Graphics.prototype.drawCircle = function( x, y, radius) PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.ELIP}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7169,7 +7332,7 @@ PIXI.Graphics.prototype.clear = function() { this.lineWidth = 0; this.filling = false; - + this.dirty = true; this.clearDirty = true; this.graphicsData = []; @@ -7190,20 +7353,20 @@ PIXI.Strip = function(texture, width, height) PIXI.DisplayObjectContainer.call( this ); this.texture = texture; this.blendMode = PIXI.blendModes.NORMAL; - + try { this.uvs = new Float32Array([0, 1, 1, 1, 1, 0, 0,1]); - + this.verticies = new Float32Array([0, 0, 0,0, 0,0, 0, 0, 0]); - + this.colors = new Float32Array([1, 1, 1, 1]); - + this.indices = new Uint16Array([0, 1, 2, 3]); } catch(error) @@ -7211,18 +7374,18 @@ PIXI.Strip = function(texture, width, height) this.uvs = [0, 1, 1, 1, 1, 0, 0,1]; - + this.verticies = [0, 0, 0,0, 0,0, 0, 0, 0]; - + this.colors = [1, 1, 1, 1]; - + this.indices = [0, 1, 2, 3]; } - - + + /* this.uvs = new Float32Array() this.verticies = new Float32Array() @@ -7231,7 +7394,7 @@ PIXI.Strip = function(texture, width, height) */ this.width = width; this.height = height; - + // load the texture! if(texture.baseTexture.hasLoaded) { @@ -7244,7 +7407,7 @@ PIXI.Strip = function(texture, width, height) this.onTextureUpdateBind = this.onTextureUpdate.bind(this); this.texture.addEventListener( 'update', this.onTextureUpdateBind ); } - + this.renderable = true; } @@ -7256,8 +7419,8 @@ PIXI.Strip.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.width = texture.frame.width; this.height = texture.frame.height; @@ -7280,7 +7443,7 @@ PIXI.Rope = function(texture, points) { PIXI.Strip.call( this, texture ); this.points = points; - + try { this.verticies = new Float32Array( points.length * 4); @@ -7291,12 +7454,12 @@ PIXI.Rope = function(texture, points) catch(error) { this.verticies = verticies - + this.uvs = uvs this.colors = colors this.indices = indices } - + this.refresh(); } @@ -7309,99 +7472,99 @@ PIXI.Rope.prototype.refresh = function() { var points = this.points; if(points.length < 1)return; - + var uvs = this.uvs var indices = this.indices; var colors = this.colors; - + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - + + uvs[0] = 0 uvs[1] = 1 uvs[2] = 0 uvs[3] = 1 - + colors[0] = 1; colors[1] = 1; - + indices[0] = 0; indices[1] = 1; - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; // time to do some smart drawing! var 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; } } PIXI.Rope.prototype.updateTransform = function() { - + var points = this.points; if(points.length < 1)return; - - var verticies = this.verticies - + + var verticies = this.verticies + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - verticies[0] = point.x + perp.x + + verticies[0] = point.x + perp.x verticies[1] = point.y + perp.y //+ 200 - verticies[2] = point.x - perp.x + verticies[2] = point.x - perp.x verticies[3] = point.y - perp.y//+200 // time to do some smart drawing! - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; - + if(i < points.length-1) { nextPoint = points[i+1]; @@ -7410,35 +7573,35 @@ PIXI.Rope.prototype.updateTransform = function() { nextPoint = point } - + perp.y = -(nextPoint.x - lastPoint.x); perp.x = nextPoint.y - lastPoint.y; - + var ratio = (1 - (i / (total-1))) * 10; if(ratio > 1)ratio = 1; - + var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); var 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; - - verticies[index] = point.x + perp.x + + verticies[index] = point.x + perp.x verticies[index+1] = point.y + perp.y - verticies[index+2] = point.x - perp.x + verticies[index+2] = point.x - perp.x verticies[index+3] = point.y - perp.y lastPoint = point; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); } PIXI.Rope.prototype.setTexture = function(texture) { - // stop current texture + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7494,7 +7657,7 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tileScale * @type Point - */ + */ this.tileScale = new PIXI.Point(1,1); /** @@ -7502,11 +7665,11 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tilePosition * @type Point - */ + */ this.tilePosition = new PIXI.Point(0,0); this.renderable = true; - + this.blendMode = PIXI.blendModes.NORMAL } @@ -7524,8 +7687,8 @@ PIXI.TilingSprite.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7546,10 +7709,10 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) /** * @author Mat Groves http://matgroves.com/ @Doormat23 * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * + * * Awesome JS run time provided by EsotericSoftware * https://github.com/EsotericSoftware/spine-runtimes - * + * */ /** @@ -7562,48 +7725,41 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) * @constructor * @param url {String} The url of the spine anim file to be used */ -PIXI.Spine = function(url) -{ +PIXI.Spine = function (url) { PIXI.DisplayObjectContainer.call(this); - + this.spineData = PIXI.AnimCache[url]; - - if(!this.spineData) - { + + if (!this.spineData) { throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: " + url); - return; } - - this.count = 0; - - this.sprites = []; - + this.skeleton = new spine.Skeleton(this.spineData); this.skeleton.updateWorldTransform(); - this.stateData = new spine.AnimationStateData(this.spineData); + this.stateData = new spine.AnimationStateData(this.spineData); this.state = new spine.AnimationState(this.stateData); - - // add the sprites.. - for (var i = 0; i < this.skeleton.drawOrder.length; i++) { - - var attachmentName = this.skeleton.drawOrder[i].data.attachmentName; - - // kind of an assumtion here. that its a png - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; - } - - - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(attachmentName)); - sprite.anchor.x = sprite.anchor.y = 0.5; - this.addChild(sprite); - this.sprites.push(sprite); - }; -} -PIXI.Spine.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); + 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)) { + continue; + } + var spriteName = attachment.rendererObject.name; + var sprite = this.createSprite(slot, attachment.rendererObject); + slot.currentSprite = sprite; + slot.currentSpriteName = spriteName; + slotContainer.addChild(sprite); + } +}; + +PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); PIXI.Spine.prototype.constructor = PIXI.Spine; /* @@ -7612,55 +7768,74 @@ PIXI.Spine.prototype.constructor = PIXI.Spine; * @method updateTransform * @private */ -PIXI.Spine.prototype.updateTransform = function() -{ - // TODO should make this time based really.. - this.state.update(1/60); +PIXI.Spine.prototype.updateTransform = function () { + this.lastTime = this.lastTime || Date.now(); + var timeDelta = (Date.now() - this.lastTime) * 0.001; + this.lastTime = Date.now(); + this.state.update(timeDelta); this.state.apply(this.skeleton); this.skeleton.updateWorldTransform(); - - for (var i = 0; i < this.skeleton.drawOrder.length; i++) - { - var slot = this.skeleton.drawOrder[i]; + 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 instanceof spine.RegionAttachment)) { + slotContainer.visible = false; + continue; + } - var x = slot.bone.worldX + slot.attachment.x * slot.bone.m00 + slot.attachment.y * slot.bone.m01 + slot.attachment.width * 0.5; - var y = slot.bone.worldY + slot.attachment.x * slot.bone.m10 + slot.attachment.y * slot.bone.m11 + slot.attachment.height * 0.5; - //console.log(x + ' : ' + y); - - - //console.log(slot.attachment.name) - if(slot.cacheName != slot.attachment.name) - { - var attachmentName = slot.attachment.name; - - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; + if (attachment.rendererObject) { + if (!slot.currentSpriteName || slot.currentSpriteName != attachment.name) { + var spriteName = attachment.rendererObject.name; + if (slot.currentSprite !== undefined) { + slot.currentSprite.visible = false; } - - this.sprites[i].setTexture(PIXI.TextureCache[attachmentName]); - - slot.cacheName = slot.attachment.name; + slot.sprites = slot.sprites || {}; + if (slot.sprites[spriteName] !== undefined) { + slot.sprites[spriteName].visible = true; + } else { + var sprite = this.createSprite(slot, attachment.rendererObject); + slotContainer.addChild(sprite); + } + slot.currentSprite = slot.sprites[spriteName]; + slot.currentSpriteName = spriteName; } - - x += -((slot.attachment.width * (slot.bone.worldScaleX + slot.attachment.scaleX - 1))>>1); - y += -((slot.attachment.height * (slot.bone.worldScaleY + slot.attachment.scaleY - 1))>>1); - - - this.sprites[i].position.x = x; - this.sprites[i].position.y = y; - this.sprites[i].rotation = (-(slot.bone.worldRotation + slot.attachment.rotation)) * (Math.PI/180); - } - + } + slotContainer.visible = true; + + 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 * Math.PI / 180); + } + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -} +}; + + +PIXI.Spine.prototype.createSprite = function (slot, descriptor) { + var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; + var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); + sprite.scale = descriptor.scale; + sprite.rotation = descriptor.rotation; + sprite.anchor.x = sprite.anchor.y = 0.5; + + slot.sprites = slot.sprites || {}; + slot.sprites[descriptor.name] = sprite; + return sprite; +}; /* * Awesome JS run time provided by EsotericSoftware - * + * * https://github.com/EsotericSoftware/spine-runtimes - * + * */ var spine = {}; @@ -7770,7 +7945,7 @@ spine.Slot.prototype = { this.g = data.g; this.b = data.b; this.a = data.a; - + var slotDatas = this.skeleton.data.slots; for (var i = 0, n = slotDatas.length; i < n; i++) { if (slotDatas[i] == data) { @@ -8001,6 +8176,7 @@ spine.TranslateTimeline.prototype = { var frameTime = frames[frameIndex]; var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); + bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; } @@ -8025,14 +8201,12 @@ spine.ScaleTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. - + var bone = skeleton.bones[this.boneIndex]; if (time >= frames[frames.length - 3]) { // Time is after last frame. bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - - return; } @@ -8070,6 +8244,7 @@ spine.ColorTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. + var slot = skeleton.slots[this.slotIndex]; if (time >= frames[frames.length - 5]) { // Time is after last frame. @@ -8119,7 +8294,7 @@ spine.AttachmentTimeline = function (frameCount) { spine.AttachmentTimeline.prototype = { slotIndex: 0, getFrameCount: function () { - return this.frames.length / 2; + return this.frames.length; }, setFrame: function (frameIndex, time, attachmentName) { this.frames[frameIndex] = time; @@ -8136,11 +8311,6 @@ spine.AttachmentTimeline.prototype = { frameIndex = spine.binarySearch(frames, time, 1) - 1; var attachmentName = this.attachmentNames[frameIndex]; - //console.log(skeleton.slots[this.slotIndex]) - - // change the name! - // skeleton.slots[this.slotIndex].attachmentName = attachmentName; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); } }; @@ -8312,11 +8482,9 @@ spine.Skeleton.prototype = { if (slot.data.name == slotName) { var attachment = null; if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; } - slot.setAttachment(attachment); return; } @@ -8398,7 +8566,6 @@ spine.RegionAttachment.prototype = { offset[7/*Y4*/] = localYCos + localX2Sin; }, computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; y += bone.worldY; var m00 = bone.m00; @@ -8422,6 +8589,7 @@ spine.AnimationStateData = function (skeletonData) { this.animationToMixTime = {}; }; spine.AnimationStateData.prototype = { + defaultMix: 0, setMixByName: function (fromName, toName, duration) { var from = this.skeletonData.findAnimation(fromName); if (!from) throw "Animation not found: " + fromName; @@ -8434,7 +8602,7 @@ spine.AnimationStateData.prototype = { }, getMix: function (from, to) { var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : 0; + return time ? time : this.defaultMix; } }; @@ -8474,7 +8642,7 @@ spine.AnimationState.prototype = { this.previous = null; } this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else + } else this.current.apply(skeleton, this.currentTime, this.currentLoop); }, clearAnimation: function () { @@ -8620,16 +8788,9 @@ spine.SkeletonJson.prototype = { name = map["name"] || name; var type = spine.AttachmentType[map["type"] || "region"]; - - // @ekelokorpi - // var attachment = this.attachmentLoader.newAttachment(skin, type, name); - var attachment = new spine.RegionAttachment(); - - // @Doormat23 - // add the name of the attachment - attachment.name = name; - + if (type == spine.AttachmentType.region) { + var attachment = new spine.RegionAttachment(); attachment.x = (map["x"] || 0) * this.scale; attachment.y = (map["y"] || 0) * this.scale; attachment.scaleX = map["scaleX"] || 1; @@ -8638,10 +8799,19 @@ spine.SkeletonJson.prototype = { attachment.width = (map["width"] || 32) * this.scale; attachment.height = (map["height"] || 32) * this.scale; attachment.updateOffset(); + + attachment.rendererObject = {}; + attachment.rendererObject.name = name; + attachment.rendererObject.scale = {}; + attachment.rendererObject.scale.x = attachment.scaleX; + attachment.rendererObject.scale.y = attachment.scaleY; + attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; + return attachment; } - return attachment; + throw "Unknown attachment type: " + type; }, + readAnimation: function (name, map, skeletonData) { var timelines = []; var duration = 0; @@ -8692,7 +8862,7 @@ spine.SkeletonJson.prototype = { } timelines.push(timeline); duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - + } else throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; } @@ -8735,8 +8905,8 @@ spine.SkeletonJson.prototype = { timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); } timelines.push(timeline); - // PIXI FIX - duration = Math.max(duration, timeline.frames[Math.floor(timeline.getFrameCount()) - 1]); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } else throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; } @@ -9005,14 +9175,14 @@ spine.Bone.yDown = true; /** * This object is one that will allow you to specify custom rendering functions based on render type * - * @class CustomRenderable + * @class CustomRenderable * @extends DisplayObject * @constructor */ PIXI.CustomRenderable = function() { PIXI.DisplayObject.call( this ); - + } // constructor @@ -9118,19 +9288,19 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } else { - + var scope = this; this.source.onload = function(){ - + scope.hasLoaded = true; scope.width = scope.source.width; scope.height = scope.source.height; - + // add it to somewhere... PIXI.texturesToUpdate.push(scope); scope.dispatchEvent( { type: 'loaded', content: scope } ); @@ -9143,7 +9313,7 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } @@ -9183,7 +9353,7 @@ PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) { // new Image() breaks tex loading in some versions of Chrome. // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); + var image = new Image();//document.createElement('img'); if (crossorigin) { image.crossOrigin = ''; @@ -9211,7 +9381,7 @@ PIXI.FrameCache = {}; * @uses EventTarget * @constructor * @param baseTexture {BaseTexture} The base texture source to create the texture from - * @param frmae {Rectangle} The rectangle frame of the texture to show + * @param frame {Rectangle} The rectangle frame of the texture to show */ PIXI.Texture = function(baseTexture, frame) { @@ -9256,7 +9426,7 @@ PIXI.Texture = function(baseTexture, frame) { if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); //console.log(frame) - + this.setFrame(frame); } else @@ -9335,13 +9505,13 @@ PIXI.Texture.prototype.setFrame = function(frame) PIXI.Texture.fromImage = function(imageUrl, crossorigin) { var texture = PIXI.TextureCache[imageUrl]; - + if(!texture) { texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); PIXI.TextureCache[imageUrl] = texture; } - + return texture; } @@ -9391,7 +9561,7 @@ PIXI.Texture.addTextureToCache = function(texture, id) } /** - * Remove a texture from the textureCache. + * Remove a texture from the textureCache. * * @static * @method removeTextureFromCache @@ -9503,15 +9673,7 @@ PIXI.RenderTexture.prototype.initWebGL = function() // create a projection matrix.. this.projection = new PIXI.Point(this.width/2 , this.height/2); -/* - this.projectionMatrix = PIXI.mat4.create(); - this.projectionMatrix[5] = 2/this.height// * 0.5; - this.projectionMatrix[13] = -1; - - this.projectionMatrix[0] = 2/this.width; - this.projectionMatrix[12] = -1; -*/ // set the correct render function.. this.render = this.renderWebGL; @@ -9525,10 +9687,6 @@ PIXI.RenderTexture.prototype.resize = function(width, height) this.width = width; this.height = height; - //this.frame.width = this.width - //this.frame.height = this.height; - - if(PIXI.gl) { this.projection.x = this.width/2 @@ -9592,6 +9750,7 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle var children = displayObject.children; //TODO -? create a new one??? dont think so! + var originalWorldTransform = displayObject.worldTransform; displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; // modify to flip... displayObject.worldTransform[4] = -1; @@ -9604,8 +9763,9 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle displayObject.worldTransform[5] -= position.y; } - - + PIXI.visibleCount++; + displayObject.vcount = PIXI.visibleCount; + for(var i=0,j=children.length; i- format + */ +PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) +{ + this.frames = []; + var cols = Math.floor(this.texture.width / frameWidth); + var rows = Math.floor(this.texture.height / frameHeight); + + var i=0; + for (var y=0; y x1 && x < x1 + this.width) + if(x >= x1 && x <= x1 + this.width) { var y1 = this.y; - - if(y > y1 && y < y1 + this.height) + + if(y >= y1 && y <= y1 + this.height) { return true; } @@ -165,7 +165,7 @@ PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; * @class Polygon * @constructor * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, - * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arugments passed can be + * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are * Numbers. @@ -232,9 +232,9 @@ PIXI.Polygon.prototype.contains = function(x, y) return inside; } +// constructor PIXI.Polygon.prototype.constructor = PIXI.Polygon; - /** * @author Chad Engler */ @@ -256,7 +256,7 @@ PIXI.Circle = function(x, y, radius) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number @@ -306,6 +306,7 @@ PIXI.Circle.prototype.contains = function(x, y) return (dx + dy <= r2); } +// constructor PIXI.Circle.prototype.constructor = PIXI.Circle; @@ -320,8 +321,8 @@ PIXI.Circle.prototype.constructor = PIXI.Circle; * @constructor * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse - * @param width {Number} The overall height of this ellipse - * @param height {Number} The overall width of this ellipse + * @param width {Number} The overall width of this ellipse + * @param height {Number} The overall height of this ellipse */ PIXI.Ellipse = function(x, y, width, height) { @@ -331,21 +332,21 @@ PIXI.Ellipse = function(x, y, width, height) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number * @default 0 */ this.y = y || 0; - + /** * @property width * @type Number * @default 0 */ this.width = width || 0; - + /** * @property height * @type Number @@ -394,11 +395,11 @@ PIXI.Ellipse.getBounds = function() return new PIXI.Rectangle(this.x, this.y, this.width, this.height); } +// constructor PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; - /* * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV * you both rock! @@ -426,7 +427,7 @@ PIXI.mat3.create = function() matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -442,7 +443,7 @@ PIXI.mat3.identity = function(matrix) matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -469,35 +470,35 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat3.multiply = function (mat, mat2, dest) +PIXI.mat3.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[0], a01 = mat[1], a02 = mat[2], a10 = mat[3], a11 = mat[4], a12 = mat[5], a20 = mat[6], a21 = mat[7], a22 = mat[8], - + b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; - + dest[0] = b00 * a00 + b01 * a10 + b02 * a20; dest[1] = b00 * a01 + b01 * a11 + b02 * a21; dest[2] = b00 * a02 + b01 * a12 + b02 * a22; - + dest[3] = b10 * a00 + b11 * a10 + b12 * a20; dest[4] = b10 * a01 + b11 * a11 + b12 * a21; dest[5] = b10 * a02 + b11 * a12 + b12 * a22; - + dest[6] = b20 * a00 + b21 * a10 + b22 * a20; dest[7] = b20 * a01 + b21 * a11 + b22 * a21; dest[8] = b20 * a02 + b21 * a12 + b22 * a22; - + return dest; } @@ -514,11 +515,11 @@ PIXI.mat3.clone = function(mat) matrix[6] = mat[6]; matrix[7] = mat[7]; matrix[8] = mat[8]; - + return matrix; } -PIXI.mat3.transpose = function (mat, dest) +PIXI.mat3.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values if (!dest || mat === dest) { @@ -546,30 +547,30 @@ PIXI.mat3.transpose = function (mat, dest) return dest; } -PIXI.mat3.toMat4 = function (mat, dest) +PIXI.mat3.toMat4 = function (mat, dest) { if (!dest) { dest = PIXI.mat4.create(); } - + dest[15] = 1; dest[14] = 0; dest[13] = 0; dest[12] = 0; - + dest[11] = 0; dest[10] = mat[8]; dest[9] = mat[7]; dest[8] = mat[6]; - + dest[7] = 0; dest[6] = mat[5]; dest[5] = mat[4]; dest[4] = mat[3]; - + dest[3] = 0; dest[2] = mat[2]; dest[1] = mat[1]; dest[0] = mat[0]; - + return dest; } @@ -597,19 +598,19 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat4.transpose = function (mat, dest) +PIXI.mat4.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) + if (!dest || mat === dest) { var a01 = mat[1], a02 = mat[2], a03 = mat[3], a12 = mat[6], a13 = mat[7], a23 = mat[11]; - + mat[1] = mat[4]; mat[2] = mat[8]; mat[3] = mat[12]; @@ -624,7 +625,7 @@ PIXI.mat4.transpose = function (mat, dest) mat[14] = a23; return mat; } - + dest[0] = mat[0]; dest[1] = mat[4]; dest[2] = mat[8]; @@ -644,18 +645,18 @@ PIXI.mat4.transpose = function (mat, dest) return dest; } -PIXI.mat4.multiply = function (mat, mat2, dest) +PIXI.mat4.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - + // Cache only the current line of the second matrix - var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; + var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; @@ -705,7 +706,6 @@ PIXI.DisplayObject = function() { this.last = this; this.first = this; - /** * The coordinate of the object relative to the local coordinates of the parent. * @@ -779,15 +779,6 @@ PIXI.DisplayObject = function() */ this.renderable = false; - /** - * [read-only] The visibility of the object based on world (parent) factors. - * - * @property worldVisible - * @type Boolean - * @readOnly - */ - this.worldVisible = false; - /** * [read-only] The display object container that contains this display object. * @@ -806,15 +797,6 @@ PIXI.DisplayObject = function() */ this.stage = null; - /** - * [read-only] The index of this object in the parent's `children` array - * - * @property childIndex - * @type Number - * @readOnly - */ - this.childIndex = 0; - /** * [read-only] The multiplied alpha of the displayobject * @@ -953,17 +935,6 @@ PIXI.DisplayObject = function() // constructor PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObject.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - } -});*/ - /** * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default * Instead of using this function you can now simply set the interactive property to true or false @@ -1011,16 +982,57 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { }, set: function(value) { - this._mask = value; - + if(value) { + if(this._mask) + { + value.start = this._mask.start; + value.end = this._mask.end; + } + else + { + this.addFilter(value); + value.renderable = false; + } + } + else + { + this.removeFilter(this._mask); + this._mask.renderable = true; + } + + this._mask = value; + } +}); + +/** + * Sets the filters for the displayObject. Currently there's a few limitations. + * 1: At the moment only one filter can be applied at a time.. + * 2: They cannot be nested. + * 3: There's no padding yet. + * 4: this is a webGL only feature. + * @property filters + * @type Array + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { + get: function() { + return this._filters; + }, + set: function(value) { + + //if(value == ) + if(value) + { + if(this._filters)this.removeFilter(this._filters); this.addFilter(value) } else { - this.removeFilter(); + if(this._filters)this.removeFilter(this._filters); } + + this._filters = value; } }); @@ -1031,19 +1043,21 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { * @param mask {Graphics} the graphics object to use as a filter * @private */ -PIXI.DisplayObject.prototype.addFilter = function(mask) +PIXI.DisplayObject.prototype.addFilter = function(data) { - if(this.filter)return; - this.filter = true; - + //if(this.filter)return; + //this.filter = true; // insert a filter block.. + // TODO Onject pool thease bad boys.. var start = new PIXI.FilterBlock(); var end = new PIXI.FilterBlock(); + data.start = start; + data.end = end; - start.mask = mask; - end.mask = mask; + start.data = data; + end.data = data; start.first = start.last = this; end.first = end.last = this; @@ -1051,9 +1065,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) start.open = true; /* - * * insert start - * */ var childFirst = start @@ -1084,9 +1096,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) // now insert the end filter block.. /* - * * insert end filter - * */ var childFirst = end var childLast = end @@ -1125,8 +1135,6 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) this.__renderGroup.addFilterBlocks(start, end); } - mask.renderable = false; - } /* @@ -1135,13 +1143,14 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) * @method removeFilter * @private */ -PIXI.DisplayObject.prototype.removeFilter = function() +PIXI.DisplayObject.prototype.removeFilter = function(data) { - if(!this.filter)return; - this.filter = false; - + //if(!this.filter)return; + //this.filter = false; + console.log("YUOIO") // modify the list.. - var startBlock = this.first; + var startBlock = data.start; + var nextObject = startBlock._iNext; var previousObject = startBlock._iPrev; @@ -1151,9 +1160,8 @@ PIXI.DisplayObject.prototype.removeFilter = function() this.first = startBlock._iNext; - // remove the end filter - var lastBlock = this.last; + var lastBlock = data.end; var nextObject = lastBlock._iNext; var previousObject = lastBlock._iPrev; @@ -1162,8 +1170,6 @@ PIXI.DisplayObject.prototype.removeFilter = function() previousObject._iNext = nextObject; // this is always true too! -// if(this.last == lastBlock) - //{ var tempLast = lastBlock._iPrev; // need to make sure the parents last is updated too var updateLast = this; @@ -1174,15 +1180,11 @@ PIXI.DisplayObject.prototype.removeFilter = function() if(!updateLast)break; } - var mask = startBlock.mask - mask.renderable = true; - // if webGL... if(this.__renderGroup) { this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); } - //} } /* @@ -1194,7 +1196,7 @@ PIXI.DisplayObject.prototype.removeFilter = function() PIXI.DisplayObject.prototype.updateTransform = function() { // TODO OPTIMIZE THIS!! with dirty - if(this.rotation != this.rotationCache) + if(this.rotation !== this.rotationCache) { this.rotationCache = this.rotation; this._sr = Math.sin(this.rotation); @@ -1236,9 +1238,12 @@ PIXI.DisplayObject.prototype.updateTransform = function() // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); this.worldAlpha = this.alpha * this.parent.worldAlpha; + + this.vcount = PIXI.visibleCount; } +PIXI.visibleCount = 0; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1270,18 +1275,6 @@ PIXI.DisplayObjectContainer = function() PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObjectContainer.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - - } -});*/ - /** * Adds a child to the container. * @@ -1299,11 +1292,10 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) } child.parent = this; - child.childIndex = this.children.length; this.children.push(child); - // updae the stage refference.. + // update the stage refference.. if(this.stage) { @@ -1326,7 +1318,7 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) var previousObject; // this could be wrong if there is a filter?? - if(this.filter) + if(this._filters) { previousObject = this.last._iPrev; } @@ -1338,7 +1330,6 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) nextObject = previousObject._iNext; // always true in this case - //this.last = child.last; // need to make sure the parents last is updated too var updateLast = this; var prevLast = previousObject; @@ -1402,7 +1393,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) } // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject; var previousObject; @@ -1410,7 +1401,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) if(index == this.children.length) { previousObject = this.last; - var updateLast = this;//.parent; + var updateLast = this; var prevLast = this.last; while(updateLast) { @@ -1539,7 +1530,7 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child) { // unlink // // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject = childLast._iNext; @@ -1609,7 +1600,6 @@ PIXI.DisplayObjectContainer.prototype.updateTransform = function() this.children[i].updateTransform(); } } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1739,9 +1729,18 @@ PIXI.Sprite.prototype.setTexture = function(texture) if(this.texture.baseTexture != texture.baseTexture) { this.textureChange = true; + this.texture = texture; + + if(this.__renderGroup) + { + this.__renderGroup.updateTexture(this); + } + } + else + { + this.texture = texture; } - this.texture = texture; this.updateFrame = true; } @@ -1798,7 +1797,6 @@ PIXI.Sprite.fromImage = function(imageId) return new PIXI.Sprite(texture); } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1814,7 +1812,7 @@ PIXI.Sprite.fromImage = function(imageId) PIXI.MovieClip = function(textures) { PIXI.Sprite.call(this, textures[0]); - + /** * The array of textures that make up the animation * @@ -1822,7 +1820,7 @@ PIXI.MovieClip = function(textures) * @type Array */ this.textures = textures; - + /** * The speed that the MovieClip will play at. Higher is faster, lower is slower * @@ -1848,7 +1846,7 @@ PIXI.MovieClip = function(textures) * @type Function */ this.onComplete = null; - + /** * [read-only] The index MovieClips current frame (this may not have to be a whole number) * @@ -1857,8 +1855,8 @@ PIXI.MovieClip = function(textures) * @default 0 * @readOnly */ - this.currentFrame = 0; - + this.currentFrame = 0; + /** * [read-only] Indicates if the MovieClip is currently playing * @@ -1873,6 +1871,23 @@ PIXI.MovieClip = function(textures) PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; +/** +* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures +* assigned to the MovieClip. +* +* @property totalFrames +* @type Number +* @default 0 +* @readOnly +*/ +Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { + get: function() { + + return this.textures.length; + } +}); + + /** * Stops the MovieClip * @@ -1928,11 +1943,13 @@ PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) PIXI.MovieClip.prototype.updateTransform = function() { PIXI.Sprite.prototype.updateTransform.call(this); - + if(!this.playing)return; - + this.currentFrame += this.animationSpeed; + var round = (this.currentFrame + 0.5) | 0; + if(this.loop || round < this.textures.length) { this.setTexture(this.textures[round % this.textures.length]); @@ -1952,14 +1969,49 @@ PIXI.MovieClip.prototype.updateTransform = function() -PIXI.FilterBlock = function(mask) +PIXI.FilterBlock = function() { - this.graphics = mask this.visible = true; this.renderable = true; } +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.ColorMatrixFilter = function() +{ + // set the uniforms + this.uniforms = { + matrix: {type: 'mat4', value: [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1]}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float invert;", + "uniform mat4 matrix;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", + "gl_FragColor = gl_FragColor * vColor;", + "}" + ]; + +} +Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { + get: function() { + return this.uniforms.matrix.value; + }, + set: function(value) { + this.uniforms.matrix.value = value; + } +}); /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1988,7 +2040,7 @@ PIXI.Text = function(text, style) this.setText(text); this.setStyle(style); - + this.updateText(); this.dirty = false; }; @@ -2030,7 +2082,7 @@ PIXI.Text.prototype.setStyle = function(style) * @methos setText * @param {String} text The copy that you would like the text to display */ -PIXI.Sprite.prototype.setText = function(text) +PIXI.Text.prototype.setText = function(text) { this.text = text.toString() || " "; this.dirty = true; @@ -2045,9 +2097,9 @@ PIXI.Sprite.prototype.setText = function(text) PIXI.Text.prototype.updateText = function() { this.context.font = this.style.font; - + var outputText = this.text; - + // word wrap // preserve original text if(this.style.wordWrap)outputText = this.wordWrap(this.text); @@ -2065,7 +2117,7 @@ PIXI.Text.prototype.updateText = function() maxLineWidth = Math.max(maxLineWidth, lineWidth); } this.canvas.width = maxLineWidth + this.style.strokeThickness; - + //calculate text height var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; this.canvas.height = lineHeight * lines.length; @@ -2073,7 +2125,7 @@ PIXI.Text.prototype.updateText = function() //set canvas text styles this.context.fillStyle = this.style.fill; this.context.font = this.style.font; - + this.context.strokeStyle = this.style.stroke; this.context.lineWidth = this.style.strokeThickness; @@ -2083,7 +2135,7 @@ PIXI.Text.prototype.updateText = function() for (i = 0; i < lines.length; i++) { var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); - + if(this.style.align == "right") { linePosition.x += maxLineWidth - lineWidths[i]; @@ -2103,7 +2155,7 @@ PIXI.Text.prototype.updateText = function() this.context.fillText(lines[i], linePosition.x, linePosition.y); } } - + this.updateTexture(); }; @@ -2119,10 +2171,10 @@ PIXI.Text.prototype.updateTexture = function() this.texture.baseTexture.height = this.canvas.height; this.texture.frame.width = this.canvas.width; this.texture.frame.height = this.canvas.height; - + this._width = this.canvas.width; this._height = this.canvas.height; - + PIXI.texturesToUpdate.push(this.texture.baseTexture); }; @@ -2136,10 +2188,10 @@ PIXI.Text.prototype.updateTransform = function() { if(this.dirty) { - this.updateText(); + this.updateText(); this.dirty = false; } - + PIXI.Sprite.prototype.updateTransform.call(this); }; @@ -2151,12 +2203,12 @@ PIXI.Text.prototype.updateTransform = function() * @param fontStyle {Object} * @private */ -PIXI.Text.prototype.determineFontHeight = function(fontStyle) +PIXI.Text.prototype.determineFontHeight = function(fontStyle) { // build a little reference dictionary so if the font style has been used return a // cached version... var result = PIXI.Text.heightCache[fontStyle]; - + if(!result) { var body = document.getElementsByTagName("body")[0]; @@ -2165,13 +2217,13 @@ PIXI.Text.prototype.determineFontHeight = function(fontStyle) dummy.appendChild(dummyText); dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); body.appendChild(dummy); - + result = dummy.offsetHeight; PIXI.Text.heightCache[fontStyle] = result; - + body.removeChild(dummy); } - + return result; }; @@ -2191,7 +2243,7 @@ PIXI.Text.prototype.wordWrap = function(text) if(p == start) { return 1; } - + if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) { if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) @@ -2208,7 +2260,7 @@ PIXI.Text.prototype.wordWrap = function(text) return arguments.callee(ctx, text, start, p, wrapWidth); } }; - + var lineWrap = function(ctx, text, wrapWidth) { if(ctx.measureText(text).width <= wrapWidth || text.length < 1) @@ -2218,14 +2270,14 @@ PIXI.Text.prototype.wordWrap = function(text) var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); }; - + var result = ""; var lines = text.split("\n"); for (var i = 0; i < lines.length; i++) { result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; } - + return result; }; @@ -2241,7 +2293,7 @@ PIXI.Text.prototype.destroy = function(destroyTexture) { this.texture.destroy(); } - + }; PIXI.Text.heightCache = {}; @@ -2252,7 +2304,7 @@ PIXI.Text.heightCache = {}; /** * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" - * You can generate the fnt files using + * You can generate the fnt files using * http://www.angelcode.com/products/bmfont/ for windows or * http://www.bmglyph.com/ for mac. * @@ -2342,7 +2394,7 @@ PIXI.BitmapText.prototype.updateText = function() prevCharCode = null; continue; } - + var charData = data.chars[charCode]; if(!charData) continue; @@ -2405,7 +2457,7 @@ PIXI.BitmapText.prototype.updateTransform = function() this.dirty = false; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); }; @@ -2414,10 +2466,8 @@ PIXI.BitmapText.fonts = {}; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ - - - -/** + + /** * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive * This manager also supports multitouch. * @@ -2451,6 +2501,8 @@ PIXI.InteractionManager = function(stage) */ this.touchs = {}; + + // helpers this.tempPoint = new PIXI.Point(); //this.tempMatrix = mat3.create(); @@ -2461,7 +2513,19 @@ PIXI.InteractionManager = function(stage) this.pool = []; this.interactiveItems = []; + this.interactionDOMElement = null; + //this will make it so that you dont have to call bind all the time + this.onMouseMove = this.onMouseMove.bind( this ); + this.onMouseDown = this.onMouseDown.bind(this); + this.onMouseOut = this.onMouseOut.bind(this); + this.onMouseUp = this.onMouseUp.bind(this); + + this.onTouchStart = this.onTouchStart.bind(this); + this.onTouchEnd = this.onTouchEnd.bind(this); + this.onTouchMove = this.onTouchMove.bind(this); + + this.last = 0; } @@ -2486,7 +2550,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj { var child = children[i]; - if(child.visible) { +// if(child.visible) { // push all interactive bits if(child.interactive) { @@ -2508,7 +2572,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj this.collectInteractiveSprite(child, iParent); } } - } +// } } } @@ -2521,27 +2585,68 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj */ PIXI.InteractionManager.prototype.setTarget = function(target) { + this.target = target; + + //check if the dom element has been set. If it has don't do anything + if( this.interactionDOMElement === null ) { + + this.setTargetDomElement( target.view ); + } + + document.body.addEventListener('mouseup', this.onMouseUp, true); +} + + +/** + * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM + * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element + * to receive those events + * + * @method setTargetDomElement + * @param domElement {DOMElement} the dom element which will receive mouse and touch events + * @private + */ +PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) +{ + //remove previouse listeners + if( this.interactionDOMElement !== null ) + { + this.interactionDOMElement.style['-ms-content-zooming'] = ''; + this.interactionDOMElement.style['-ms-touch-action'] = ''; + + this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); + this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); + this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); + this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); + this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); + } + + if (window.navigator.msPointerEnabled) { // time to remove some of that zoom in ja.. - target.view.style["-ms-content-zooming"] = "none"; - target.view.style["-ms-touch-action"] = "none" + domElement.style['-ms-content-zooming'] = 'none'; + domElement.style['-ms-touch-action'] = 'none'; // DO some window specific touch! } - - this.target = target; - target.view.addEventListener('mousemove', this.onMouseMove.bind(this), true); - target.view.addEventListener('mousedown', this.onMouseDown.bind(this), true); - document.body.addEventListener('mouseup', this.onMouseUp.bind(this), true); - target.view.addEventListener('mouseout', this.onMouseUp.bind(this), true); - - // aint no multi touch just yet! - target.view.addEventListener("touchstart", this.onTouchStart.bind(this), true); - target.view.addEventListener("touchend", this.onTouchEnd.bind(this), true); - target.view.addEventListener("touchmove", this.onTouchMove.bind(this), true); + + this.interactionDOMElement = domElement; + + domElement.addEventListener('mousemove', this.onMouseMove, true); + domElement.addEventListener('mousedown', this.onMouseDown, true); + domElement.addEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + domElement.addEventListener('touchstart', this.onTouchStart, true); + domElement.addEventListener('touchend', this.onTouchEnd, true); + domElement.addEventListener('touchmove', this.onTouchMove, true); } + /** * updates the state of interactive objects * @@ -2583,12 +2688,14 @@ PIXI.InteractionManager.prototype.update = function() // loop through interactive objects! var length = this.interactiveItems.length; - this.target.view.style.cursor = "default"; + this.interactionDOMElement.style.cursor = "default"; for (var i = 0; i < length; i++) { var item = this.interactiveItems[i]; - if(!item.visible)continue; + + + //if(!item.visible)continue; // OPTIMISATION - only calculate every time if the mousemove function exists.. // OK so.. does the object have any other interactive functions? @@ -2604,7 +2711,7 @@ PIXI.InteractionManager.prototype.update = function() // loks like there was a hit! if(item.__hit) { - if(item.buttonMode)this.target.view.style.cursor = "pointer"; + if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; if(!item.__isOver) { @@ -2639,7 +2746,7 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) { this.mouse.originalEvent = event || window.event; //IE uses window.event // TODO optimize by not check EVERY TIME! maybe half as often? // - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); @@ -2669,7 +2776,6 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) */ PIXI.InteractionManager.prototype.onMouseDown = function(event) { - event.preventDefault(); this.mouse.originalEvent = event || window.event; //IE uses window.event // loop through inteaction tree... @@ -2706,6 +2812,26 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) } } + +PIXI.InteractionManager.prototype.onMouseOut = function(event) +{ + var length = this.interactiveItems.length; + + this.interactionDOMElement.style.cursor = "default"; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.__isOver) + { + this.mouse.target = item; + if(item.mouseout)item.mouseout(this.mouse); + item.__isOver = false; + } + } +} + /** * Is called when the mouse button is released on the renderer element * @@ -2770,7 +2896,7 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) { var global = interactionData.global; - if(!item.visible)return false; + if(item.vcount !== PIXI.visibleCount)return false; var isSprite = (item instanceof PIXI.Sprite), worldTransform = item.worldTransform, @@ -2840,14 +2966,14 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) */ PIXI.InteractionManager.prototype.onTouchMove = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) { var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; + touchData.originalEvent = event || window.event; // update the touch position touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); @@ -2871,10 +2997,7 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) */ PIXI.InteractionManager.prototype.onTouchStart = function(event) { - event.preventDefault(); - this.mouse.originalEvent = event || window.event; //IE uses window.event - - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2884,6 +3007,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) var touchData = this.pool.pop(); if(!touchData)touchData = new PIXI.InteractionData(); + touchData.originalEvent = event || window.event; + this.touchs[touchEvent.identifier] = touchData; touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); @@ -2921,8 +3046,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) */ PIXI.InteractionManager.prototype.onTouchEnd = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + //this.mouse.originalEvent = event || window.event; //IE uses window.event + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2943,7 +3068,7 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) if(itemTouchData == touchData) { // so this one WAS down... - + touchData.originalEvent = event || window.event; // hitTest?? if(item.touchend || item.tap) @@ -3055,9 +3180,8 @@ PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; * @constructor * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format * like: 0xFFFFFF for white - * @param interactive {Boolean} enable / disable interaction (default is false) */ -PIXI.Stage = function(backgroundColor, interactive) +PIXI.Stage = function(backgroundColor) { PIXI.DisplayObjectContainer.call( this ); @@ -3077,7 +3201,7 @@ PIXI.Stage = function(backgroundColor, interactive) * @property interactive * @type Boolean */ - this.interactive = interactive; + this.interactive = true; /** * The interaction manage for this stage, manages all interactive activity on the stage @@ -3113,6 +3237,18 @@ PIXI.Stage = function(backgroundColor, interactive) PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); PIXI.Stage.prototype.constructor = PIXI.Stage; +/** + * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. + * This is useful for when you have other DOM elements ontop of the Canvas element. + * + * @method setInteractionDelegate + * @param domElement {DOMElement} This new domElement which will receive mouse/touch events + */ +PIXI.Stage.prototype.setInteractionDelegate = function(domElement) +{ + this.interactionManager.setTargetDomElement( domElement ); +} + /* * Updates the object transform for rendering * @@ -3122,6 +3258,7 @@ PIXI.Stage.prototype.constructor = PIXI.Stage; PIXI.Stage.prototype.updateTransform = function() { this.worldAlpha = 1; + this.vcount = PIXI.visibleCount; for(var i=0,j=this.children.length; i 100) { console.log("BREAK") break } - } + } } @@ -3361,14 +3466,14 @@ PIXI.runList = function(item) PIXI.EventTarget = function () { var listeners = {}; - + this.addEventListener = this.on = function ( type, listener ) { - - + + if ( listeners[ type ] === undefined ) { listeners[ type ] = []; - + } if ( listeners[ type ].indexOf( listener ) === - 1 ) { @@ -3379,11 +3484,17 @@ PIXI.EventTarget = function () { }; this.dispatchEvent = this.emit = function ( event ) { - - for ( var listener in listeners[ event.type ] ) { - listeners[ event.type ][ listener ]( event ); - + if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { + + return; + + } + + for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { + + listeners[ event.type ][ i ]( event ); + } }; @@ -3417,8 +3528,11 @@ PIXI.EventTarget = function () { * @param height {Number} the height of the renderers view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) + * + * antialias */ -PIXI.autoDetectRenderer = function(width, height, view, transparent) +PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) { if(!width)width = 800; if(!height)height = 600; @@ -3429,7 +3543,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) //console.log(webgl); if( webgl ) { - return new PIXI.WebGLRenderer(width, height, view, transparent); + return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); } return new PIXI.CanvasRenderer(width, height, view, transparent); @@ -3441,7 +3555,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) PolyK library url: http://polyk.ivank.net Released under MIT licence. - + Copyright (c) 2012 Ivan Kuckir Permission is hereby granted, free of charge, to any person @@ -3465,8 +3579,8 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - This is an amazing lib! - + This is an amazing lib! + slightly modified by mat groves (matgroves.com); */ @@ -3482,13 +3596,13 @@ PIXI.PolyK = {}; PIXI.PolyK.Triangulate = function(p) { var sign = true; - + var n = p.length>>1; if(n<3) return []; var tgs = []; var avl = []; for(var i=0; i 3) @@ -3496,11 +3610,11 @@ PIXI.PolyK.Triangulate = function(p) var i0 = avl[(i+0)%al]; var i1 = avl[(i+1)%al]; var i2 = avl[(i+2)%al]; - + var ax = p[2*i0], ay = p[2*i0+1]; var bx = p[2*i1], by = p[2*i1+1]; var cx = p[2*i2], cy = p[2*i2+1]; - + var earFound = false; if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) { @@ -3519,7 +3633,7 @@ PIXI.PolyK.Triangulate = function(p) al--; i = 0; } - else if(i++ > 3*al) + else if(i++ > 3*al) { // need to flip flip reverse it! // reset! @@ -3528,17 +3642,17 @@ PIXI.PolyK.Triangulate = function(p) var tgs = []; avl = []; for(var i=0; i= 0) == sign; } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -3612,13 +3725,11 @@ PIXI.shaderVertexSrc = [ "attribute vec2 aVertexPosition;", "attribute vec2 aTextureCoord;", "attribute float aColor;", - //"uniform mat4 uMVMatrix;", "uniform vec2 projectionVector;", "varying vec2 vTextureCoord;", "varying float vColor;", "void main(void) {", - // "gl_Position = uMVMatrix * vec4(aVertexPosition, 1.0, 1.0);", "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", "vTextureCoord = aTextureCoord;", "vColor = aColor;", @@ -3658,7 +3769,6 @@ PIXI.stripShaderVertexSrc = [ "}" ]; - /* * primitive shader.. */ @@ -3685,6 +3795,8 @@ PIXI.primitiveShaderVertexSrc = [ "}" ]; +PIXI.shaderStack = []; + PIXI.initPrimitiveShader = function() { var gl = PIXI.gl; @@ -3699,27 +3811,26 @@ PIXI.initPrimitiveShader = function() shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); + + //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(shaderProgram.colorAttribute); +//gl.enableVertexAttribArray(program.textureCoordAttribute); + shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); PIXI.primitiveProgram = shaderProgram; + + } PIXI.initDefaultShader = function() { - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.shaderVertexSrc, PIXI.shaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - // shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.shaderProgram = shaderProgram; + PIXI.defaultShader = new PIXI.PixiShader(); + PIXI.defaultShader.init(); + PIXI.activateShader(PIXI.defaultShader); + /* + PIXI.shaderStack.push(PIXI.defaultShader); + PIXI.current*/ } PIXI.initDefaultStripShader = function() @@ -3736,9 +3847,7 @@ PIXI.initDefaultStripShader = function() shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); PIXI.stripShaderProgram = shaderProgram; @@ -3789,35 +3898,135 @@ PIXI.compileProgram = function(vertexSrc, fragmentSrc) return shaderProgram; } +PIXI.activateShader = function(shader) +{ + PIXI.shaderStack.push(shader); + + //console.log(">>>") + var gl = PIXI.gl; + + var shaderProgram = shader.program; + + // map uniforms.. + gl.useProgram(shaderProgram); + + gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + gl.enableVertexAttribArray(shaderProgram.colorAttribute); + gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); -PIXI.activateDefaultShader = function() + shader.syncUniforms(); + + PIXI.currentShader = shaderProgram; +} + + +PIXI.popShader = function() { var gl = PIXI.gl; - var shaderProgram = PIXI.shaderProgram; + // activate last program.. + var lastProgram = PIXI.shaderStack.pop(); + + var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); + PIXI.currentShader = shaderProgram; } - - PIXI.activatePrimitiveShader = function() { var gl = PIXI.gl; - gl.disableVertexAttribArray(PIXI.shaderProgram.textureCoordAttribute); - gl.disableVertexAttribArray(PIXI.shaderProgram.colorAttribute); - gl.useProgram(PIXI.primitiveProgram); - gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); + gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + + //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); } +PIXI.deactivatePrimitiveShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.currentShader); + + gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.PixiShader = function() +{ + // the webGL program.. + this.program; + + this.fragmentSrc = [ + "precision lowp float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", + "}" + ]; + +} + +PIXI.PixiShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get the default shader bits! + program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); + program.colorAttribute = gl.getAttribLocation(program, "aColor"); + program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); + + program.projectionVector = gl.getUniformLocation(program, "projectionVector"); + program.samplerUniform = gl.getUniformLocation(program, "uSampler"); + + // add those custom shaders! + for (var key in this.uniforms) + { + // get the uniform locations.. + program[key] = gl.getUniformLocation(program, key); + } + + this.program = program; +} + +PIXI.PixiShader.prototype.syncUniforms = function() +{ + var gl = PIXI.gl; + + for (var key in this.uniforms) + { + //var + var type = this.uniforms[key].type; + + // need to grow this! + if(type == "f") + { + gl.uniform1f(this.program[key], this.uniforms[key].value); + } + else if(type == "mat4") + { + gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); + } + } + +} + /** * @author Mat Groves http://matgroves.com/ @Doormat23 @@ -3887,7 +4096,7 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); // WHY DOES THIS LINE NEED TO BE THERE??? - gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // its not even used.. but need to be set or it breaks? // only on pc though.. @@ -3899,8 +4108,10 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); + PIXI.deactivatePrimitiveShader(); + // return to default shader... - PIXI.activateDefaultShader(); +// PIXI.activateShader(PIXI.defaultShader); } /** @@ -4243,7 +4454,7 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) verts.push(px , py); verts.push(r, g, b, alpha); - verts.push(p2x - (px-p2x), p2y - (py - p2y));//, 4); + verts.push(p2x - (px-p2x), p2y - (py - p2y)); verts.push(r, g, b, alpha); } } @@ -4356,9 +4567,10 @@ PIXI.gl; * @param height=0 {Number} the height of the canvas view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) * */ -PIXI.WebGLRenderer = function(width, height, view, transparent) +PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) { // do a catch.. only 1 webGL renderer.. @@ -4382,7 +4594,7 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) { PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { alpha: this.transparent, - antialias:true, // SPEED UP?? + antialias:!!antialias, // SPEED UP?? premultipliedAlpha:false, stencil:true }); @@ -4392,11 +4604,12 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); } - PIXI.initPrimitiveShader(); PIXI.initDefaultShader(); + PIXI.initPrimitiveShader(); PIXI.initDefaultStripShader(); - PIXI.activateDefaultShader(); + +// PIXI.activateDefaultShader(); var gl = this.gl; PIXI.WebGLRenderer.gl = gl; @@ -4413,7 +4626,10 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) this.resize(this.width, this.height); this.contextLost = false; + PIXI.activateShader(PIXI.defaultShader); + this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); + } // constructor @@ -4469,8 +4685,6 @@ PIXI.WebGLRenderer.prototype.render = function(stage) { // TODO make this work // dont think this is needed any more? - //if(this.__stage)this.checkVisibility(this.__stage, false) - this.__stage = stage; this.stageRenderGroup.setRenderable(stage); } @@ -4487,10 +4701,8 @@ PIXI.WebGLRenderer.prototype.render = function(stage) // update any textures PIXI.WebGLRenderer.updateTextures(); - // recursivly loop through all items! - //this.checkVisibility(stage, true); - // update the scene graph + PIXI.visibleCount++; stage.updateTransform(); var gl = this.gl; @@ -4499,16 +4711,12 @@ PIXI.WebGLRenderer.prototype.render = function(stage) gl.colorMask(true, true, true, this.transparent); gl.viewport(0, 0, this.width, this.height); - // set the correct matrix.. - // gl.uniformMatrix4fv(this.shaderProgram.mvMatrixUniform, false, this.projectionMatrix); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); gl.clear(gl.COLOR_BUFFER_BIT); // HACK TO TEST - //PIXI.projectionMatrix = this.projectionMatrix; this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; this.stageRenderGroup.render(PIXI.projection); @@ -4546,8 +4754,9 @@ PIXI.WebGLRenderer.prototype.render = function(stage) */ PIXI.WebGLRenderer.updateTextures = function() { - for (var i=0; i < PIXI.texturesToUpdate.length; i++) this.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) this.destroyTexture(PIXI.texturesToDestroy[i]); + //TODO break this out into a texture manager... + for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); + for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; } @@ -4562,6 +4771,7 @@ PIXI.WebGLRenderer.updateTextures = function() */ PIXI.WebGLRenderer.updateTexture = function(texture) { + //TODO break this out into a texture manager... var gl = PIXI.gl; if(!texture._glTexture) @@ -4602,9 +4812,10 @@ PIXI.WebGLRenderer.updateTexture = function(texture) * @param texture {Texture} The texture to update * @private */ -PIXI.WebGLRenderer.prototype.destroyTexture = function(texture) +PIXI.WebGLRenderer.destroyTexture = function(texture) { - var gl = this.gl; + //TODO break this out into a texture manager... + var gl = PIXI.gl; if(texture._glTexture) { @@ -4768,7 +4979,6 @@ PIXI.WebGLBatch.prototype.clean = function() this.uvs = []; this.indices = []; this.colors = []; - //this.sprites = []; this.dynamicSize = 1; this.texture = null; this.last = null; @@ -4805,7 +5015,6 @@ PIXI.WebGLBatch.prototype.init = function(sprite) this.dirty = true; this.blendMode = sprite.blendMode; this.texture = sprite.texture.baseTexture; -// this.sprites.push(sprite); this.head = sprite; this.tail = sprite; this.size = 1; @@ -4838,7 +5047,6 @@ PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) else { this.head = sprite; - //this.head.__prev = null } } @@ -4926,7 +5134,7 @@ PIXI.WebGLBatch.prototype.split = function(sprite) { this.dirty = true; - var batch = new PIXI.WebGLBatch(this.gl);//PIXI._getBatch(this.gl); + var batch = new PIXI.WebGLBatch(this.gl); batch.init(sprite); batch.texture = this.texture; batch.tail = this.tail; @@ -4936,8 +5144,6 @@ PIXI.WebGLBatch.prototype.split = function(sprite) sprite.__prev = null; // return a splite batch! - //sprite.__prev.__next = null; - //sprite.__prev = null; // TODO this size is wrong! // need to recalculate :/ problem with a linked list! @@ -5007,13 +5213,13 @@ PIXI.WebGLBatch.prototype.growBatch = function() gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); - this.uvs = new Float32Array( this.dynamicSize * 8 ) + this.uvs = new Float32Array( this.dynamicSize * 8 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); this.dirtyUVS = true; - this.colors = new Float32Array( this.dynamicSize * 4 ) + this.colors = new Float32Array( this.dynamicSize * 4 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); @@ -5112,7 +5318,7 @@ PIXI.WebGLBatch.prototype.update = function() while(displayObject) { - if(displayObject.worldVisible) + if(displayObject.vcount === PIXI.visibleCount) { width = displayObject.texture.frame.width; height = displayObject.texture.frame.height; @@ -5214,7 +5420,7 @@ PIXI.WebGLBatch.prototype.update = function() PIXI.WebGLBatch.prototype.render = function(start, end) { start = start || 0; - //end = end || this.size; + if(end == undefined)end = this.size; if(this.dirty) @@ -5230,8 +5436,9 @@ PIXI.WebGLBatch.prototype.render = function(start, end) //TODO optimize this! - var shaderProgram = PIXI.shaderProgram; - gl.useProgram(shaderProgram); + var shaderProgram = PIXI.currentShader; + + //gl.useProgram(shaderProgram); // update the verts.. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); @@ -5239,6 +5446,8 @@ PIXI.WebGLBatch.prototype.render = function(start, end) gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // update the uvs + var isDefault = (shaderProgram == PIXI.shaderProgram) + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); if(this.dirtyUVS) @@ -5262,13 +5471,11 @@ PIXI.WebGLBatch.prototype.render = function(start, end) } gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - //var startIndex = 0//1; var len = end - start; - // console.log(this.size) + // DRAW THAT this! gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); } @@ -5336,77 +5543,45 @@ PIXI.WebGLRenderGroup.prototype.render = function(projection) PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - // TODO remove this by replacing visible with getter setters.. - this.checkVisibility(this.root, this.root.visible); - // will render all the elements in the group var renderable; - - for (var i=0; i < this.batchs.length; i++) { + renderable = this.batchs[i]; if(renderable instanceof PIXI.WebGLBatch) { this.batchs[i].render(); + continue; } - else if(renderable instanceof PIXI.TilingSprite) + + // non sprite batch.. + var worldVisible = renderable.vcount === PIXI.visibleCount; + + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ - if(renderable.open) - { - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - gl.colorMask(true, true, true, false); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - else - { - gl.disable(gl.STENCIL_TEST); - } + this.handleFilterBlock(renderable, projection); } } } -/** - * Renders the stage to its webgl view - * - * @method handleFilter - * @param filter {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.handleFilter = function(filter, projection) -{ - -} - /** * Renders a specific displayObject * @@ -5420,11 +5595,8 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - this.checkVisibility(displayObject, displayObject.visible); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); -// gl.uniformMatrix4fv(PIXI.shaderProgram.mvMatrixUniform, false, projectionMatrix); - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); - // to do! // render part of the scene... @@ -5483,7 +5655,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project while(lastItem.children.length > 0) { lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem; + if(lastItem.renderable)lastRenderable = lastItem.last; } if(lastRenderable instanceof PIXI.Sprite) @@ -5577,45 +5749,80 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project */ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) { + var sta = PIXI.shaderStack.length; + + var worldVisible = renderable.vcount === PIXI.visibleCount + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.CustomRenderable) { - if(renderable.visible) renderable.renderWebGL(this, projection); + if(worldVisible) renderable.renderWebGL(this, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ + this.handleFilterBlock(renderable, projection); + } +} - var gl = PIXI.gl; +PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) +{ + /* + * for now only masks are supported.. + */ + var gl = PIXI.gl; - if(renderable.open) + if(renderable.open) + { + if(renderable.data instanceof Array) + { + var filter = renderable.data[0]; + + if(!filter.shader) + { + var shader = new PIXI.PixiShader(); + + shader.fragmentSrc = filter.fragmentSrc; + shader.uniforms = filter.uniforms; + shader.init(); + + filter.shader = shader + } + + PIXI.activateShader(filter.shader); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } + else { gl.enable(gl.STENCIL_TEST); gl.colorMask(false, false, false, false); gl.stencilFunc(gl.ALWAYS,1,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - // we know this is a render texture so enable alpha too.. + PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); + gl.colorMask(true, true, true, true); gl.stencilFunc(gl.NOTEQUAL,0,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); } + } + else + { + if(renderable.data instanceof Array) + { + PIXI.popShader(); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } else { gl.disable(gl.STENCIL_TEST); @@ -5623,42 +5830,6 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) } } -/** - * Checks the visibility of a displayObject - * - * @method checkVisibility - * @param displayObject {DisplayObject} - * @param globalVisible {Boolean} - * @private - */ -PIXI.WebGLRenderGroup.prototype.checkVisibility = function(displayObject, globalVisible) -{ - // give the dp a reference to its renderGroup... - var children = displayObject.children; - //displayObject.worldVisible = globalVisible; - for (var i=0; i < children.length; i++) - { - var child = children[i]; - - // TODO optimize... should'nt need to loop through everything all the time - child.worldVisible = child.visible && globalVisible; - - // everything should have a batch! - // time to see whats new! - if(child.textureChange) - { - child.textureChange = false; - if(child.worldVisible)this.updateTexture(child); - // update texture!! - } - - if(child.children.length > 0) - { - this.checkVisibility(child, child.worldVisible); - } - }; -} - /** * Updates a webgl texture * @@ -5719,7 +5890,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * It keeps going back until it finds a sprite or the stage */ var previousRenderable = start; - while(previousRenderable != this.root) + while(previousRenderable != this.root.first) { previousRenderable = previousRenderable._iPrev; if(previousRenderable.renderable && previousRenderable.__renderGroup)break; @@ -5733,7 +5904,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * scene graph */ var previousRenderable2 = end; - while(previousRenderable2 != this.root) + while(previousRenderable2 != this.root.first) { previousRenderable2 = previousRenderable2._iPrev; if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; @@ -6105,6 +6276,7 @@ PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) } } + /** * Initializes a tiling sprite * @@ -6175,23 +6347,19 @@ PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) { var gl = this.gl; - var shaderProgram = PIXI.shaderProgram; -// mat - //var mat4Real = PIXI.mat3.toMat4(strip.worldTransform); - //PIXI.mat4.transpose(mat4Real); - //PIXI.mat4.multiply(projectionMatrix, mat4Real, mat4Real ) - + var shaderProgram = PIXI.stripShaderProgram; - gl.useProgram(PIXI.stripShaderProgram); + + gl.useProgram(shaderProgram); var m = PIXI.mat3.clone(strip.worldTransform); PIXI.mat3.transpose(m); // set the matrix transform for the - gl.uniformMatrix3fv(PIXI.stripShaderProgram.translationMatrix, false, m); - gl.uniform2f(PIXI.stripShaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(PIXI.stripShaderProgram.alpha, strip.worldAlpha); + gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); + gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); /* if(strip.blendMode == PIXI.blendModes.NORMAL) @@ -6249,11 +6417,10 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } - //console.log(gl.TRIANGLE_STRIP); gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - gl.useProgram(PIXI.shaderProgram); + gl.useProgram(PIXI.currentProgram); } /** @@ -6328,6 +6495,7 @@ PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } + /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -6401,7 +6569,6 @@ PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; */ PIXI.CanvasRenderer.prototype.render = function(stage) { - // update children if need be //stage.__childrenAdded = []; //stage.__childrenRemoved = []; @@ -6410,6 +6577,7 @@ PIXI.CanvasRenderer.prototype.render = function(stage) PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; + PIXI.visibleCount++; stage.updateTransform(); // update the background color @@ -6496,7 +6664,7 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) var frame = displayObject.texture.frame; - if(frame) + if(frame && frame.width && frame.height) { context.globalAlpha = displayObject.worldAlpha; @@ -6534,31 +6702,34 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) } else if(displayObject instanceof PIXI.FilterBlock) { - if(displayObject.open) + if(PIXI.FilterBlock.data instanceof PIXI.Graphics) { - context.save(); - - var cacheAlpha = displayObject.mask.alpha; - var maskTransform = displayObject.mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - displayObject.mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); - // context.fillStyle = 0xFF0000; - // context.fillRect(0, 0, 200, 200); - context.clip(); - - displayObject.mask.worldAlpha = cacheAlpha; - //context.globalCompositeOperation = 'lighter'; + if(displayObject.open) + { + context.save(); + + var cacheAlpha = displayObject.mask.alpha; + var maskTransform = displayObject.mask.worldTransform; + + context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) + + displayObject.mask.worldAlpha = 0.5; + + context.worldAlpha = 0; + + PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); + context.clip(); + + displayObject.mask.worldAlpha = cacheAlpha; + } + else + { + context.restore(); + } } else { - //context.globalCompositeOperation = 'source-over'; - context.restore(); + // only masks supported right now! } } // count++ @@ -6651,7 +6822,7 @@ PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) PIXI.CanvasRenderer.prototype.renderStrip = function(strip) { var context = this.context; - //context.globalCompositeOperation = 'lighter'; + // draw triangles!! var verticies = strip.verticies; var uvs = strip.uvs; @@ -6678,8 +6849,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.lineTo(x2, y2); context.closePath(); - // context.fillStyle = "white"//rgb(1, 1, 1,1)); - // context.fill(); context.clip(); @@ -6703,7 +6872,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.restore(); }; -// context.globalCompositeOperation = 'source-over'; } /** @@ -6718,7 +6886,7 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) */ PIXI.CanvasGraphics = function() { - + } @@ -6734,35 +6902,33 @@ PIXI.CanvasGraphics = function() PIXI.CanvasGraphics.renderGraphics = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - - for (var i=0; i < graphics.graphicsData.length; i++) + + for (var i=0; i < graphics.graphicsData.length; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); context.lineWidth = data.lineWidth; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); - + context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6777,21 +6943,20 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.RECT) { - - // TODO - need to be Undefined! - if(data.fillColor) + + if(data.fillColor || data.fillColor === 0) { context.globalAlpha = data.fillAlpha * worldAlpha; context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); context.fillRect(points[0], points[1], points[2], points[3]); - + } if(data.lineWidth) { context.globalAlpha = data.lineAlpha * worldAlpha; context.strokeRect(points[0], points[1], points[2], points[3]); } - + } else if(data.type == PIXI.Graphics.CIRC) { @@ -6799,7 +6964,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.beginPath(); context.arc(points[0], points[1], points[2],0,2*Math.PI); context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6814,19 +6979,19 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - + var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6834,15 +6999,15 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - + context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6855,7 +7020,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.stroke(); } } - + }; } @@ -6871,37 +7036,35 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - + var len = graphics.graphicsData.length; if(len > 1) { len = 1; console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") } - - for (var i=0; i < 1; i++) + + for (var i=0; i < 1; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + } else if(data.type == PIXI.Graphics.RECT) { @@ -6918,18 +7081,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6937,7 +7100,7 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); @@ -6945,8 +7108,8 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); context.closePath(); } - - + + }; } @@ -6956,18 +7119,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) /** - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. + * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. * It is important to know that with the webGL renderer only simple polys can be filled at this stage * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png * - * @class Graphics + * @class Graphics * @extends DisplayObjectContainer * @constructor */ PIXI.Graphics = function() { PIXI.DisplayObjectContainer.call( this ); - + this.renderable = true; /** @@ -7028,14 +7191,14 @@ PIXI.Graphics.prototype.constructor = PIXI.Graphics; PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - + this.lineWidth = lineWidth || 0; this.lineColor = color || 0; this.lineAlpha = (alpha == undefined) ? 1 : alpha; - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.graphicsData.push(this.currentPath); } @@ -7049,12 +7212,12 @@ PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) PIXI.Graphics.prototype.moveTo = function(x, y) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.currentPath.points.push(x, y); - + this.graphicsData.push(this.currentPath); } @@ -7084,7 +7247,7 @@ PIXI.Graphics.prototype.beginFill = function(color, alpha) { this.filling = true; this.fillColor = color || 0; - this.fillAlpha = alpha || 1; + this.fillAlpha = (alpha == undefined) ? 1 : alpha; } /** @@ -7110,11 +7273,11 @@ PIXI.Graphics.prototype.endFill = function() PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.RECT}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7130,11 +7293,11 @@ PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) PIXI.Graphics.prototype.drawCircle = function( x, y, radius) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7151,11 +7314,11 @@ PIXI.Graphics.prototype.drawCircle = function( x, y, radius) PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.ELIP}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7169,7 +7332,7 @@ PIXI.Graphics.prototype.clear = function() { this.lineWidth = 0; this.filling = false; - + this.dirty = true; this.clearDirty = true; this.graphicsData = []; @@ -7190,20 +7353,20 @@ PIXI.Strip = function(texture, width, height) PIXI.DisplayObjectContainer.call( this ); this.texture = texture; this.blendMode = PIXI.blendModes.NORMAL; - + try { this.uvs = new Float32Array([0, 1, 1, 1, 1, 0, 0,1]); - + this.verticies = new Float32Array([0, 0, 0,0, 0,0, 0, 0, 0]); - + this.colors = new Float32Array([1, 1, 1, 1]); - + this.indices = new Uint16Array([0, 1, 2, 3]); } catch(error) @@ -7211,18 +7374,18 @@ PIXI.Strip = function(texture, width, height) this.uvs = [0, 1, 1, 1, 1, 0, 0,1]; - + this.verticies = [0, 0, 0,0, 0,0, 0, 0, 0]; - + this.colors = [1, 1, 1, 1]; - + this.indices = [0, 1, 2, 3]; } - - + + /* this.uvs = new Float32Array() this.verticies = new Float32Array() @@ -7231,7 +7394,7 @@ PIXI.Strip = function(texture, width, height) */ this.width = width; this.height = height; - + // load the texture! if(texture.baseTexture.hasLoaded) { @@ -7244,7 +7407,7 @@ PIXI.Strip = function(texture, width, height) this.onTextureUpdateBind = this.onTextureUpdate.bind(this); this.texture.addEventListener( 'update', this.onTextureUpdateBind ); } - + this.renderable = true; } @@ -7256,8 +7419,8 @@ PIXI.Strip.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.width = texture.frame.width; this.height = texture.frame.height; @@ -7280,7 +7443,7 @@ PIXI.Rope = function(texture, points) { PIXI.Strip.call( this, texture ); this.points = points; - + try { this.verticies = new Float32Array( points.length * 4); @@ -7291,12 +7454,12 @@ PIXI.Rope = function(texture, points) catch(error) { this.verticies = verticies - + this.uvs = uvs this.colors = colors this.indices = indices } - + this.refresh(); } @@ -7309,99 +7472,99 @@ PIXI.Rope.prototype.refresh = function() { var points = this.points; if(points.length < 1)return; - + var uvs = this.uvs var indices = this.indices; var colors = this.colors; - + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - + + uvs[0] = 0 uvs[1] = 1 uvs[2] = 0 uvs[3] = 1 - + colors[0] = 1; colors[1] = 1; - + indices[0] = 0; indices[1] = 1; - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; // time to do some smart drawing! var 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; } } PIXI.Rope.prototype.updateTransform = function() { - + var points = this.points; if(points.length < 1)return; - - var verticies = this.verticies - + + var verticies = this.verticies + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - verticies[0] = point.x + perp.x + + verticies[0] = point.x + perp.x verticies[1] = point.y + perp.y //+ 200 - verticies[2] = point.x - perp.x + verticies[2] = point.x - perp.x verticies[3] = point.y - perp.y//+200 // time to do some smart drawing! - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; - + if(i < points.length-1) { nextPoint = points[i+1]; @@ -7410,35 +7573,35 @@ PIXI.Rope.prototype.updateTransform = function() { nextPoint = point } - + perp.y = -(nextPoint.x - lastPoint.x); perp.x = nextPoint.y - lastPoint.y; - + var ratio = (1 - (i / (total-1))) * 10; if(ratio > 1)ratio = 1; - + var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); var 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; - - verticies[index] = point.x + perp.x + + verticies[index] = point.x + perp.x verticies[index+1] = point.y + perp.y - verticies[index+2] = point.x - perp.x + verticies[index+2] = point.x - perp.x verticies[index+3] = point.y - perp.y lastPoint = point; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); } PIXI.Rope.prototype.setTexture = function(texture) { - // stop current texture + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7494,7 +7657,7 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tileScale * @type Point - */ + */ this.tileScale = new PIXI.Point(1,1); /** @@ -7502,11 +7665,11 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tilePosition * @type Point - */ + */ this.tilePosition = new PIXI.Point(0,0); this.renderable = true; - + this.blendMode = PIXI.blendModes.NORMAL } @@ -7524,8 +7687,8 @@ PIXI.TilingSprite.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7546,10 +7709,10 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) /** * @author Mat Groves http://matgroves.com/ @Doormat23 * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * + * * Awesome JS run time provided by EsotericSoftware * https://github.com/EsotericSoftware/spine-runtimes - * + * */ /** @@ -7562,48 +7725,41 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) * @constructor * @param url {String} The url of the spine anim file to be used */ -PIXI.Spine = function(url) -{ +PIXI.Spine = function (url) { PIXI.DisplayObjectContainer.call(this); - + this.spineData = PIXI.AnimCache[url]; - - if(!this.spineData) - { + + if (!this.spineData) { throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: " + url); - return; } - - this.count = 0; - - this.sprites = []; - + this.skeleton = new spine.Skeleton(this.spineData); this.skeleton.updateWorldTransform(); - this.stateData = new spine.AnimationStateData(this.spineData); + this.stateData = new spine.AnimationStateData(this.spineData); this.state = new spine.AnimationState(this.stateData); - - // add the sprites.. - for (var i = 0; i < this.skeleton.drawOrder.length; i++) { - - var attachmentName = this.skeleton.drawOrder[i].data.attachmentName; - - // kind of an assumtion here. that its a png - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; - } - - - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(attachmentName)); - sprite.anchor.x = sprite.anchor.y = 0.5; - this.addChild(sprite); - this.sprites.push(sprite); - }; -} -PIXI.Spine.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); + 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)) { + continue; + } + var spriteName = attachment.rendererObject.name; + var sprite = this.createSprite(slot, attachment.rendererObject); + slot.currentSprite = sprite; + slot.currentSpriteName = spriteName; + slotContainer.addChild(sprite); + } +}; + +PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); PIXI.Spine.prototype.constructor = PIXI.Spine; /* @@ -7612,55 +7768,74 @@ PIXI.Spine.prototype.constructor = PIXI.Spine; * @method updateTransform * @private */ -PIXI.Spine.prototype.updateTransform = function() -{ - // TODO should make this time based really.. - this.state.update(1/60); +PIXI.Spine.prototype.updateTransform = function () { + this.lastTime = this.lastTime || Date.now(); + var timeDelta = (Date.now() - this.lastTime) * 0.001; + this.lastTime = Date.now(); + this.state.update(timeDelta); this.state.apply(this.skeleton); this.skeleton.updateWorldTransform(); - - for (var i = 0; i < this.skeleton.drawOrder.length; i++) - { - var slot = this.skeleton.drawOrder[i]; + 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 instanceof spine.RegionAttachment)) { + slotContainer.visible = false; + continue; + } - var x = slot.bone.worldX + slot.attachment.x * slot.bone.m00 + slot.attachment.y * slot.bone.m01 + slot.attachment.width * 0.5; - var y = slot.bone.worldY + slot.attachment.x * slot.bone.m10 + slot.attachment.y * slot.bone.m11 + slot.attachment.height * 0.5; - //console.log(x + ' : ' + y); - - - //console.log(slot.attachment.name) - if(slot.cacheName != slot.attachment.name) - { - var attachmentName = slot.attachment.name; - - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; + if (attachment.rendererObject) { + if (!slot.currentSpriteName || slot.currentSpriteName != attachment.name) { + var spriteName = attachment.rendererObject.name; + if (slot.currentSprite !== undefined) { + slot.currentSprite.visible = false; } - - this.sprites[i].setTexture(PIXI.TextureCache[attachmentName]); - - slot.cacheName = slot.attachment.name; + slot.sprites = slot.sprites || {}; + if (slot.sprites[spriteName] !== undefined) { + slot.sprites[spriteName].visible = true; + } else { + var sprite = this.createSprite(slot, attachment.rendererObject); + slotContainer.addChild(sprite); + } + slot.currentSprite = slot.sprites[spriteName]; + slot.currentSpriteName = spriteName; } - - x += -((slot.attachment.width * (slot.bone.worldScaleX + slot.attachment.scaleX - 1))>>1); - y += -((slot.attachment.height * (slot.bone.worldScaleY + slot.attachment.scaleY - 1))>>1); - - - this.sprites[i].position.x = x; - this.sprites[i].position.y = y; - this.sprites[i].rotation = (-(slot.bone.worldRotation + slot.attachment.rotation)) * (Math.PI/180); - } - + } + slotContainer.visible = true; + + 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 * Math.PI / 180); + } + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -} +}; + + +PIXI.Spine.prototype.createSprite = function (slot, descriptor) { + var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; + var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); + sprite.scale = descriptor.scale; + sprite.rotation = descriptor.rotation; + sprite.anchor.x = sprite.anchor.y = 0.5; + + slot.sprites = slot.sprites || {}; + slot.sprites[descriptor.name] = sprite; + return sprite; +}; /* * Awesome JS run time provided by EsotericSoftware - * + * * https://github.com/EsotericSoftware/spine-runtimes - * + * */ var spine = {}; @@ -7770,7 +7945,7 @@ spine.Slot.prototype = { this.g = data.g; this.b = data.b; this.a = data.a; - + var slotDatas = this.skeleton.data.slots; for (var i = 0, n = slotDatas.length; i < n; i++) { if (slotDatas[i] == data) { @@ -8001,6 +8176,7 @@ spine.TranslateTimeline.prototype = { var frameTime = frames[frameIndex]; var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); + bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; } @@ -8025,14 +8201,12 @@ spine.ScaleTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. - + var bone = skeleton.bones[this.boneIndex]; if (time >= frames[frames.length - 3]) { // Time is after last frame. bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - - return; } @@ -8070,6 +8244,7 @@ spine.ColorTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. + var slot = skeleton.slots[this.slotIndex]; if (time >= frames[frames.length - 5]) { // Time is after last frame. @@ -8119,7 +8294,7 @@ spine.AttachmentTimeline = function (frameCount) { spine.AttachmentTimeline.prototype = { slotIndex: 0, getFrameCount: function () { - return this.frames.length / 2; + return this.frames.length; }, setFrame: function (frameIndex, time, attachmentName) { this.frames[frameIndex] = time; @@ -8136,11 +8311,6 @@ spine.AttachmentTimeline.prototype = { frameIndex = spine.binarySearch(frames, time, 1) - 1; var attachmentName = this.attachmentNames[frameIndex]; - //console.log(skeleton.slots[this.slotIndex]) - - // change the name! - // skeleton.slots[this.slotIndex].attachmentName = attachmentName; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); } }; @@ -8312,11 +8482,9 @@ spine.Skeleton.prototype = { if (slot.data.name == slotName) { var attachment = null; if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; } - slot.setAttachment(attachment); return; } @@ -8398,7 +8566,6 @@ spine.RegionAttachment.prototype = { offset[7/*Y4*/] = localYCos + localX2Sin; }, computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; y += bone.worldY; var m00 = bone.m00; @@ -8422,6 +8589,7 @@ spine.AnimationStateData = function (skeletonData) { this.animationToMixTime = {}; }; spine.AnimationStateData.prototype = { + defaultMix: 0, setMixByName: function (fromName, toName, duration) { var from = this.skeletonData.findAnimation(fromName); if (!from) throw "Animation not found: " + fromName; @@ -8434,7 +8602,7 @@ spine.AnimationStateData.prototype = { }, getMix: function (from, to) { var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : 0; + return time ? time : this.defaultMix; } }; @@ -8474,7 +8642,7 @@ spine.AnimationState.prototype = { this.previous = null; } this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else + } else this.current.apply(skeleton, this.currentTime, this.currentLoop); }, clearAnimation: function () { @@ -8620,16 +8788,9 @@ spine.SkeletonJson.prototype = { name = map["name"] || name; var type = spine.AttachmentType[map["type"] || "region"]; - - // @ekelokorpi - // var attachment = this.attachmentLoader.newAttachment(skin, type, name); - var attachment = new spine.RegionAttachment(); - - // @Doormat23 - // add the name of the attachment - attachment.name = name; - + if (type == spine.AttachmentType.region) { + var attachment = new spine.RegionAttachment(); attachment.x = (map["x"] || 0) * this.scale; attachment.y = (map["y"] || 0) * this.scale; attachment.scaleX = map["scaleX"] || 1; @@ -8638,10 +8799,19 @@ spine.SkeletonJson.prototype = { attachment.width = (map["width"] || 32) * this.scale; attachment.height = (map["height"] || 32) * this.scale; attachment.updateOffset(); + + attachment.rendererObject = {}; + attachment.rendererObject.name = name; + attachment.rendererObject.scale = {}; + attachment.rendererObject.scale.x = attachment.scaleX; + attachment.rendererObject.scale.y = attachment.scaleY; + attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; + return attachment; } - return attachment; + throw "Unknown attachment type: " + type; }, + readAnimation: function (name, map, skeletonData) { var timelines = []; var duration = 0; @@ -8692,7 +8862,7 @@ spine.SkeletonJson.prototype = { } timelines.push(timeline); duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - + } else throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; } @@ -8735,8 +8905,8 @@ spine.SkeletonJson.prototype = { timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); } timelines.push(timeline); - // PIXI FIX - duration = Math.max(duration, timeline.frames[Math.floor(timeline.getFrameCount()) - 1]); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } else throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; } @@ -9005,14 +9175,14 @@ spine.Bone.yDown = true; /** * This object is one that will allow you to specify custom rendering functions based on render type * - * @class CustomRenderable + * @class CustomRenderable * @extends DisplayObject * @constructor */ PIXI.CustomRenderable = function() { PIXI.DisplayObject.call( this ); - + } // constructor @@ -9118,19 +9288,19 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } else { - + var scope = this; this.source.onload = function(){ - + scope.hasLoaded = true; scope.width = scope.source.width; scope.height = scope.source.height; - + // add it to somewhere... PIXI.texturesToUpdate.push(scope); scope.dispatchEvent( { type: 'loaded', content: scope } ); @@ -9143,7 +9313,7 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } @@ -9183,7 +9353,7 @@ PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) { // new Image() breaks tex loading in some versions of Chrome. // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); + var image = new Image();//document.createElement('img'); if (crossorigin) { image.crossOrigin = ''; @@ -9211,7 +9381,7 @@ PIXI.FrameCache = {}; * @uses EventTarget * @constructor * @param baseTexture {BaseTexture} The base texture source to create the texture from - * @param frmae {Rectangle} The rectangle frame of the texture to show + * @param frame {Rectangle} The rectangle frame of the texture to show */ PIXI.Texture = function(baseTexture, frame) { @@ -9256,7 +9426,7 @@ PIXI.Texture = function(baseTexture, frame) { if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); //console.log(frame) - + this.setFrame(frame); } else @@ -9335,13 +9505,13 @@ PIXI.Texture.prototype.setFrame = function(frame) PIXI.Texture.fromImage = function(imageUrl, crossorigin) { var texture = PIXI.TextureCache[imageUrl]; - + if(!texture) { texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); PIXI.TextureCache[imageUrl] = texture; } - + return texture; } @@ -9391,7 +9561,7 @@ PIXI.Texture.addTextureToCache = function(texture, id) } /** - * Remove a texture from the textureCache. + * Remove a texture from the textureCache. * * @static * @method removeTextureFromCache @@ -9503,15 +9673,7 @@ PIXI.RenderTexture.prototype.initWebGL = function() // create a projection matrix.. this.projection = new PIXI.Point(this.width/2 , this.height/2); -/* - this.projectionMatrix = PIXI.mat4.create(); - this.projectionMatrix[5] = 2/this.height// * 0.5; - this.projectionMatrix[13] = -1; - - this.projectionMatrix[0] = 2/this.width; - this.projectionMatrix[12] = -1; -*/ // set the correct render function.. this.render = this.renderWebGL; @@ -9525,10 +9687,6 @@ PIXI.RenderTexture.prototype.resize = function(width, height) this.width = width; this.height = height; - //this.frame.width = this.width - //this.frame.height = this.height; - - if(PIXI.gl) { this.projection.x = this.width/2 @@ -9592,6 +9750,7 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle var children = displayObject.children; //TODO -? create a new one??? dont think so! + var originalWorldTransform = displayObject.worldTransform; displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; // modify to flip... displayObject.worldTransform[4] = -1; @@ -9604,8 +9763,9 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle displayObject.worldTransform[5] -= position.y; } - - + PIXI.visibleCount++; + displayObject.vcount = PIXI.visibleCount; + for(var i=0,j=children.length; i- format + */ +PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) +{ + this.frames = []; + var cols = Math.floor(this.texture.width / frameWidth); + var rows = Math.floor(this.texture.height / frameHeight); + + var i=0; + for (var y=0; y x1 && x < x1 + this.width) + if(x >= x1 && x <= x1 + this.width) { var y1 = this.y; - - if(y > y1 && y < y1 + this.height) + + if(y >= y1 && y <= y1 + this.height) { return true; } @@ -165,7 +165,7 @@ PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; * @class Polygon * @constructor * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, - * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arugments passed can be + * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are * Numbers. @@ -232,9 +232,9 @@ PIXI.Polygon.prototype.contains = function(x, y) return inside; } +// constructor PIXI.Polygon.prototype.constructor = PIXI.Polygon; - /** * @author Chad Engler */ @@ -256,7 +256,7 @@ PIXI.Circle = function(x, y, radius) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number @@ -306,6 +306,7 @@ PIXI.Circle.prototype.contains = function(x, y) return (dx + dy <= r2); } +// constructor PIXI.Circle.prototype.constructor = PIXI.Circle; @@ -320,8 +321,8 @@ PIXI.Circle.prototype.constructor = PIXI.Circle; * @constructor * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse - * @param width {Number} The overall height of this ellipse - * @param height {Number} The overall width of this ellipse + * @param width {Number} The overall width of this ellipse + * @param height {Number} The overall height of this ellipse */ PIXI.Ellipse = function(x, y, width, height) { @@ -331,21 +332,21 @@ PIXI.Ellipse = function(x, y, width, height) * @default 0 */ this.x = x || 0; - + /** * @property y * @type Number * @default 0 */ this.y = y || 0; - + /** * @property width * @type Number * @default 0 */ this.width = width || 0; - + /** * @property height * @type Number @@ -394,11 +395,11 @@ PIXI.Ellipse.getBounds = function() return new PIXI.Rectangle(this.x, this.y, this.width, this.height); } +// constructor PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; - /* * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV * you both rock! @@ -426,7 +427,7 @@ PIXI.mat3.create = function() matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -442,7 +443,7 @@ PIXI.mat3.identity = function(matrix) matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; - + return matrix; } @@ -469,35 +470,35 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat3.multiply = function (mat, mat2, dest) +PIXI.mat3.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[0], a01 = mat[1], a02 = mat[2], a10 = mat[3], a11 = mat[4], a12 = mat[5], a20 = mat[6], a21 = mat[7], a22 = mat[8], - + b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; - + dest[0] = b00 * a00 + b01 * a10 + b02 * a20; dest[1] = b00 * a01 + b01 * a11 + b02 * a21; dest[2] = b00 * a02 + b01 * a12 + b02 * a22; - + dest[3] = b10 * a00 + b11 * a10 + b12 * a20; dest[4] = b10 * a01 + b11 * a11 + b12 * a21; dest[5] = b10 * a02 + b11 * a12 + b12 * a22; - + dest[6] = b20 * a00 + b21 * a10 + b22 * a20; dest[7] = b20 * a01 + b21 * a11 + b22 * a21; dest[8] = b20 * a02 + b21 * a12 + b22 * a22; - + return dest; } @@ -514,11 +515,11 @@ PIXI.mat3.clone = function(mat) matrix[6] = mat[6]; matrix[7] = mat[7]; matrix[8] = mat[8]; - + return matrix; } -PIXI.mat3.transpose = function (mat, dest) +PIXI.mat3.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values if (!dest || mat === dest) { @@ -546,30 +547,30 @@ PIXI.mat3.transpose = function (mat, dest) return dest; } -PIXI.mat3.toMat4 = function (mat, dest) +PIXI.mat3.toMat4 = function (mat, dest) { if (!dest) { dest = PIXI.mat4.create(); } - + dest[15] = 1; dest[14] = 0; dest[13] = 0; dest[12] = 0; - + dest[11] = 0; dest[10] = mat[8]; dest[9] = mat[7]; dest[8] = mat[6]; - + dest[7] = 0; dest[6] = mat[5]; dest[5] = mat[4]; dest[4] = mat[3]; - + dest[3] = 0; dest[2] = mat[2]; dest[1] = mat[1]; dest[0] = mat[0]; - + return dest; } @@ -597,19 +598,19 @@ PIXI.mat4.create = function() matrix[13] = 0; matrix[14] = 0; matrix[15] = 1; - + return matrix; } -PIXI.mat4.transpose = function (mat, dest) +PIXI.mat4.transpose = function (mat, dest) { // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) + if (!dest || mat === dest) { var a01 = mat[1], a02 = mat[2], a03 = mat[3], a12 = mat[6], a13 = mat[7], a23 = mat[11]; - + mat[1] = mat[4]; mat[2] = mat[8]; mat[3] = mat[12]; @@ -624,7 +625,7 @@ PIXI.mat4.transpose = function (mat, dest) mat[14] = a23; return mat; } - + dest[0] = mat[0]; dest[1] = mat[4]; dest[2] = mat[8]; @@ -644,18 +645,18 @@ PIXI.mat4.transpose = function (mat, dest) return dest; } -PIXI.mat4.multiply = function (mat, mat2, dest) +PIXI.mat4.multiply = function (mat, mat2, dest) { if (!dest) { dest = mat; } - + // Cache the matrix values (makes for huge speed increases!) var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - + // Cache only the current line of the second matrix - var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; + var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; @@ -705,7 +706,6 @@ PIXI.DisplayObject = function() { this.last = this; this.first = this; - /** * The coordinate of the object relative to the local coordinates of the parent. * @@ -779,15 +779,6 @@ PIXI.DisplayObject = function() */ this.renderable = false; - /** - * [read-only] The visibility of the object based on world (parent) factors. - * - * @property worldVisible - * @type Boolean - * @readOnly - */ - this.worldVisible = false; - /** * [read-only] The display object container that contains this display object. * @@ -806,15 +797,6 @@ PIXI.DisplayObject = function() */ this.stage = null; - /** - * [read-only] The index of this object in the parent's `children` array - * - * @property childIndex - * @type Number - * @readOnly - */ - this.childIndex = 0; - /** * [read-only] The multiplied alpha of the displayobject * @@ -953,17 +935,6 @@ PIXI.DisplayObject = function() // constructor PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObject.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - } -});*/ - /** * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default * Instead of using this function you can now simply set the interactive property to true or false @@ -1011,16 +982,57 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { }, set: function(value) { - this._mask = value; - + if(value) { + if(this._mask) + { + value.start = this._mask.start; + value.end = this._mask.end; + } + else + { + this.addFilter(value); + value.renderable = false; + } + } + else + { + this.removeFilter(this._mask); + this._mask.renderable = true; + } + + this._mask = value; + } +}); + +/** + * Sets the filters for the displayObject. Currently there's a few limitations. + * 1: At the moment only one filter can be applied at a time.. + * 2: They cannot be nested. + * 3: There's no padding yet. + * 4: this is a webGL only feature. + * @property filters + * @type Array + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { + get: function() { + return this._filters; + }, + set: function(value) { + + //if(value == ) + if(value) + { + if(this._filters)this.removeFilter(this._filters); this.addFilter(value) } else { - this.removeFilter(); + if(this._filters)this.removeFilter(this._filters); } + + this._filters = value; } }); @@ -1031,19 +1043,21 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { * @param mask {Graphics} the graphics object to use as a filter * @private */ -PIXI.DisplayObject.prototype.addFilter = function(mask) +PIXI.DisplayObject.prototype.addFilter = function(data) { - if(this.filter)return; - this.filter = true; - + //if(this.filter)return; + //this.filter = true; // insert a filter block.. + // TODO Onject pool thease bad boys.. var start = new PIXI.FilterBlock(); var end = new PIXI.FilterBlock(); + data.start = start; + data.end = end; - start.mask = mask; - end.mask = mask; + start.data = data; + end.data = data; start.first = start.last = this; end.first = end.last = this; @@ -1051,9 +1065,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) start.open = true; /* - * * insert start - * */ var childFirst = start @@ -1084,9 +1096,7 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) // now insert the end filter block.. /* - * * insert end filter - * */ var childFirst = end var childLast = end @@ -1125,8 +1135,6 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) this.__renderGroup.addFilterBlocks(start, end); } - mask.renderable = false; - } /* @@ -1135,13 +1143,14 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) * @method removeFilter * @private */ -PIXI.DisplayObject.prototype.removeFilter = function() +PIXI.DisplayObject.prototype.removeFilter = function(data) { - if(!this.filter)return; - this.filter = false; - + //if(!this.filter)return; + //this.filter = false; + console.log("YUOIO") // modify the list.. - var startBlock = this.first; + var startBlock = data.start; + var nextObject = startBlock._iNext; var previousObject = startBlock._iPrev; @@ -1151,9 +1160,8 @@ PIXI.DisplayObject.prototype.removeFilter = function() this.first = startBlock._iNext; - // remove the end filter - var lastBlock = this.last; + var lastBlock = data.end; var nextObject = lastBlock._iNext; var previousObject = lastBlock._iPrev; @@ -1162,8 +1170,6 @@ PIXI.DisplayObject.prototype.removeFilter = function() previousObject._iNext = nextObject; // this is always true too! -// if(this.last == lastBlock) - //{ var tempLast = lastBlock._iPrev; // need to make sure the parents last is updated too var updateLast = this; @@ -1174,15 +1180,11 @@ PIXI.DisplayObject.prototype.removeFilter = function() if(!updateLast)break; } - var mask = startBlock.mask - mask.renderable = true; - // if webGL... if(this.__renderGroup) { this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); } - //} } /* @@ -1194,7 +1196,7 @@ PIXI.DisplayObject.prototype.removeFilter = function() PIXI.DisplayObject.prototype.updateTransform = function() { // TODO OPTIMIZE THIS!! with dirty - if(this.rotation != this.rotationCache) + if(this.rotation !== this.rotationCache) { this.rotationCache = this.rotation; this._sr = Math.sin(this.rotation); @@ -1236,9 +1238,12 @@ PIXI.DisplayObject.prototype.updateTransform = function() // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); this.worldAlpha = this.alpha * this.parent.worldAlpha; + + this.vcount = PIXI.visibleCount; } +PIXI.visibleCount = 0; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1270,18 +1275,6 @@ PIXI.DisplayObjectContainer = function() PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObjectContainer.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - - } -});*/ - /** * Adds a child to the container. * @@ -1299,11 +1292,10 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) } child.parent = this; - child.childIndex = this.children.length; this.children.push(child); - // updae the stage refference.. + // update the stage refference.. if(this.stage) { @@ -1326,7 +1318,7 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) var previousObject; // this could be wrong if there is a filter?? - if(this.filter) + if(this._filters) { previousObject = this.last._iPrev; } @@ -1338,7 +1330,6 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) nextObject = previousObject._iNext; // always true in this case - //this.last = child.last; // need to make sure the parents last is updated too var updateLast = this; var prevLast = previousObject; @@ -1402,7 +1393,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) } // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject; var previousObject; @@ -1410,7 +1401,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) if(index == this.children.length) { previousObject = this.last; - var updateLast = this;//.parent; + var updateLast = this; var prevLast = this.last; while(updateLast) { @@ -1539,7 +1530,7 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child) { // unlink // // modify the list.. - var childFirst = child.first + var childFirst = child.first; var childLast = child.last; var nextObject = childLast._iNext; @@ -1609,7 +1600,6 @@ PIXI.DisplayObjectContainer.prototype.updateTransform = function() this.children[i].updateTransform(); } } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1739,9 +1729,18 @@ PIXI.Sprite.prototype.setTexture = function(texture) if(this.texture.baseTexture != texture.baseTexture) { this.textureChange = true; + this.texture = texture; + + if(this.__renderGroup) + { + this.__renderGroup.updateTexture(this); + } + } + else + { + this.texture = texture; } - this.texture = texture; this.updateFrame = true; } @@ -1798,7 +1797,6 @@ PIXI.Sprite.fromImage = function(imageId) return new PIXI.Sprite(texture); } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1814,7 +1812,7 @@ PIXI.Sprite.fromImage = function(imageId) PIXI.MovieClip = function(textures) { PIXI.Sprite.call(this, textures[0]); - + /** * The array of textures that make up the animation * @@ -1822,7 +1820,7 @@ PIXI.MovieClip = function(textures) * @type Array */ this.textures = textures; - + /** * The speed that the MovieClip will play at. Higher is faster, lower is slower * @@ -1848,7 +1846,7 @@ PIXI.MovieClip = function(textures) * @type Function */ this.onComplete = null; - + /** * [read-only] The index MovieClips current frame (this may not have to be a whole number) * @@ -1857,8 +1855,8 @@ PIXI.MovieClip = function(textures) * @default 0 * @readOnly */ - this.currentFrame = 0; - + this.currentFrame = 0; + /** * [read-only] Indicates if the MovieClip is currently playing * @@ -1873,6 +1871,23 @@ PIXI.MovieClip = function(textures) PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; +/** +* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures +* assigned to the MovieClip. +* +* @property totalFrames +* @type Number +* @default 0 +* @readOnly +*/ +Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { + get: function() { + + return this.textures.length; + } +}); + + /** * Stops the MovieClip * @@ -1928,11 +1943,13 @@ PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) PIXI.MovieClip.prototype.updateTransform = function() { PIXI.Sprite.prototype.updateTransform.call(this); - + if(!this.playing)return; - + this.currentFrame += this.animationSpeed; + var round = (this.currentFrame + 0.5) | 0; + if(this.loop || round < this.textures.length) { this.setTexture(this.textures[round % this.textures.length]); @@ -1952,14 +1969,49 @@ PIXI.MovieClip.prototype.updateTransform = function() -PIXI.FilterBlock = function(mask) +PIXI.FilterBlock = function() { - this.graphics = mask this.visible = true; this.renderable = true; } +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.ColorMatrixFilter = function() +{ + // set the uniforms + this.uniforms = { + matrix: {type: 'mat4', value: [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1]}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float invert;", + "uniform mat4 matrix;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", + "gl_FragColor = gl_FragColor * vColor;", + "}" + ]; + +} +Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { + get: function() { + return this.uniforms.matrix.value; + }, + set: function(value) { + this.uniforms.matrix.value = value; + } +}); /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -1988,7 +2040,7 @@ PIXI.Text = function(text, style) this.setText(text); this.setStyle(style); - + this.updateText(); this.dirty = false; }; @@ -2030,7 +2082,7 @@ PIXI.Text.prototype.setStyle = function(style) * @methos setText * @param {String} text The copy that you would like the text to display */ -PIXI.Sprite.prototype.setText = function(text) +PIXI.Text.prototype.setText = function(text) { this.text = text.toString() || " "; this.dirty = true; @@ -2045,9 +2097,9 @@ PIXI.Sprite.prototype.setText = function(text) PIXI.Text.prototype.updateText = function() { this.context.font = this.style.font; - + var outputText = this.text; - + // word wrap // preserve original text if(this.style.wordWrap)outputText = this.wordWrap(this.text); @@ -2065,7 +2117,7 @@ PIXI.Text.prototype.updateText = function() maxLineWidth = Math.max(maxLineWidth, lineWidth); } this.canvas.width = maxLineWidth + this.style.strokeThickness; - + //calculate text height var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; this.canvas.height = lineHeight * lines.length; @@ -2073,7 +2125,7 @@ PIXI.Text.prototype.updateText = function() //set canvas text styles this.context.fillStyle = this.style.fill; this.context.font = this.style.font; - + this.context.strokeStyle = this.style.stroke; this.context.lineWidth = this.style.strokeThickness; @@ -2083,7 +2135,7 @@ PIXI.Text.prototype.updateText = function() for (i = 0; i < lines.length; i++) { var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); - + if(this.style.align == "right") { linePosition.x += maxLineWidth - lineWidths[i]; @@ -2103,7 +2155,7 @@ PIXI.Text.prototype.updateText = function() this.context.fillText(lines[i], linePosition.x, linePosition.y); } } - + this.updateTexture(); }; @@ -2119,10 +2171,10 @@ PIXI.Text.prototype.updateTexture = function() this.texture.baseTexture.height = this.canvas.height; this.texture.frame.width = this.canvas.width; this.texture.frame.height = this.canvas.height; - + this._width = this.canvas.width; this._height = this.canvas.height; - + PIXI.texturesToUpdate.push(this.texture.baseTexture); }; @@ -2136,10 +2188,10 @@ PIXI.Text.prototype.updateTransform = function() { if(this.dirty) { - this.updateText(); + this.updateText(); this.dirty = false; } - + PIXI.Sprite.prototype.updateTransform.call(this); }; @@ -2151,12 +2203,12 @@ PIXI.Text.prototype.updateTransform = function() * @param fontStyle {Object} * @private */ -PIXI.Text.prototype.determineFontHeight = function(fontStyle) +PIXI.Text.prototype.determineFontHeight = function(fontStyle) { // build a little reference dictionary so if the font style has been used return a // cached version... var result = PIXI.Text.heightCache[fontStyle]; - + if(!result) { var body = document.getElementsByTagName("body")[0]; @@ -2165,13 +2217,13 @@ PIXI.Text.prototype.determineFontHeight = function(fontStyle) dummy.appendChild(dummyText); dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); body.appendChild(dummy); - + result = dummy.offsetHeight; PIXI.Text.heightCache[fontStyle] = result; - + body.removeChild(dummy); } - + return result; }; @@ -2191,7 +2243,7 @@ PIXI.Text.prototype.wordWrap = function(text) if(p == start) { return 1; } - + if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) { if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) @@ -2208,7 +2260,7 @@ PIXI.Text.prototype.wordWrap = function(text) return arguments.callee(ctx, text, start, p, wrapWidth); } }; - + var lineWrap = function(ctx, text, wrapWidth) { if(ctx.measureText(text).width <= wrapWidth || text.length < 1) @@ -2218,14 +2270,14 @@ PIXI.Text.prototype.wordWrap = function(text) var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); }; - + var result = ""; var lines = text.split("\n"); for (var i = 0; i < lines.length; i++) { result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; } - + return result; }; @@ -2241,7 +2293,7 @@ PIXI.Text.prototype.destroy = function(destroyTexture) { this.texture.destroy(); } - + }; PIXI.Text.heightCache = {}; @@ -2252,7 +2304,7 @@ PIXI.Text.heightCache = {}; /** * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" - * You can generate the fnt files using + * You can generate the fnt files using * http://www.angelcode.com/products/bmfont/ for windows or * http://www.bmglyph.com/ for mac. * @@ -2342,7 +2394,7 @@ PIXI.BitmapText.prototype.updateText = function() prevCharCode = null; continue; } - + var charData = data.chars[charCode]; if(!charData) continue; @@ -2405,7 +2457,7 @@ PIXI.BitmapText.prototype.updateTransform = function() this.dirty = false; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); }; @@ -2414,10 +2466,8 @@ PIXI.BitmapText.fonts = {}; /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ - - - -/** + + /** * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive * This manager also supports multitouch. * @@ -2451,6 +2501,8 @@ PIXI.InteractionManager = function(stage) */ this.touchs = {}; + + // helpers this.tempPoint = new PIXI.Point(); //this.tempMatrix = mat3.create(); @@ -2461,7 +2513,19 @@ PIXI.InteractionManager = function(stage) this.pool = []; this.interactiveItems = []; + this.interactionDOMElement = null; + //this will make it so that you dont have to call bind all the time + this.onMouseMove = this.onMouseMove.bind( this ); + this.onMouseDown = this.onMouseDown.bind(this); + this.onMouseOut = this.onMouseOut.bind(this); + this.onMouseUp = this.onMouseUp.bind(this); + + this.onTouchStart = this.onTouchStart.bind(this); + this.onTouchEnd = this.onTouchEnd.bind(this); + this.onTouchMove = this.onTouchMove.bind(this); + + this.last = 0; } @@ -2486,7 +2550,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj { var child = children[i]; - if(child.visible) { +// if(child.visible) { // push all interactive bits if(child.interactive) { @@ -2508,7 +2572,7 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj this.collectInteractiveSprite(child, iParent); } } - } +// } } } @@ -2521,27 +2585,68 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj */ PIXI.InteractionManager.prototype.setTarget = function(target) { + this.target = target; + + //check if the dom element has been set. If it has don't do anything + if( this.interactionDOMElement === null ) { + + this.setTargetDomElement( target.view ); + } + + document.body.addEventListener('mouseup', this.onMouseUp, true); +} + + +/** + * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM + * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element + * to receive those events + * + * @method setTargetDomElement + * @param domElement {DOMElement} the dom element which will receive mouse and touch events + * @private + */ +PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) +{ + //remove previouse listeners + if( this.interactionDOMElement !== null ) + { + this.interactionDOMElement.style['-ms-content-zooming'] = ''; + this.interactionDOMElement.style['-ms-touch-action'] = ''; + + this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); + this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); + this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); + this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); + this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); + } + + if (window.navigator.msPointerEnabled) { // time to remove some of that zoom in ja.. - target.view.style["-ms-content-zooming"] = "none"; - target.view.style["-ms-touch-action"] = "none" + domElement.style['-ms-content-zooming'] = 'none'; + domElement.style['-ms-touch-action'] = 'none'; // DO some window specific touch! } - - this.target = target; - target.view.addEventListener('mousemove', this.onMouseMove.bind(this), true); - target.view.addEventListener('mousedown', this.onMouseDown.bind(this), true); - document.body.addEventListener('mouseup', this.onMouseUp.bind(this), true); - target.view.addEventListener('mouseout', this.onMouseUp.bind(this), true); - - // aint no multi touch just yet! - target.view.addEventListener("touchstart", this.onTouchStart.bind(this), true); - target.view.addEventListener("touchend", this.onTouchEnd.bind(this), true); - target.view.addEventListener("touchmove", this.onTouchMove.bind(this), true); + + this.interactionDOMElement = domElement; + + domElement.addEventListener('mousemove', this.onMouseMove, true); + domElement.addEventListener('mousedown', this.onMouseDown, true); + domElement.addEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + domElement.addEventListener('touchstart', this.onTouchStart, true); + domElement.addEventListener('touchend', this.onTouchEnd, true); + domElement.addEventListener('touchmove', this.onTouchMove, true); } + /** * updates the state of interactive objects * @@ -2583,12 +2688,14 @@ PIXI.InteractionManager.prototype.update = function() // loop through interactive objects! var length = this.interactiveItems.length; - this.target.view.style.cursor = "default"; + this.interactionDOMElement.style.cursor = "default"; for (var i = 0; i < length; i++) { var item = this.interactiveItems[i]; - if(!item.visible)continue; + + + //if(!item.visible)continue; // OPTIMISATION - only calculate every time if the mousemove function exists.. // OK so.. does the object have any other interactive functions? @@ -2604,7 +2711,7 @@ PIXI.InteractionManager.prototype.update = function() // loks like there was a hit! if(item.__hit) { - if(item.buttonMode)this.target.view.style.cursor = "pointer"; + if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; if(!item.__isOver) { @@ -2639,7 +2746,7 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) { this.mouse.originalEvent = event || window.event; //IE uses window.event // TODO optimize by not check EVERY TIME! maybe half as often? // - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); @@ -2669,7 +2776,6 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) */ PIXI.InteractionManager.prototype.onMouseDown = function(event) { - event.preventDefault(); this.mouse.originalEvent = event || window.event; //IE uses window.event // loop through inteaction tree... @@ -2706,6 +2812,26 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) } } + +PIXI.InteractionManager.prototype.onMouseOut = function(event) +{ + var length = this.interactiveItems.length; + + this.interactionDOMElement.style.cursor = "default"; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.__isOver) + { + this.mouse.target = item; + if(item.mouseout)item.mouseout(this.mouse); + item.__isOver = false; + } + } +} + /** * Is called when the mouse button is released on the renderer element * @@ -2770,7 +2896,7 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) { var global = interactionData.global; - if(!item.visible)return false; + if(item.vcount !== PIXI.visibleCount)return false; var isSprite = (item instanceof PIXI.Sprite), worldTransform = item.worldTransform, @@ -2840,14 +2966,14 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) */ PIXI.InteractionManager.prototype.onTouchMove = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) { var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; + touchData.originalEvent = event || window.event; // update the touch position touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); @@ -2871,10 +2997,7 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) */ PIXI.InteractionManager.prototype.onTouchStart = function(event) { - event.preventDefault(); - this.mouse.originalEvent = event || window.event; //IE uses window.event - - var rect = this.target.view.getBoundingClientRect(); + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2884,6 +3007,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) var touchData = this.pool.pop(); if(!touchData)touchData = new PIXI.InteractionData(); + touchData.originalEvent = event || window.event; + this.touchs[touchEvent.identifier] = touchData; touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); @@ -2921,8 +3046,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event) */ PIXI.InteractionManager.prototype.onTouchEnd = function(event) { - this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.target.view.getBoundingClientRect(); + //this.mouse.originalEvent = event || window.event; //IE uses window.event + var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; for (var i=0; i < changedTouches.length; i++) @@ -2943,7 +3068,7 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) if(itemTouchData == touchData) { // so this one WAS down... - + touchData.originalEvent = event || window.event; // hitTest?? if(item.touchend || item.tap) @@ -3055,9 +3180,8 @@ PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; * @constructor * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format * like: 0xFFFFFF for white - * @param interactive {Boolean} enable / disable interaction (default is false) */ -PIXI.Stage = function(backgroundColor, interactive) +PIXI.Stage = function(backgroundColor) { PIXI.DisplayObjectContainer.call( this ); @@ -3077,7 +3201,7 @@ PIXI.Stage = function(backgroundColor, interactive) * @property interactive * @type Boolean */ - this.interactive = interactive; + this.interactive = true; /** * The interaction manage for this stage, manages all interactive activity on the stage @@ -3113,6 +3237,18 @@ PIXI.Stage = function(backgroundColor, interactive) PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); PIXI.Stage.prototype.constructor = PIXI.Stage; +/** + * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. + * This is useful for when you have other DOM elements ontop of the Canvas element. + * + * @method setInteractionDelegate + * @param domElement {DOMElement} This new domElement which will receive mouse/touch events + */ +PIXI.Stage.prototype.setInteractionDelegate = function(domElement) +{ + this.interactionManager.setTargetDomElement( domElement ); +} + /* * Updates the object transform for rendering * @@ -3122,6 +3258,7 @@ PIXI.Stage.prototype.constructor = PIXI.Stage; PIXI.Stage.prototype.updateTransform = function() { this.worldAlpha = 1; + this.vcount = PIXI.visibleCount; for(var i=0,j=this.children.length; i 100) { console.log("BREAK") break } - } + } } @@ -3361,14 +3466,14 @@ PIXI.runList = function(item) PIXI.EventTarget = function () { var listeners = {}; - + this.addEventListener = this.on = function ( type, listener ) { - - + + if ( listeners[ type ] === undefined ) { listeners[ type ] = []; - + } if ( listeners[ type ].indexOf( listener ) === - 1 ) { @@ -3379,11 +3484,17 @@ PIXI.EventTarget = function () { }; this.dispatchEvent = this.emit = function ( event ) { - - for ( var listener in listeners[ event.type ] ) { - listeners[ event.type ][ listener ]( event ); - + if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { + + return; + + } + + for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { + + listeners[ event.type ][ i ]( event ); + } }; @@ -3417,8 +3528,11 @@ PIXI.EventTarget = function () { * @param height {Number} the height of the renderers view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) + * + * antialias */ -PIXI.autoDetectRenderer = function(width, height, view, transparent) +PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) { if(!width)width = 800; if(!height)height = 600; @@ -3429,7 +3543,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) //console.log(webgl); if( webgl ) { - return new PIXI.WebGLRenderer(width, height, view, transparent); + return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); } return new PIXI.CanvasRenderer(width, height, view, transparent); @@ -3441,7 +3555,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) PolyK library url: http://polyk.ivank.net Released under MIT licence. - + Copyright (c) 2012 Ivan Kuckir Permission is hereby granted, free of charge, to any person @@ -3465,8 +3579,8 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent) FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - This is an amazing lib! - + This is an amazing lib! + slightly modified by mat groves (matgroves.com); */ @@ -3482,13 +3596,13 @@ PIXI.PolyK = {}; PIXI.PolyK.Triangulate = function(p) { var sign = true; - + var n = p.length>>1; if(n<3) return []; var tgs = []; var avl = []; for(var i=0; i 3) @@ -3496,11 +3610,11 @@ PIXI.PolyK.Triangulate = function(p) var i0 = avl[(i+0)%al]; var i1 = avl[(i+1)%al]; var i2 = avl[(i+2)%al]; - + var ax = p[2*i0], ay = p[2*i0+1]; var bx = p[2*i1], by = p[2*i1+1]; var cx = p[2*i2], cy = p[2*i2+1]; - + var earFound = false; if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) { @@ -3519,7 +3633,7 @@ PIXI.PolyK.Triangulate = function(p) al--; i = 0; } - else if(i++ > 3*al) + else if(i++ > 3*al) { // need to flip flip reverse it! // reset! @@ -3528,17 +3642,17 @@ PIXI.PolyK.Triangulate = function(p) var tgs = []; avl = []; for(var i=0; i= 0) == sign; } - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -3612,13 +3725,11 @@ PIXI.shaderVertexSrc = [ "attribute vec2 aVertexPosition;", "attribute vec2 aTextureCoord;", "attribute float aColor;", - //"uniform mat4 uMVMatrix;", "uniform vec2 projectionVector;", "varying vec2 vTextureCoord;", "varying float vColor;", "void main(void) {", - // "gl_Position = uMVMatrix * vec4(aVertexPosition, 1.0, 1.0);", "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", "vTextureCoord = aTextureCoord;", "vColor = aColor;", @@ -3658,7 +3769,6 @@ PIXI.stripShaderVertexSrc = [ "}" ]; - /* * primitive shader.. */ @@ -3685,6 +3795,8 @@ PIXI.primitiveShaderVertexSrc = [ "}" ]; +PIXI.shaderStack = []; + PIXI.initPrimitiveShader = function() { var gl = PIXI.gl; @@ -3699,27 +3811,26 @@ PIXI.initPrimitiveShader = function() shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); + + //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(shaderProgram.colorAttribute); +//gl.enableVertexAttribArray(program.textureCoordAttribute); + shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); PIXI.primitiveProgram = shaderProgram; + + } PIXI.initDefaultShader = function() { - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.shaderVertexSrc, PIXI.shaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - // shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.shaderProgram = shaderProgram; + PIXI.defaultShader = new PIXI.PixiShader(); + PIXI.defaultShader.init(); + PIXI.activateShader(PIXI.defaultShader); + /* + PIXI.shaderStack.push(PIXI.defaultShader); + PIXI.current*/ } PIXI.initDefaultStripShader = function() @@ -3736,9 +3847,7 @@ PIXI.initDefaultStripShader = function() shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); PIXI.stripShaderProgram = shaderProgram; @@ -3789,35 +3898,135 @@ PIXI.compileProgram = function(vertexSrc, fragmentSrc) return shaderProgram; } +PIXI.activateShader = function(shader) +{ + PIXI.shaderStack.push(shader); + + //console.log(">>>") + var gl = PIXI.gl; + + var shaderProgram = shader.program; + + // map uniforms.. + gl.useProgram(shaderProgram); + + gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + gl.enableVertexAttribArray(shaderProgram.colorAttribute); + gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); -PIXI.activateDefaultShader = function() + shader.syncUniforms(); + + PIXI.currentShader = shaderProgram; +} + + +PIXI.popShader = function() { var gl = PIXI.gl; - var shaderProgram = PIXI.shaderProgram; + // activate last program.. + var lastProgram = PIXI.shaderStack.pop(); + + var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); + PIXI.currentShader = shaderProgram; } - - PIXI.activatePrimitiveShader = function() { var gl = PIXI.gl; - gl.disableVertexAttribArray(PIXI.shaderProgram.textureCoordAttribute); - gl.disableVertexAttribArray(PIXI.shaderProgram.colorAttribute); - gl.useProgram(PIXI.primitiveProgram); - gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); + gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + + //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); } +PIXI.deactivatePrimitiveShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.currentShader); + + gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.PixiShader = function() +{ + // the webGL program.. + this.program; + + this.fragmentSrc = [ + "precision lowp float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", + "}" + ]; + +} + +PIXI.PixiShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get the default shader bits! + program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); + program.colorAttribute = gl.getAttribLocation(program, "aColor"); + program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); + + program.projectionVector = gl.getUniformLocation(program, "projectionVector"); + program.samplerUniform = gl.getUniformLocation(program, "uSampler"); + + // add those custom shaders! + for (var key in this.uniforms) + { + // get the uniform locations.. + program[key] = gl.getUniformLocation(program, key); + } + + this.program = program; +} + +PIXI.PixiShader.prototype.syncUniforms = function() +{ + var gl = PIXI.gl; + + for (var key in this.uniforms) + { + //var + var type = this.uniforms[key].type; + + // need to grow this! + if(type == "f") + { + gl.uniform1f(this.program[key], this.uniforms[key].value); + } + else if(type == "mat4") + { + gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); + } + } + +} + /** * @author Mat Groves http://matgroves.com/ @Doormat23 @@ -3887,7 +4096,7 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); // WHY DOES THIS LINE NEED TO BE THERE??? - gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // its not even used.. but need to be set or it breaks? // only on pc though.. @@ -3899,8 +4108,10 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); + PIXI.deactivatePrimitiveShader(); + // return to default shader... - PIXI.activateDefaultShader(); +// PIXI.activateShader(PIXI.defaultShader); } /** @@ -4243,7 +4454,7 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) verts.push(px , py); verts.push(r, g, b, alpha); - verts.push(p2x - (px-p2x), p2y - (py - p2y));//, 4); + verts.push(p2x - (px-p2x), p2y - (py - p2y)); verts.push(r, g, b, alpha); } } @@ -4356,9 +4567,10 @@ PIXI.gl; * @param height=0 {Number} the height of the canvas view * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) * */ -PIXI.WebGLRenderer = function(width, height, view, transparent) +PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) { // do a catch.. only 1 webGL renderer.. @@ -4382,7 +4594,7 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) { PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { alpha: this.transparent, - antialias:true, // SPEED UP?? + antialias:!!antialias, // SPEED UP?? premultipliedAlpha:false, stencil:true }); @@ -4392,11 +4604,12 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); } - PIXI.initPrimitiveShader(); PIXI.initDefaultShader(); + PIXI.initPrimitiveShader(); PIXI.initDefaultStripShader(); - PIXI.activateDefaultShader(); + +// PIXI.activateDefaultShader(); var gl = this.gl; PIXI.WebGLRenderer.gl = gl; @@ -4413,7 +4626,10 @@ PIXI.WebGLRenderer = function(width, height, view, transparent) this.resize(this.width, this.height); this.contextLost = false; + PIXI.activateShader(PIXI.defaultShader); + this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); + } // constructor @@ -4469,8 +4685,6 @@ PIXI.WebGLRenderer.prototype.render = function(stage) { // TODO make this work // dont think this is needed any more? - //if(this.__stage)this.checkVisibility(this.__stage, false) - this.__stage = stage; this.stageRenderGroup.setRenderable(stage); } @@ -4487,10 +4701,8 @@ PIXI.WebGLRenderer.prototype.render = function(stage) // update any textures PIXI.WebGLRenderer.updateTextures(); - // recursivly loop through all items! - //this.checkVisibility(stage, true); - // update the scene graph + PIXI.visibleCount++; stage.updateTransform(); var gl = this.gl; @@ -4499,16 +4711,12 @@ PIXI.WebGLRenderer.prototype.render = function(stage) gl.colorMask(true, true, true, this.transparent); gl.viewport(0, 0, this.width, this.height); - // set the correct matrix.. - // gl.uniformMatrix4fv(this.shaderProgram.mvMatrixUniform, false, this.projectionMatrix); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); gl.clear(gl.COLOR_BUFFER_BIT); // HACK TO TEST - //PIXI.projectionMatrix = this.projectionMatrix; this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; this.stageRenderGroup.render(PIXI.projection); @@ -4546,8 +4754,9 @@ PIXI.WebGLRenderer.prototype.render = function(stage) */ PIXI.WebGLRenderer.updateTextures = function() { - for (var i=0; i < PIXI.texturesToUpdate.length; i++) this.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) this.destroyTexture(PIXI.texturesToDestroy[i]); + //TODO break this out into a texture manager... + for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); + for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; } @@ -4562,6 +4771,7 @@ PIXI.WebGLRenderer.updateTextures = function() */ PIXI.WebGLRenderer.updateTexture = function(texture) { + //TODO break this out into a texture manager... var gl = PIXI.gl; if(!texture._glTexture) @@ -4602,9 +4812,10 @@ PIXI.WebGLRenderer.updateTexture = function(texture) * @param texture {Texture} The texture to update * @private */ -PIXI.WebGLRenderer.prototype.destroyTexture = function(texture) +PIXI.WebGLRenderer.destroyTexture = function(texture) { - var gl = this.gl; + //TODO break this out into a texture manager... + var gl = PIXI.gl; if(texture._glTexture) { @@ -4768,7 +4979,6 @@ PIXI.WebGLBatch.prototype.clean = function() this.uvs = []; this.indices = []; this.colors = []; - //this.sprites = []; this.dynamicSize = 1; this.texture = null; this.last = null; @@ -4805,7 +5015,6 @@ PIXI.WebGLBatch.prototype.init = function(sprite) this.dirty = true; this.blendMode = sprite.blendMode; this.texture = sprite.texture.baseTexture; -// this.sprites.push(sprite); this.head = sprite; this.tail = sprite; this.size = 1; @@ -4838,7 +5047,6 @@ PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) else { this.head = sprite; - //this.head.__prev = null } } @@ -4926,7 +5134,7 @@ PIXI.WebGLBatch.prototype.split = function(sprite) { this.dirty = true; - var batch = new PIXI.WebGLBatch(this.gl);//PIXI._getBatch(this.gl); + var batch = new PIXI.WebGLBatch(this.gl); batch.init(sprite); batch.texture = this.texture; batch.tail = this.tail; @@ -4936,8 +5144,6 @@ PIXI.WebGLBatch.prototype.split = function(sprite) sprite.__prev = null; // return a splite batch! - //sprite.__prev.__next = null; - //sprite.__prev = null; // TODO this size is wrong! // need to recalculate :/ problem with a linked list! @@ -5007,13 +5213,13 @@ PIXI.WebGLBatch.prototype.growBatch = function() gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); - this.uvs = new Float32Array( this.dynamicSize * 8 ) + this.uvs = new Float32Array( this.dynamicSize * 8 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); this.dirtyUVS = true; - this.colors = new Float32Array( this.dynamicSize * 4 ) + this.colors = new Float32Array( this.dynamicSize * 4 ); gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); @@ -5112,7 +5318,7 @@ PIXI.WebGLBatch.prototype.update = function() while(displayObject) { - if(displayObject.worldVisible) + if(displayObject.vcount === PIXI.visibleCount) { width = displayObject.texture.frame.width; height = displayObject.texture.frame.height; @@ -5214,7 +5420,7 @@ PIXI.WebGLBatch.prototype.update = function() PIXI.WebGLBatch.prototype.render = function(start, end) { start = start || 0; - //end = end || this.size; + if(end == undefined)end = this.size; if(this.dirty) @@ -5230,8 +5436,9 @@ PIXI.WebGLBatch.prototype.render = function(start, end) //TODO optimize this! - var shaderProgram = PIXI.shaderProgram; - gl.useProgram(shaderProgram); + var shaderProgram = PIXI.currentShader; + + //gl.useProgram(shaderProgram); // update the verts.. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); @@ -5239,6 +5446,8 @@ PIXI.WebGLBatch.prototype.render = function(start, end) gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // update the uvs + var isDefault = (shaderProgram == PIXI.shaderProgram) + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); if(this.dirtyUVS) @@ -5262,13 +5471,11 @@ PIXI.WebGLBatch.prototype.render = function(start, end) } gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - //var startIndex = 0//1; var len = end - start; - // console.log(this.size) + // DRAW THAT this! gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); } @@ -5336,77 +5543,45 @@ PIXI.WebGLRenderGroup.prototype.render = function(projection) PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - // TODO remove this by replacing visible with getter setters.. - this.checkVisibility(this.root, this.root.visible); - // will render all the elements in the group var renderable; - - for (var i=0; i < this.batchs.length; i++) { + renderable = this.batchs[i]; if(renderable instanceof PIXI.WebGLBatch) { this.batchs[i].render(); + continue; } - else if(renderable instanceof PIXI.TilingSprite) + + // non sprite batch.. + var worldVisible = renderable.vcount === PIXI.visibleCount; + + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ - if(renderable.open) - { - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - gl.colorMask(true, true, true, false); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - else - { - gl.disable(gl.STENCIL_TEST); - } + this.handleFilterBlock(renderable, projection); } } } -/** - * Renders the stage to its webgl view - * - * @method handleFilter - * @param filter {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.handleFilter = function(filter, projection) -{ - -} - /** * Renders a specific displayObject * @@ -5420,11 +5595,8 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - this.checkVisibility(displayObject, displayObject.visible); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); -// gl.uniformMatrix4fv(PIXI.shaderProgram.mvMatrixUniform, false, projectionMatrix); - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); - // to do! // render part of the scene... @@ -5483,7 +5655,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project while(lastItem.children.length > 0) { lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem; + if(lastItem.renderable)lastRenderable = lastItem.last; } if(lastRenderable instanceof PIXI.Sprite) @@ -5577,45 +5749,80 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project */ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) { + var sta = PIXI.shaderStack.length; + + var worldVisible = renderable.vcount === PIXI.visibleCount + if(renderable instanceof PIXI.TilingSprite) { - if(renderable.visible)this.renderTilingSprite(renderable, projection); + if(worldVisible)this.renderTilingSprite(renderable, projection); } else if(renderable instanceof PIXI.Strip) { - if(renderable.visible)this.renderStrip(renderable, projection); + if(worldVisible)this.renderStrip(renderable, projection); } else if(renderable instanceof PIXI.CustomRenderable) { - if(renderable.visible) renderable.renderWebGL(this, projection); + if(worldVisible) renderable.renderWebGL(this, projection); } else if(renderable instanceof PIXI.Graphics) { - if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ + this.handleFilterBlock(renderable, projection); + } +} - var gl = PIXI.gl; +PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) +{ + /* + * for now only masks are supported.. + */ + var gl = PIXI.gl; - if(renderable.open) + if(renderable.open) + { + if(renderable.data instanceof Array) + { + var filter = renderable.data[0]; + + if(!filter.shader) + { + var shader = new PIXI.PixiShader(); + + shader.fragmentSrc = filter.fragmentSrc; + shader.uniforms = filter.uniforms; + shader.init(); + + filter.shader = shader + } + + PIXI.activateShader(filter.shader); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } + else { gl.enable(gl.STENCIL_TEST); gl.colorMask(false, false, false, false); gl.stencilFunc(gl.ALWAYS,1,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - // we know this is a render texture so enable alpha too.. + PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); + gl.colorMask(true, true, true, true); gl.stencilFunc(gl.NOTEQUAL,0,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); } + } + else + { + if(renderable.data instanceof Array) + { + PIXI.popShader(); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } else { gl.disable(gl.STENCIL_TEST); @@ -5623,42 +5830,6 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) } } -/** - * Checks the visibility of a displayObject - * - * @method checkVisibility - * @param displayObject {DisplayObject} - * @param globalVisible {Boolean} - * @private - */ -PIXI.WebGLRenderGroup.prototype.checkVisibility = function(displayObject, globalVisible) -{ - // give the dp a reference to its renderGroup... - var children = displayObject.children; - //displayObject.worldVisible = globalVisible; - for (var i=0; i < children.length; i++) - { - var child = children[i]; - - // TODO optimize... should'nt need to loop through everything all the time - child.worldVisible = child.visible && globalVisible; - - // everything should have a batch! - // time to see whats new! - if(child.textureChange) - { - child.textureChange = false; - if(child.worldVisible)this.updateTexture(child); - // update texture!! - } - - if(child.children.length > 0) - { - this.checkVisibility(child, child.worldVisible); - } - }; -} - /** * Updates a webgl texture * @@ -5719,7 +5890,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * It keeps going back until it finds a sprite or the stage */ var previousRenderable = start; - while(previousRenderable != this.root) + while(previousRenderable != this.root.first) { previousRenderable = previousRenderable._iPrev; if(previousRenderable.renderable && previousRenderable.__renderGroup)break; @@ -5733,7 +5904,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * scene graph */ var previousRenderable2 = end; - while(previousRenderable2 != this.root) + while(previousRenderable2 != this.root.first) { previousRenderable2 = previousRenderable2._iPrev; if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; @@ -6105,6 +6276,7 @@ PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) } } + /** * Initializes a tiling sprite * @@ -6175,23 +6347,19 @@ PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) { var gl = this.gl; - var shaderProgram = PIXI.shaderProgram; -// mat - //var mat4Real = PIXI.mat3.toMat4(strip.worldTransform); - //PIXI.mat4.transpose(mat4Real); - //PIXI.mat4.multiply(projectionMatrix, mat4Real, mat4Real ) - + var shaderProgram = PIXI.stripShaderProgram; - gl.useProgram(PIXI.stripShaderProgram); + + gl.useProgram(shaderProgram); var m = PIXI.mat3.clone(strip.worldTransform); PIXI.mat3.transpose(m); // set the matrix transform for the - gl.uniformMatrix3fv(PIXI.stripShaderProgram.translationMatrix, false, m); - gl.uniform2f(PIXI.stripShaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(PIXI.stripShaderProgram.alpha, strip.worldAlpha); + gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); + gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); /* if(strip.blendMode == PIXI.blendModes.NORMAL) @@ -6249,11 +6417,10 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } - //console.log(gl.TRIANGLE_STRIP); gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - gl.useProgram(PIXI.shaderProgram); + gl.useProgram(PIXI.currentProgram); } /** @@ -6328,6 +6495,7 @@ PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } + /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -6401,7 +6569,6 @@ PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; */ PIXI.CanvasRenderer.prototype.render = function(stage) { - // update children if need be //stage.__childrenAdded = []; //stage.__childrenRemoved = []; @@ -6410,6 +6577,7 @@ PIXI.CanvasRenderer.prototype.render = function(stage) PIXI.texturesToUpdate = []; PIXI.texturesToDestroy = []; + PIXI.visibleCount++; stage.updateTransform(); // update the background color @@ -6496,7 +6664,7 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) var frame = displayObject.texture.frame; - if(frame) + if(frame && frame.width && frame.height) { context.globalAlpha = displayObject.worldAlpha; @@ -6534,31 +6702,34 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) } else if(displayObject instanceof PIXI.FilterBlock) { - if(displayObject.open) + if(PIXI.FilterBlock.data instanceof PIXI.Graphics) { - context.save(); - - var cacheAlpha = displayObject.mask.alpha; - var maskTransform = displayObject.mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - displayObject.mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); - // context.fillStyle = 0xFF0000; - // context.fillRect(0, 0, 200, 200); - context.clip(); - - displayObject.mask.worldAlpha = cacheAlpha; - //context.globalCompositeOperation = 'lighter'; + if(displayObject.open) + { + context.save(); + + var cacheAlpha = displayObject.mask.alpha; + var maskTransform = displayObject.mask.worldTransform; + + context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) + + displayObject.mask.worldAlpha = 0.5; + + context.worldAlpha = 0; + + PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); + context.clip(); + + displayObject.mask.worldAlpha = cacheAlpha; + } + else + { + context.restore(); + } } else { - //context.globalCompositeOperation = 'source-over'; - context.restore(); + // only masks supported right now! } } // count++ @@ -6651,7 +6822,7 @@ PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) PIXI.CanvasRenderer.prototype.renderStrip = function(strip) { var context = this.context; - //context.globalCompositeOperation = 'lighter'; + // draw triangles!! var verticies = strip.verticies; var uvs = strip.uvs; @@ -6678,8 +6849,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.lineTo(x2, y2); context.closePath(); - // context.fillStyle = "white"//rgb(1, 1, 1,1)); - // context.fill(); context.clip(); @@ -6703,7 +6872,6 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) context.restore(); }; -// context.globalCompositeOperation = 'source-over'; } /** @@ -6718,7 +6886,7 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) */ PIXI.CanvasGraphics = function() { - + } @@ -6734,35 +6902,33 @@ PIXI.CanvasGraphics = function() PIXI.CanvasGraphics.renderGraphics = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - - for (var i=0; i < graphics.graphicsData.length; i++) + + for (var i=0; i < graphics.graphicsData.length; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); context.lineWidth = data.lineWidth; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); - + context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6777,21 +6943,20 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.RECT) { - - // TODO - need to be Undefined! - if(data.fillColor) + + if(data.fillColor || data.fillColor === 0) { context.globalAlpha = data.fillAlpha * worldAlpha; context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); context.fillRect(points[0], points[1], points[2], points[3]); - + } if(data.lineWidth) { context.globalAlpha = data.lineAlpha * worldAlpha; context.strokeRect(points[0], points[1], points[2], points[3]); } - + } else if(data.type == PIXI.Graphics.CIRC) { @@ -6799,7 +6964,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.beginPath(); context.arc(points[0], points[1], points[2],0,2*Math.PI); context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6814,19 +6979,19 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - + var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6834,15 +6999,15 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - + context.closePath(); - + if(data.fill) { context.globalAlpha = data.fillAlpha * worldAlpha; @@ -6855,7 +7020,7 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) context.stroke(); } } - + }; } @@ -6871,37 +7036,35 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context) PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) { var worldAlpha = graphics.worldAlpha; - + var len = graphics.graphicsData.length; if(len > 1) { len = 1; console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") } - - for (var i=0; i < 1; i++) + + for (var i=0; i < 1; i++) { var data = graphics.graphicsData[i]; var points = data.points; - + if(data.type == PIXI.Graphics.POLY) { - //if(data.lineWidth <= 0)continue; - context.beginPath(); context.moveTo(points[0], points[1]); - + for (var j=1; j < points.length/2; j++) { context.lineTo(points[j * 2], points[j * 2 + 1]); - } - + } + // if the first and last point are the same close the path - much neater :) if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) { context.closePath(); } - + } else if(data.type == PIXI.Graphics.RECT) { @@ -6918,18 +7081,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) } else if(data.type == PIXI.Graphics.ELIP) { - + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas var elipseData = data.points; - + var w = elipseData[2] * 2; var h = elipseData[3] * 2; - + var x = elipseData[0] - w/2; var y = elipseData[1] - h/2; - + context.beginPath(); - + var kappa = .5522848, ox = (w / 2) * kappa, // control point offset horizontal oy = (h / 2) * kappa, // control point offset vertical @@ -6937,7 +7100,7 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) ye = y + h, // y-end xm = x + w / 2, // x-middle ym = y + h / 2; // y-middle - + context.moveTo(x, ym); context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); @@ -6945,8 +7108,8 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); context.closePath(); } - - + + }; } @@ -6956,18 +7119,18 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) /** - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. + * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. * It is important to know that with the webGL renderer only simple polys can be filled at this stage * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png * - * @class Graphics + * @class Graphics * @extends DisplayObjectContainer * @constructor */ PIXI.Graphics = function() { PIXI.DisplayObjectContainer.call( this ); - + this.renderable = true; /** @@ -7028,14 +7191,14 @@ PIXI.Graphics.prototype.constructor = PIXI.Graphics; PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - + this.lineWidth = lineWidth || 0; this.lineColor = color || 0; this.lineAlpha = (alpha == undefined) ? 1 : alpha; - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.graphicsData.push(this.currentPath); } @@ -7049,12 +7212,12 @@ PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) PIXI.Graphics.prototype.moveTo = function(x, y) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + + this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - + this.currentPath.points.push(x, y); - + this.graphicsData.push(this.currentPath); } @@ -7084,7 +7247,7 @@ PIXI.Graphics.prototype.beginFill = function(color, alpha) { this.filling = true; this.fillColor = color || 0; - this.fillAlpha = alpha || 1; + this.fillAlpha = (alpha == undefined) ? 1 : alpha; } /** @@ -7110,11 +7273,11 @@ PIXI.Graphics.prototype.endFill = function() PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.RECT}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7130,11 +7293,11 @@ PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) PIXI.Graphics.prototype.drawCircle = function( x, y, radius) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7151,11 +7314,11 @@ PIXI.Graphics.prototype.drawCircle = function( x, y, radius) PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) { if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[x, y, width, height], type:PIXI.Graphics.ELIP}; - + this.graphicsData.push(this.currentPath); this.dirty = true; } @@ -7169,7 +7332,7 @@ PIXI.Graphics.prototype.clear = function() { this.lineWidth = 0; this.filling = false; - + this.dirty = true; this.clearDirty = true; this.graphicsData = []; @@ -7190,20 +7353,20 @@ PIXI.Strip = function(texture, width, height) PIXI.DisplayObjectContainer.call( this ); this.texture = texture; this.blendMode = PIXI.blendModes.NORMAL; - + try { this.uvs = new Float32Array([0, 1, 1, 1, 1, 0, 0,1]); - + this.verticies = new Float32Array([0, 0, 0,0, 0,0, 0, 0, 0]); - + this.colors = new Float32Array([1, 1, 1, 1]); - + this.indices = new Uint16Array([0, 1, 2, 3]); } catch(error) @@ -7211,18 +7374,18 @@ PIXI.Strip = function(texture, width, height) this.uvs = [0, 1, 1, 1, 1, 0, 0,1]; - + this.verticies = [0, 0, 0,0, 0,0, 0, 0, 0]; - + this.colors = [1, 1, 1, 1]; - + this.indices = [0, 1, 2, 3]; } - - + + /* this.uvs = new Float32Array() this.verticies = new Float32Array() @@ -7231,7 +7394,7 @@ PIXI.Strip = function(texture, width, height) */ this.width = width; this.height = height; - + // load the texture! if(texture.baseTexture.hasLoaded) { @@ -7244,7 +7407,7 @@ PIXI.Strip = function(texture, width, height) this.onTextureUpdateBind = this.onTextureUpdate.bind(this); this.texture.addEventListener( 'update', this.onTextureUpdateBind ); } - + this.renderable = true; } @@ -7256,8 +7419,8 @@ PIXI.Strip.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.width = texture.frame.width; this.height = texture.frame.height; @@ -7280,7 +7443,7 @@ PIXI.Rope = function(texture, points) { PIXI.Strip.call( this, texture ); this.points = points; - + try { this.verticies = new Float32Array( points.length * 4); @@ -7291,12 +7454,12 @@ PIXI.Rope = function(texture, points) catch(error) { this.verticies = verticies - + this.uvs = uvs this.colors = colors this.indices = indices } - + this.refresh(); } @@ -7309,99 +7472,99 @@ PIXI.Rope.prototype.refresh = function() { var points = this.points; if(points.length < 1)return; - + var uvs = this.uvs var indices = this.indices; var colors = this.colors; - + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - + + uvs[0] = 0 uvs[1] = 1 uvs[2] = 0 uvs[3] = 1 - + colors[0] = 1; colors[1] = 1; - + indices[0] = 0; indices[1] = 1; - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; // time to do some smart drawing! var 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; } } PIXI.Rope.prototype.updateTransform = function() { - + var points = this.points; if(points.length < 1)return; - - var verticies = this.verticies - + + var verticies = this.verticies + var lastPoint = points[0]; var nextPoint; var perp = {x:0, y:0}; var point = points[0]; - + this.count-=0.2; - - verticies[0] = point.x + perp.x + + verticies[0] = point.x + perp.x verticies[1] = point.y + perp.y //+ 200 - verticies[2] = point.x - perp.x + verticies[2] = point.x - perp.x verticies[3] = point.y - perp.y//+200 // time to do some smart drawing! - + var total = points.length; - - for (var i = 1; i < total; i++) + + for (var i = 1; i < total; i++) { - + var point = points[i]; var index = i * 4; - + if(i < points.length-1) { nextPoint = points[i+1]; @@ -7410,35 +7573,35 @@ PIXI.Rope.prototype.updateTransform = function() { nextPoint = point } - + perp.y = -(nextPoint.x - lastPoint.x); perp.x = nextPoint.y - lastPoint.y; - + var ratio = (1 - (i / (total-1))) * 10; if(ratio > 1)ratio = 1; - + var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); var 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; - - verticies[index] = point.x + perp.x + + verticies[index] = point.x + perp.x verticies[index+1] = point.y + perp.y - verticies[index+2] = point.x - perp.x + verticies[index+2] = point.x - perp.x verticies[index+3] = point.y - perp.y lastPoint = point; } - + PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); } PIXI.Rope.prototype.setTexture = function(texture) { - // stop current texture + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7494,7 +7657,7 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tileScale * @type Point - */ + */ this.tileScale = new PIXI.Point(1,1); /** @@ -7502,11 +7665,11 @@ PIXI.TilingSprite = function(texture, width, height) * * @property tilePosition * @type Point - */ + */ this.tilePosition = new PIXI.Point(0,0); this.renderable = true; - + this.blendMode = PIXI.blendModes.NORMAL } @@ -7524,8 +7687,8 @@ PIXI.TilingSprite.prototype.setTexture = function(texture) { //TODO SET THE TEXTURES //TODO VISIBILITY - - // stop current texture + + // stop current texture this.texture = texture; this.updateFrame = true; } @@ -7546,10 +7709,10 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) /** * @author Mat Groves http://matgroves.com/ @Doormat23 * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * + * * Awesome JS run time provided by EsotericSoftware * https://github.com/EsotericSoftware/spine-runtimes - * + * */ /** @@ -7562,48 +7725,41 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event) * @constructor * @param url {String} The url of the spine anim file to be used */ -PIXI.Spine = function(url) -{ +PIXI.Spine = function (url) { PIXI.DisplayObjectContainer.call(this); - + this.spineData = PIXI.AnimCache[url]; - - if(!this.spineData) - { + + if (!this.spineData) { throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: " + url); - return; } - - this.count = 0; - - this.sprites = []; - + this.skeleton = new spine.Skeleton(this.spineData); this.skeleton.updateWorldTransform(); - this.stateData = new spine.AnimationStateData(this.spineData); + this.stateData = new spine.AnimationStateData(this.spineData); this.state = new spine.AnimationState(this.stateData); - - // add the sprites.. - for (var i = 0; i < this.skeleton.drawOrder.length; i++) { - - var attachmentName = this.skeleton.drawOrder[i].data.attachmentName; - - // kind of an assumtion here. that its a png - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; - } - - - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(attachmentName)); - sprite.anchor.x = sprite.anchor.y = 0.5; - this.addChild(sprite); - this.sprites.push(sprite); - }; -} -PIXI.Spine.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); + 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)) { + continue; + } + var spriteName = attachment.rendererObject.name; + var sprite = this.createSprite(slot, attachment.rendererObject); + slot.currentSprite = sprite; + slot.currentSpriteName = spriteName; + slotContainer.addChild(sprite); + } +}; + +PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); PIXI.Spine.prototype.constructor = PIXI.Spine; /* @@ -7612,55 +7768,74 @@ PIXI.Spine.prototype.constructor = PIXI.Spine; * @method updateTransform * @private */ -PIXI.Spine.prototype.updateTransform = function() -{ - // TODO should make this time based really.. - this.state.update(1/60); +PIXI.Spine.prototype.updateTransform = function () { + this.lastTime = this.lastTime || Date.now(); + var timeDelta = (Date.now() - this.lastTime) * 0.001; + this.lastTime = Date.now(); + this.state.update(timeDelta); this.state.apply(this.skeleton); this.skeleton.updateWorldTransform(); - - for (var i = 0; i < this.skeleton.drawOrder.length; i++) - { - var slot = this.skeleton.drawOrder[i]; + 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 instanceof spine.RegionAttachment)) { + slotContainer.visible = false; + continue; + } - var x = slot.bone.worldX + slot.attachment.x * slot.bone.m00 + slot.attachment.y * slot.bone.m01 + slot.attachment.width * 0.5; - var y = slot.bone.worldY + slot.attachment.x * slot.bone.m10 + slot.attachment.y * slot.bone.m11 + slot.attachment.height * 0.5; - //console.log(x + ' : ' + y); - - - //console.log(slot.attachment.name) - if(slot.cacheName != slot.attachment.name) - { - var attachmentName = slot.attachment.name; - - if(!PIXI.TextureCache[attachmentName]) - { - attachmentName += ".png"; + if (attachment.rendererObject) { + if (!slot.currentSpriteName || slot.currentSpriteName != attachment.name) { + var spriteName = attachment.rendererObject.name; + if (slot.currentSprite !== undefined) { + slot.currentSprite.visible = false; } - - this.sprites[i].setTexture(PIXI.TextureCache[attachmentName]); - - slot.cacheName = slot.attachment.name; + slot.sprites = slot.sprites || {}; + if (slot.sprites[spriteName] !== undefined) { + slot.sprites[spriteName].visible = true; + } else { + var sprite = this.createSprite(slot, attachment.rendererObject); + slotContainer.addChild(sprite); + } + slot.currentSprite = slot.sprites[spriteName]; + slot.currentSpriteName = spriteName; } - - x += -((slot.attachment.width * (slot.bone.worldScaleX + slot.attachment.scaleX - 1))>>1); - y += -((slot.attachment.height * (slot.bone.worldScaleY + slot.attachment.scaleY - 1))>>1); - - - this.sprites[i].position.x = x; - this.sprites[i].position.y = y; - this.sprites[i].rotation = (-(slot.bone.worldRotation + slot.attachment.rotation)) * (Math.PI/180); - } - + } + slotContainer.visible = true; + + 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 * Math.PI / 180); + } + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -} +}; + + +PIXI.Spine.prototype.createSprite = function (slot, descriptor) { + var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; + var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); + sprite.scale = descriptor.scale; + sprite.rotation = descriptor.rotation; + sprite.anchor.x = sprite.anchor.y = 0.5; + + slot.sprites = slot.sprites || {}; + slot.sprites[descriptor.name] = sprite; + return sprite; +}; /* * Awesome JS run time provided by EsotericSoftware - * + * * https://github.com/EsotericSoftware/spine-runtimes - * + * */ var spine = {}; @@ -7770,7 +7945,7 @@ spine.Slot.prototype = { this.g = data.g; this.b = data.b; this.a = data.a; - + var slotDatas = this.skeleton.data.slots; for (var i = 0, n = slotDatas.length; i < n; i++) { if (slotDatas[i] == data) { @@ -8001,6 +8176,7 @@ spine.TranslateTimeline.prototype = { var frameTime = frames[frameIndex]; var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); + bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; } @@ -8025,14 +8201,12 @@ spine.ScaleTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. - + var bone = skeleton.bones[this.boneIndex]; if (time >= frames[frames.length - 3]) { // Time is after last frame. bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - - return; } @@ -8070,6 +8244,7 @@ spine.ColorTimeline.prototype = { apply: function (skeleton, time, alpha) { var frames = this.frames; if (time < frames[0]) return; // Time is before first frame. + var slot = skeleton.slots[this.slotIndex]; if (time >= frames[frames.length - 5]) { // Time is after last frame. @@ -8119,7 +8294,7 @@ spine.AttachmentTimeline = function (frameCount) { spine.AttachmentTimeline.prototype = { slotIndex: 0, getFrameCount: function () { - return this.frames.length / 2; + return this.frames.length; }, setFrame: function (frameIndex, time, attachmentName) { this.frames[frameIndex] = time; @@ -8136,11 +8311,6 @@ spine.AttachmentTimeline.prototype = { frameIndex = spine.binarySearch(frames, time, 1) - 1; var attachmentName = this.attachmentNames[frameIndex]; - //console.log(skeleton.slots[this.slotIndex]) - - // change the name! - // skeleton.slots[this.slotIndex].attachmentName = attachmentName; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); } }; @@ -8312,11 +8482,9 @@ spine.Skeleton.prototype = { if (slot.data.name == slotName) { var attachment = null; if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; } - slot.setAttachment(attachment); return; } @@ -8398,7 +8566,6 @@ spine.RegionAttachment.prototype = { offset[7/*Y4*/] = localYCos + localX2Sin; }, computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; y += bone.worldY; var m00 = bone.m00; @@ -8422,6 +8589,7 @@ spine.AnimationStateData = function (skeletonData) { this.animationToMixTime = {}; }; spine.AnimationStateData.prototype = { + defaultMix: 0, setMixByName: function (fromName, toName, duration) { var from = this.skeletonData.findAnimation(fromName); if (!from) throw "Animation not found: " + fromName; @@ -8434,7 +8602,7 @@ spine.AnimationStateData.prototype = { }, getMix: function (from, to) { var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : 0; + return time ? time : this.defaultMix; } }; @@ -8474,7 +8642,7 @@ spine.AnimationState.prototype = { this.previous = null; } this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else + } else this.current.apply(skeleton, this.currentTime, this.currentLoop); }, clearAnimation: function () { @@ -8620,16 +8788,9 @@ spine.SkeletonJson.prototype = { name = map["name"] || name; var type = spine.AttachmentType[map["type"] || "region"]; - - // @ekelokorpi - // var attachment = this.attachmentLoader.newAttachment(skin, type, name); - var attachment = new spine.RegionAttachment(); - - // @Doormat23 - // add the name of the attachment - attachment.name = name; - + if (type == spine.AttachmentType.region) { + var attachment = new spine.RegionAttachment(); attachment.x = (map["x"] || 0) * this.scale; attachment.y = (map["y"] || 0) * this.scale; attachment.scaleX = map["scaleX"] || 1; @@ -8638,10 +8799,19 @@ spine.SkeletonJson.prototype = { attachment.width = (map["width"] || 32) * this.scale; attachment.height = (map["height"] || 32) * this.scale; attachment.updateOffset(); + + attachment.rendererObject = {}; + attachment.rendererObject.name = name; + attachment.rendererObject.scale = {}; + attachment.rendererObject.scale.x = attachment.scaleX; + attachment.rendererObject.scale.y = attachment.scaleY; + attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; + return attachment; } - return attachment; + throw "Unknown attachment type: " + type; }, + readAnimation: function (name, map, skeletonData) { var timelines = []; var duration = 0; @@ -8692,7 +8862,7 @@ spine.SkeletonJson.prototype = { } timelines.push(timeline); duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - + } else throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; } @@ -8735,8 +8905,8 @@ spine.SkeletonJson.prototype = { timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); } timelines.push(timeline); - // PIXI FIX - duration = Math.max(duration, timeline.frames[Math.floor(timeline.getFrameCount()) - 1]); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } else throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; } @@ -9005,14 +9175,14 @@ spine.Bone.yDown = true; /** * This object is one that will allow you to specify custom rendering functions based on render type * - * @class CustomRenderable + * @class CustomRenderable * @extends DisplayObject * @constructor */ PIXI.CustomRenderable = function() { PIXI.DisplayObject.call( this ); - + } // constructor @@ -9118,19 +9288,19 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } else { - + var scope = this; this.source.onload = function(){ - + scope.hasLoaded = true; scope.width = scope.source.width; scope.height = scope.source.height; - + // add it to somewhere... PIXI.texturesToUpdate.push(scope); scope.dispatchEvent( { type: 'loaded', content: scope } ); @@ -9143,7 +9313,7 @@ PIXI.BaseTexture = function(source) this.hasLoaded = true; this.width = this.source.width; this.height = this.source.height; - + PIXI.texturesToUpdate.push(this); } @@ -9183,7 +9353,7 @@ PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) { // new Image() breaks tex loading in some versions of Chrome. // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); + var image = new Image();//document.createElement('img'); if (crossorigin) { image.crossOrigin = ''; @@ -9211,7 +9381,7 @@ PIXI.FrameCache = {}; * @uses EventTarget * @constructor * @param baseTexture {BaseTexture} The base texture source to create the texture from - * @param frmae {Rectangle} The rectangle frame of the texture to show + * @param frame {Rectangle} The rectangle frame of the texture to show */ PIXI.Texture = function(baseTexture, frame) { @@ -9256,7 +9426,7 @@ PIXI.Texture = function(baseTexture, frame) { if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); //console.log(frame) - + this.setFrame(frame); } else @@ -9335,13 +9505,13 @@ PIXI.Texture.prototype.setFrame = function(frame) PIXI.Texture.fromImage = function(imageUrl, crossorigin) { var texture = PIXI.TextureCache[imageUrl]; - + if(!texture) { texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); PIXI.TextureCache[imageUrl] = texture; } - + return texture; } @@ -9391,7 +9561,7 @@ PIXI.Texture.addTextureToCache = function(texture, id) } /** - * Remove a texture from the textureCache. + * Remove a texture from the textureCache. * * @static * @method removeTextureFromCache @@ -9503,15 +9673,7 @@ PIXI.RenderTexture.prototype.initWebGL = function() // create a projection matrix.. this.projection = new PIXI.Point(this.width/2 , this.height/2); -/* - this.projectionMatrix = PIXI.mat4.create(); - this.projectionMatrix[5] = 2/this.height// * 0.5; - this.projectionMatrix[13] = -1; - - this.projectionMatrix[0] = 2/this.width; - this.projectionMatrix[12] = -1; -*/ // set the correct render function.. this.render = this.renderWebGL; @@ -9525,10 +9687,6 @@ PIXI.RenderTexture.prototype.resize = function(width, height) this.width = width; this.height = height; - //this.frame.width = this.width - //this.frame.height = this.height; - - if(PIXI.gl) { this.projection.x = this.width/2 @@ -9592,6 +9750,7 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle var children = displayObject.children; //TODO -? create a new one??? dont think so! + var originalWorldTransform = displayObject.worldTransform; displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; // modify to flip... displayObject.worldTransform[4] = -1; @@ -9604,8 +9763,9 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle displayObject.worldTransform[5] -= position.y; } - - + PIXI.visibleCount++; + displayObject.vcount = PIXI.visibleCount; + for(var i=0,j=children.length; i- format + */ +PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) +{ + this.frames = []; + var cols = Math.floor(this.texture.width / frameWidth); + var rows = Math.floor(this.texture.height / frameHeight); + + var i=0; + for (var y=0; y= 0; i--) { var child = children[i]; - + // if(child.visible) { // push all interactive bits if(child.interactive) @@ -146,7 +144,7 @@ PIXI.InteractionManager.prototype.setTarget = function(target) PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) { //remove previouse listeners - if( this.interactionDOMElement !== null ) + if( this.interactionDOMElement !== null ) { this.interactionDOMElement.style['-ms-content-zooming'] = ''; this.interactionDOMElement.style['-ms-touch-action'] = ''; @@ -162,12 +160,12 @@ PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) } - if (window.navigator.msPointerEnabled) + if (window.navigator.msPointerEnabled) { // time to remove some of that zoom in ja.. domElement.style['-ms-content-zooming'] = 'none'; domElement.style['-ms-touch-action'] = 'none'; - + // DO some window specific touch! } @@ -193,7 +191,7 @@ PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) PIXI.InteractionManager.prototype.update = function() { if(!this.target)return; - + // frequency of 30fps?? var now = Date.now(); var diff = now - this.last; @@ -201,44 +199,44 @@ PIXI.InteractionManager.prototype.update = function() if(diff < 1)return; this.last = now; // - + // ok.. so mouse events?? // yes for now :) // OPTIMSE - how often to check?? if(this.dirty) { this.dirty = false; - + var len = this.interactiveItems.length; - + for (var i=0; i < len; i++) { this.interactiveItems[i].interactiveChildren = false; } - + this.interactiveItems = []; - + if(this.stage.interactive)this.interactiveItems.push(this.stage); // go through and collect all the objects that are interactive.. this.collectInteractiveSprite(this.stage, this.stage); } - + // loop through interactive objects! var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - + + this.interactionDOMElement.style.cursor = "default"; + for (var i = 0; i < length; i++) { var item = this.interactiveItems[i]; - - + + //if(!item.visible)continue; - + // OPTIMISATION - only calculate every time if the mousemove function exists.. // OK so.. does the object have any other interactive functions? // hit-test the clip! - - + + if(item.mouseover || item.mouseout || item.buttonMode) { // ok so there are some functions so lets hit test it.. @@ -248,13 +246,13 @@ PIXI.InteractionManager.prototype.update = function() // loks like there was a hit! if(item.__hit) { - if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; - + if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; + if(!item.__isOver) { - + if(item.mouseover)item.mouseover(this.mouse); - item.__isOver = true; + item.__isOver = true; } } else @@ -263,11 +261,11 @@ PIXI.InteractionManager.prototype.update = function() { // roll out! if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; + item.__isOver = false; } } } - + // ---> } } @@ -284,18 +282,18 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) this.mouse.originalEvent = event || window.event; //IE uses window.event // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.interactionDOMElement.getBoundingClientRect(); - + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); - + var length = this.interactiveItems.length; var global = this.mouse.global; - - + + for (var i = 0; i < length; i++) { var item = this.interactiveItems[i]; - + if(item.mousemove) { //call the function! @@ -314,34 +312,34 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event) PIXI.InteractionManager.prototype.onMouseDown = function(event) { this.mouse.originalEvent = event || window.event; //IE uses window.event - + // loop through inteaction tree... - // hit test each item! -> + // hit test each item! -> // get interactive items under point?? //stage.__i var length = this.interactiveItems.length; var global = this.mouse.global; - + var index = 0; var parent = this.stage; - - // while - // hit test + + // while + // hit test for (var i = 0; i < length; i++) { var item = this.interactiveItems[i]; - + if(item.mousedown || item.click) { item.__mouseIsDown = true; item.__hit = this.hitTest(item, this.mouse); - + if(item.__hit) { //call the function! if(item.mousedown)item.mousedown(this.mouse); item.__isDown = true; - + // just the one! if(!item.interactiveChildren)break; } @@ -353,18 +351,18 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) PIXI.InteractionManager.prototype.onMouseOut = function(event) { var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - + + this.interactionDOMElement.style.cursor = "default"; + for (var i = 0; i < length; i++) { var item = this.interactiveItems[i]; - + if(item.__isOver) { this.mouse.target = item; if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; + item.__isOver = false; } } } @@ -379,21 +377,21 @@ PIXI.InteractionManager.prototype.onMouseOut = function(event) PIXI.InteractionManager.prototype.onMouseUp = function(event) { this.mouse.originalEvent = event || window.event; //IE uses window.event - + var global = this.mouse.global; - - + + var length = this.interactiveItems.length; var up = false; - + for (var i = 0; i < length; i++) { var item = this.interactiveItems[i]; - + if(item.mouseup || item.mouseupoutside || item.click) { item.__hit = this.hitTest(item, this.mouse); - + if(item.__hit && !up) { //call the function! @@ -405,7 +403,7 @@ PIXI.InteractionManager.prototype.onMouseUp = function(event) { if(item.click)item.click(this.mouse); } - + if(!item.interactiveChildren)up = true; } else @@ -415,8 +413,8 @@ PIXI.InteractionManager.prototype.onMouseUp = function(event) if(item.mouseupoutside)item.mouseupoutside(this.mouse); } } - - item.__isDown = false; + + item.__isDown = false; } } } @@ -432,7 +430,7 @@ PIXI.InteractionManager.prototype.onMouseUp = function(event) PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) { var global = interactionData.global; - + if(item.vcount !== PIXI.visibleCount)return false; var isSprite = (item instanceof PIXI.Sprite), @@ -444,7 +442,7 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; interactionData.target = item; - + //a sprite or display object with a hit area defined if(item.hitArea && item.hitArea.contains) { if(item.hitArea.contains(x, y)) { @@ -453,7 +451,7 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) return true; } - + return false; } // a sprite with no hitarea defined @@ -463,11 +461,11 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) height = item.texture.frame.height, x1 = -width * item.anchor.x, y1; - + if(x > x1 && x < x1 + width) { y1 = -height * item.anchor.y; - + if(y > y1 && y < y1 + height) { // set the target property if a hit is true! @@ -478,7 +476,7 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) } var length = item.children.length; - + for (var i = 0; i < length; i++) { var tempItem = item.children[i]; @@ -491,7 +489,7 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) } } - return false; + return false; } /** @@ -505,18 +503,18 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) { var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) + + for (var i=0; i < changedTouches.length; i++) { var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; touchData.originalEvent = event || window.event; - + // update the touch position touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); } - + var length = this.interactiveItems.length; for (var i = 0; i < length; i++) { @@ -535,38 +533,38 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event) PIXI.InteractionManager.prototype.onTouchStart = function(event) { var rect = this.interactionDOMElement.getBoundingClientRect(); - + var changedTouches = event.changedTouches; - for (var i=0; i < changedTouches.length; i++) + for (var i=0; i < changedTouches.length; i++) { var touchEvent = changedTouches[i]; - + var touchData = this.pool.pop(); if(!touchData)touchData = new PIXI.InteractionData(); - + touchData.originalEvent = event || window.event; - + this.touchs[touchEvent.identifier] = touchData; touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - + var length = this.interactiveItems.length; - + for (var j = 0; j < length; j++) { var item = this.interactiveItems[j]; - + if(item.touchstart || item.tap) { item.__hit = this.hitTest(item, touchData); - + if(item.__hit) { //call the function! if(item.touchstart)item.touchstart(touchData); item.__isDown = true; item.__touchData = touchData; - + if(!item.interactiveChildren)break; } } @@ -586,28 +584,28 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) //this.mouse.originalEvent = event || window.event; //IE uses window.event var rect = this.interactionDOMElement.getBoundingClientRect(); var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) + + for (var i=0; i < changedTouches.length; i++) { var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; var up = false; touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - + var length = this.interactiveItems.length; for (var j = 0; j < length; j++) { var item = this.interactiveItems[j]; var itemTouchData = item.__touchData; // <-- Here! item.__hit = this.hitTest(item, touchData); - + if(itemTouchData == touchData) { // so this one WAS down... touchData.originalEvent = event || window.event; // hitTest?? - + if(item.touchend || item.tap) { if(item.__hit && !up) @@ -617,7 +615,7 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) { if(item.tap)item.tap(touchData); } - + if(!item.interactiveChildren)up = true; } else @@ -627,16 +625,16 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) if(item.touchendoutside)item.touchendoutside(touchData); } } - + item.__isDown = false; } - + item.__touchData = null; - + } else { - + } } // remove the touch.. @@ -656,11 +654,11 @@ PIXI.InteractionData = function() /** * This point stores the global coords of where the touch/mouse event happened * - * @property global + * @property global * @type Point */ this.global = new PIXI.Point(); - + // this is here for legacy... but will remove this.local = new PIXI.Point(); @@ -692,7 +690,7 @@ PIXI.InteractionData.prototype.getLocalPosition = function(displayObject) { var worldTransform = displayObject.worldTransform; var global = this.global; - + // do a cheeky transform to get the mouse coords; var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], diff --git a/src/pixi/display/DisplayObject.js b/src/pixi/display/DisplayObject.js index f7874f3..455284d 100644 --- a/src/pixi/display/DisplayObject.js +++ b/src/pixi/display/DisplayObject.js @@ -12,7 +12,6 @@ PIXI.DisplayObject = function() { this.last = this; this.first = this; - /** * The coordinate of the object relative to the local coordinates of the parent. * @@ -50,7 +49,7 @@ PIXI.DisplayObject = function() * * @property alpha * @type Number - */ + */ this.alpha = 1; /** @@ -58,7 +57,7 @@ PIXI.DisplayObject = function() * * @property visible * @type Boolean - */ + */ this.visible = true; /** @@ -67,7 +66,7 @@ PIXI.DisplayObject = function() * * @property hitArea * @type Rectangle|Circle|Ellipse|Polygon - */ + */ this.hitArea = null; /** @@ -92,7 +91,7 @@ PIXI.DisplayObject = function() * @property parent * @type DisplayObjectContainer * @readOnly - */ + */ this.parent = null; /** @@ -101,7 +100,7 @@ PIXI.DisplayObject = function() * @property stage * @type Stage * @readOnly - */ + */ this.stage = null; /** @@ -268,7 +267,7 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'interactive', { }, set: function(value) { this._interactive = value; - + // TODO more to be done here.. // need to sort out a re-crawl! if(this.stage)this.stage.dirty = true; @@ -288,17 +287,58 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { return this._mask; }, set: function(value) { - - this._mask = value; - + + if(value) { + if(this._mask) + { + value.start = this._mask.start; + value.end = this._mask.end; + } + else + { + this.addFilter(value); + value.renderable = false; + } + } + else + { + this.removeFilter(this._mask); + this._mask.renderable = true; + } + + this._mask = value; + } +}); + +/** + * Sets the filters for the displayObject. Currently there's a few limitations. + * 1: At the moment only one filter can be applied at a time.. + * 2: They cannot be nested. + * 3: There's no padding yet. + * 4: this is a webGL only feature. + * @property filters + * @type Array + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { + get: function() { + return this._filters; + }, + set: function(value) { + + //if(value == ) + if(value) + { + if(this._filters)this.removeFilter(this._filters); this.addFilter(value) } else { - this.removeFilter(); + if(this._filters)this.removeFilter(this._filters); } + + this._filters = value; } }); @@ -309,54 +349,58 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { * @param mask {Graphics} the graphics object to use as a filter * @private */ -PIXI.DisplayObject.prototype.addFilter = function(mask) +PIXI.DisplayObject.prototype.addFilter = function(data) { - if(this.filter)return; - this.filter = true; - + //if(this.filter)return; + //this.filter = true; + // insert a filter block.. + // TODO Onject pool thease bad boys.. var start = new PIXI.FilterBlock(); var end = new PIXI.FilterBlock(); - - start.mask = mask; - end.mask = mask; - + + data.start = start; + data.end = end; + + start.data = data; + end.data = data; + start.first = start.last = this; end.first = end.last = this; - + start.open = true; - + /* * insert start */ - + var childFirst = start var childLast = start var nextObject; var previousObject; - + previousObject = this.first._iPrev; - + if(previousObject) { nextObject = previousObject._iNext; childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; + previousObject._iNext = childFirst; } else { nextObject = this; - } - + } + if(nextObject) { nextObject._iPrev = childLast; childLast._iNext = nextObject; } - - + + // now insert the end filter block.. - + /* * insert end filter */ @@ -364,21 +408,21 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) var childLast = end var nextObject = null; var previousObject = null; - + previousObject = this.last; nextObject = previousObject._iNext; - + if(nextObject) { nextObject._iPrev = childLast; childLast._iNext = nextObject; } - + childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - + previousObject._iNext = childFirst; + var updateLast = this; - + var prevLast = this.last; while(updateLast) { @@ -388,17 +432,15 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) } updateLast = updateLast.parent; } - + this.first = start; - + // if webGL... if(this.__renderGroup) { this.__renderGroup.addFilterBlocks(start, end); } - - mask.renderable = false; - + } /* @@ -407,34 +449,34 @@ PIXI.DisplayObject.prototype.addFilter = function(mask) * @method removeFilter * @private */ -PIXI.DisplayObject.prototype.removeFilter = function() +PIXI.DisplayObject.prototype.removeFilter = function(data) { - if(!this.filter)return; - this.filter = false; - + //if(!this.filter)return; + //this.filter = false; + console.log("YUOIO") // modify the list.. - var startBlock = this.first; - + var startBlock = data.start; + + var nextObject = startBlock._iNext; var previousObject = startBlock._iPrev; - + if(nextObject)nextObject._iPrev = previousObject; - if(previousObject)previousObject._iNext = nextObject; - + if(previousObject)previousObject._iNext = nextObject; + this.first = startBlock._iNext; - - + // remove the end filter - var lastBlock = this.last; - + var lastBlock = data.end; + var nextObject = lastBlock._iNext; var previousObject = lastBlock._iPrev; - + if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - + previousObject._iNext = nextObject; + // this is always true too! - var tempLast = lastBlock._iPrev; + var tempLast = lastBlock._iPrev; // need to make sure the parents last is updated too var updateLast = this; while(updateLast.last == lastBlock) @@ -443,10 +485,7 @@ PIXI.DisplayObject.prototype.removeFilter = function() updateLast = updateLast.parent; if(!updateLast)break; } - - var mask = startBlock.mask - mask.renderable = true; - + // if webGL... if(this.__renderGroup) { @@ -468,8 +507,8 @@ PIXI.DisplayObject.prototype.updateTransform = function() this.rotationCache = this.rotation; this._sr = Math.sin(this.rotation); this._cr = Math.cos(this.rotation); - } - + } + var localTransform = this.localTransform; var parentTransform = this.parent.worldTransform; var worldTransform = this.worldTransform; @@ -478,12 +517,12 @@ PIXI.DisplayObject.prototype.updateTransform = function() localTransform[1] = -this._sr * this.scale.y localTransform[3] = this._sr * this.scale.x; localTransform[4] = this._cr * this.scale.y; - + // TODO --> do we even need a local matrix??? - + var px = this.pivot.x; var py = this.pivot.y; - + // Cache the matrix values (makes for huge speed increases!) var a00 = localTransform[0], a01 = localTransform[1], a02 = this.position.x - localTransform[0] * px - py * localTransform[1], a10 = localTransform[3], a11 = localTransform[4], a12 = this.position.y - localTransform[4] * py - px * localTransform[3], @@ -493,7 +532,7 @@ PIXI.DisplayObject.prototype.updateTransform = function() localTransform[2] = a02 localTransform[5] = a12 - + worldTransform[0] = b00 * a00 + b01 * a10; worldTransform[1] = b00 * a01 + b01 * a11; worldTransform[2] = b00 * a02 + b01 * a12 + b02; @@ -505,7 +544,7 @@ PIXI.DisplayObject.prototype.updateTransform = function() // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); this.worldAlpha = this.alpha * this.parent.worldAlpha; - + this.vcount = PIXI.visibleCount; } diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index a438b3f..68ba15c 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -7,21 +7,21 @@ * A DisplayObjectContainer represents a collection of display objects. * It is the base class of all display objects that act as a container for other objects. * - * @class DisplayObjectContainer + * @class DisplayObjectContainer * @extends DisplayObject * @constructor */ PIXI.DisplayObjectContainer = function() { PIXI.DisplayObject.call( this ); - + /** * [read-only] The of children of this container. * * @property children * @type Array * @readOnly - */ + */ this.children = []; } @@ -29,18 +29,6 @@ PIXI.DisplayObjectContainer = function() PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; -//TODO make visible a getter setter -/* -Object.defineProperty(PIXI.DisplayObjectContainer.prototype, 'visible', { - get: function() { - return this._visible; - }, - set: function(value) { - this._visible = value; - - } -});*/ - /** * Adds a child to the container. * @@ -51,18 +39,18 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) { if(child.parent != undefined) { - + //// COULD BE THIS??? child.parent.removeChild(child); // return; } child.parent = this; - - this.children.push(child); - + + this.children.push(child); + // update the stage refference.. - + if(this.stage) { var tmpChild = child; @@ -71,20 +59,20 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) if(tmpChild.interactive)this.stage.dirty = true; tmpChild.stage = this.stage; tmpChild = tmpChild._iNext; - } + } while(tmpChild) } - + // LINKED LIST // - + // modify the list.. var childFirst = child.first var childLast = child.last; var nextObject; var previousObject; - + // this could be wrong if there is a filter?? - if(this.filter) + if(this._filters) { previousObject = this.last._iPrev; } @@ -94,12 +82,12 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) } nextObject = previousObject._iNext; - + // always true in this case // need to make sure the parents last is updated too var updateLast = this; var prevLast = previousObject; - + while(updateLast) { if(updateLast.last == prevLast) @@ -108,15 +96,15 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) } updateLast = updateLast.parent; } - + if(nextObject) { nextObject._iPrev = childLast; childLast._iNext = nextObject; } - + childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; + previousObject._iNext = childFirst; // need to remove any render groups.. if(this.__renderGroup) @@ -126,7 +114,7 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) // add them to the new render group.. this.__renderGroup.addDisplayObjectAndChildren(child); } - + } /** @@ -145,7 +133,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) child.parent.removeChild(child); } child.parent = this; - + if(this.stage) { var tmpChild = child; @@ -157,13 +145,13 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) } while(tmpChild) } - + // modify the list.. var childFirst = child.first; var childLast = child.last; var nextObject; var previousObject; - + if(index == this.children.length) { previousObject = this.last; @@ -186,18 +174,18 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) { previousObject = this.children[index-1].last; } - + nextObject = previousObject._iNext; - + // always true in this case if(nextObject) { nextObject._iPrev = childLast; childLast._iNext = nextObject; } - + childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; + previousObject._iNext = childFirst; this.children.splice(index, 0, child); // need to remove any render groups.. @@ -208,7 +196,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) // add them to the new render group.. this.__renderGroup.addDisplayObjectAndChildren(child); } - + } else { @@ -227,21 +215,21 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2) { /* - * this funtion needs to be recoded.. + * this funtion needs to be recoded.. * can be done a lot faster.. */ return; - + // need to fix this function :/ /* // TODO I already know this?? var index = this.children.indexOf( child ); var index2 = this.children.indexOf( child2 ); - - if ( index !== -1 && index2 !== -1 ) + + if ( index !== -1 && index2 !== -1 ) { // cool - + /* if(this.stage) { @@ -249,15 +237,15 @@ PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2) // TODO sure there is a nicer way to achieve this! this.stage.__removeChild(child); this.stage.__removeChild(child2); - + this.stage.__addChild(child); this.stage.__addChild(child2); } - + // swap the positions.. this.children[index] = child2; this.children[index2] = child; - + } else { @@ -292,22 +280,22 @@ PIXI.DisplayObjectContainer.prototype.getChildAt = function(index) PIXI.DisplayObjectContainer.prototype.removeChild = function(child) { var index = this.children.indexOf( child ); - if ( index !== -1 ) + if ( index !== -1 ) { // unlink // // modify the list.. var childFirst = child.first; var childLast = child.last; - + var nextObject = childLast._iNext; var previousObject = childFirst._iPrev; - + if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - + previousObject._iNext = nextObject; + if(this.last == childLast) { - var tempLast = childFirst._iPrev; + var tempLast = childFirst._iPrev; // need to make sure the parents last is updated too var updateLast = this; while(updateLast.last == childLast.last) @@ -317,10 +305,10 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child) if(!updateLast)break; } } - + childLast._iNext = null; childFirst._iPrev = null; - + // update the stage reference.. if(this.stage) { @@ -330,16 +318,16 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child) if(tmpChild.interactive)this.stage.dirty = true; tmpChild.stage = null; tmpChild = tmpChild._iNext; - } + } while(tmpChild) } - + // webGL trim if(child.__renderGroup) { child.__renderGroup.removeDisplayObjectAndChildren(child); } - + child.parent = undefined; this.children.splice( index, 1 ); } @@ -358,11 +346,11 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child) PIXI.DisplayObjectContainer.prototype.updateTransform = function() { if(!this.visible)return; - + PIXI.DisplayObject.prototype.updateTransform.call( this ); - + for(var i=0,j=this.children.length; i 0) { PIXI.Texture.frameUpdates = []; } - - + + } /** @@ -121,7 +121,7 @@ PIXI.CanvasRenderer.prototype.resize = function(width, height) { this.width = width; this.height = height; - + this.view.width = width; this.view.height = height; } @@ -138,50 +138,50 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) // no loger recurrsive! var transform; var context = this.context; - + context.globalCompositeOperation = 'source-over'; - - // one the display object hits this. we can break the loop + + // one the display object hits this. we can break the loop var testObject = displayObject.last._iNext; displayObject = displayObject.first; - - do + + do { transform = displayObject.worldTransform; - + if(!displayObject.visible) { displayObject = displayObject.last._iNext; continue; } - + if(!displayObject.renderable) { displayObject = displayObject._iNext; continue; } - + if(displayObject instanceof PIXI.Sprite) { - + var frame = displayObject.texture.frame; - + if(frame && frame.width && frame.height) { context.globalAlpha = displayObject.worldAlpha; - + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); - - context.drawImage(displayObject.texture.baseTexture.source, + + context.drawImage(displayObject.texture.baseTexture.source, frame.x, frame.y, frame.width, frame.height, - (displayObject.anchor.x) * -frame.width, + (displayObject.anchor.x) * -frame.width, (displayObject.anchor.y) * -frame.height, frame.width, frame.height); - } + } } else if(displayObject instanceof PIXI.Strip) { @@ -204,37 +204,44 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) } else if(displayObject instanceof PIXI.FilterBlock) { - if(displayObject.open) + if(PIXI.FilterBlock.data instanceof PIXI.Graphics) { - context.save(); - - var cacheAlpha = displayObject.mask.alpha; - var maskTransform = displayObject.mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - displayObject.mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); - context.clip(); - - displayObject.mask.worldAlpha = cacheAlpha; + if(displayObject.open) + { + context.save(); + + var cacheAlpha = displayObject.mask.alpha; + var maskTransform = displayObject.mask.worldTransform; + + context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) + + displayObject.mask.worldAlpha = 0.5; + + context.worldAlpha = 0; + + PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); + context.clip(); + + displayObject.mask.worldAlpha = cacheAlpha; + } + else + { + context.restore(); + } } else { - context.restore(); + // only masks supported right now! } } // count++ displayObject = displayObject._iNext; - - + + } while(displayObject != testObject) - + } /** @@ -249,26 +256,26 @@ PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip) var context = this.context; var verticies = strip.verticies; var uvs = strip.uvs; - + var length = verticies.length/2; this.count++; - + context.beginPath(); - for (var i=1; i < length-2; i++) + for (var i=1; i < length-2; i++) { - + // draw some triangles! var index = i*2; - + var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - + context.moveTo(x0, y0); context.lineTo(x1, y1); context.lineTo(x2, y2); - - }; - + + }; + context.fillStyle = "#FF0000"; context.fill(); context.closePath(); @@ -284,26 +291,26 @@ PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip) PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) { var context = this.context; - + context.globalAlpha = sprite.worldAlpha; - + if(!sprite.__tilePattern) sprite.__tilePattern = context.createPattern(sprite.texture.baseTexture.source, "repeat"); - + context.beginPath(); - + var tilePosition = sprite.tilePosition; var tileScale = sprite.tileScale; - + // offset context.scale(tileScale.x,tileScale.y); context.translate(tilePosition.x, tilePosition.y); - + context.fillStyle = sprite.__tilePattern; context.fillRect(-tilePosition.x,-tilePosition.y,sprite.width / tileScale.x, sprite.height / tileScale.y); - + context.scale(1/tileScale.x, 1/tileScale.y); context.translate(-tilePosition.x, -tilePosition.y); - + context.closePath(); } @@ -321,18 +328,18 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) // draw triangles!! var verticies = strip.verticies; var uvs = strip.uvs; - + var length = verticies.length/2; this.count++; - for (var i=1; i < length-2; i++) + for (var i=1; i < length-2; i++) { - + // draw some triangles! var index = i*2; - + var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - + var u0 = uvs[index] * strip.texture.width, u1 = uvs[index+2] * strip.texture.width, u2 = uvs[index+4]* strip.texture.width; var v0 = uvs[index+1]* strip.texture.height, v1 = uvs[index+3] * strip.texture.height, v2 = uvs[index+5]* strip.texture.height; @@ -343,10 +350,10 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) 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 delta_a = x0*v1 + v0*x2 + x1*v2 - v1*x2 - v0*x1 - x0*v2; @@ -355,16 +362,16 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip) var delta_d = y0*v1 + v0*y2 + y1*v2 - v1*y2 - v0*y1 - y0*v2; var delta_e = u0*y1 + y0*u2 + u1*y2 - y1*u2 - y0*u1 - u0*y2; var delta_f = u0*v1*y2 + v0*y1*u2 + y0*u1*v2 - y0*v1*u2 - v0*u1*y2 - u0*y1*v2; - - - - + + + + context.transform(delta_a/delta, delta_d/delta, delta_b/delta, delta_e/delta, delta_c/delta, delta_f/delta); - + context.drawImage(strip.texture.baseTexture.source, 0, 0); context.restore(); }; - + } diff --git a/src/pixi/renderers/webgl/PixiShader.js b/src/pixi/renderers/webgl/PixiShader.js new file mode 100644 index 0000000..97e61a3 --- /dev/null +++ b/src/pixi/renderers/webgl/PixiShader.js @@ -0,0 +1,70 @@ +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.PixiShader = function() +{ + // the webGL program.. + this.program; + + this.fragmentSrc = [ + "precision lowp float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", + "}" + ]; + +} + +PIXI.PixiShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get the default shader bits! + program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); + program.colorAttribute = gl.getAttribLocation(program, "aColor"); + program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); + + program.projectionVector = gl.getUniformLocation(program, "projectionVector"); + program.samplerUniform = gl.getUniformLocation(program, "uSampler"); + + // add those custom shaders! + for (var key in this.uniforms) + { + // get the uniform locations.. + program[key] = gl.getUniformLocation(program, key); + } + + this.program = program; +} + +PIXI.PixiShader.prototype.syncUniforms = function() +{ + var gl = PIXI.gl; + + for (var key in this.uniforms) + { + //var + var type = this.uniforms[key].type; + + // need to grow this! + if(type == "f") + { + gl.uniform1f(this.program[key], this.uniforms[key].value); + } + else if(type == "mat4") + { + gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); + } + } + +} + diff --git a/src/pixi/renderers/webgl/WebGLBatch.js b/src/pixi/renderers/webgl/WebGLBatch.js index 8b6305b..7d6758c 100644 --- a/src/pixi/renderers/webgl/WebGLBatch.js +++ b/src/pixi/renderers/webgl/WebGLBatch.js @@ -24,7 +24,7 @@ PIXI._getBatch = function(gl) */ PIXI._returnBatch = function(batch) { - batch.clean(); + batch.clean(); PIXI._batchs.push(batch); } @@ -33,7 +33,7 @@ PIXI._returnBatch = function(batch) */ PIXI._restoreBatchs = function(gl) { - for (var i=0; i < PIXI._batchs.length; i++) + for (var i=0; i < PIXI._batchs.length; i++) { PIXI._batchs[i].restoreLostContext(gl); }; @@ -54,7 +54,7 @@ PIXI._restoreBatchs = function(gl) PIXI.WebGLBatch = function(gl) { this.gl = gl; - + this.size = 0; this.vertexBuffer = gl.createBuffer(); @@ -108,7 +108,7 @@ PIXI.WebGLBatch.prototype.restoreLostContext = function(gl) * @method init * @param sprite {Sprite} the first sprite to be added to the batch. Only sprites with * the same base texture and blend mode will be allowed to be added to this batch - */ + */ PIXI.WebGLBatch.prototype.init = function(sprite) { sprite.batch = this; @@ -128,7 +128,7 @@ PIXI.WebGLBatch.prototype.init = function(sprite) * @method insertBefore * @param sprite {Sprite} the sprite to be added * @param nextSprite {nextSprite} the first sprite will be inserted before this sprite - */ + */ PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) { this.size++; @@ -156,7 +156,7 @@ PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) * @method insertAfter * @param sprite {Sprite} the sprite to be added * @param previousSprite {Sprite} the first sprite will be inserted after this sprite - */ + */ PIXI.WebGLBatch.prototype.insertAfter = function(sprite, previousSprite) { this.size++; @@ -184,7 +184,7 @@ PIXI.WebGLBatch.prototype.insertAfter = function(sprite, previousSprite) * * @method remove * @param sprite {Sprite} the sprite to be removed - */ + */ PIXI.WebGLBatch.prototype.remove = function(sprite) { this.size--; @@ -268,7 +268,7 @@ PIXI.WebGLBatch.prototype.split = function(sprite) * Merges two batchs together * * @method merge - * @param batch {WebGLBatch} the batch that will be merged + * @param batch {WebGLBatch} the batch that will be merged */ PIXI.WebGLBatch.prototype.merge = function(batch) { @@ -325,10 +325,10 @@ PIXI.WebGLBatch.prototype.growBatch = function() this.dirtyColors = true; - this.indices = new Uint16Array(this.dynamicSize * 6); + this.indices = new Uint16Array(this.dynamicSize * 6); var length = this.indices.length/6; - for (var i=0; i < length; i++) + for (var i=0; i < length; i++) { var index2 = i * 6; var index3 = i * 4; @@ -381,7 +381,7 @@ PIXI.WebGLBatch.prototype.refresh = function() this.uvs[index +3] = frame.y / th; this.uvs[index +4] = (frame.x + frame.width) / tw; - this.uvs[index +5] = (frame.y + frame.height) / th; + this.uvs[index +5] = (frame.y + frame.height) / th; this.uvs[index +6] = frame.x / tw; this.uvs[index +7] = (frame.y + frame.height) / th; @@ -443,17 +443,17 @@ PIXI.WebGLBatch.prototype.update = function() tx = worldTransform[2]; ty = worldTransform[5]; - this.verticies[index + 0 ] = a * w1 + c * h1 + tx; + this.verticies[index + 0 ] = a * w1 + c * h1 + tx; this.verticies[index + 1 ] = d * h1 + b * w1 + ty; - this.verticies[index + 2 ] = a * w0 + c * h1 + tx; - this.verticies[index + 3 ] = d * h1 + b * w0 + ty; + this.verticies[index + 2 ] = a * w0 + c * h1 + tx; + this.verticies[index + 3 ] = d * h1 + b * w0 + ty; - this.verticies[index + 4 ] = a * w0 + c * h0 + tx; - this.verticies[index + 5 ] = d * h0 + b * w0 + ty; + this.verticies[index + 4 ] = a * w0 + c * h0 + tx; + this.verticies[index + 5 ] = d * h0 + b * w0 + ty; - this.verticies[index + 6] = a * w1 + c * h0 + tx; - this.verticies[index + 7] = d * h0 + b * w1 + ty; + this.verticies[index + 6] = a * w1 + c * h0 + tx; + this.verticies[index + 7] = d * h0 + b * w1 + ty; if(displayObject.updateFrame || displayObject.texture.updateFrame) { @@ -472,7 +472,7 @@ PIXI.WebGLBatch.prototype.update = function() this.uvs[index +3] = frame.y / th; this.uvs[index +4] = (frame.x + frame.width) / tw; - this.uvs[index +5] = (frame.y + frame.height) / th; + this.uvs[index +5] = (frame.y + frame.height) / th; this.uvs[index +6] = frame.x / tw; this.uvs[index +7] = (frame.y + frame.height) / th; @@ -522,7 +522,7 @@ PIXI.WebGLBatch.prototype.render = function(start, end) start = start || 0; if(end == undefined)end = this.size; - + if(this.dirty) { this.refresh(); @@ -536,8 +536,9 @@ PIXI.WebGLBatch.prototype.render = function(start, end) //TODO optimize this! - var shaderProgram = PIXI.shaderProgram; - gl.useProgram(shaderProgram); + var shaderProgram = PIXI.currentShader; + + //gl.useProgram(shaderProgram); // update the verts.. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); @@ -545,6 +546,8 @@ PIXI.WebGLBatch.prototype.render = function(start, end) gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // update the uvs + var isDefault = (shaderProgram == PIXI.shaderProgram) + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); if(this.dirtyUVS) @@ -568,7 +571,6 @@ PIXI.WebGLBatch.prototype.render = function(start, end) } gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); diff --git a/src/pixi/renderers/webgl/WebGLGraphics.js b/src/pixi/renderers/webgl/WebGLGraphics.js index 87d98be..55e9661 100644 --- a/src/pixi/renderers/webgl/WebGLGraphics.js +++ b/src/pixi/renderers/webgl/WebGLGraphics.js @@ -9,7 +9,7 @@ */ PIXI.WebGLGraphics = function() { - + } /** @@ -24,62 +24,64 @@ PIXI.WebGLGraphics = function() PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) { var gl = PIXI.gl; - - if(!graphics._webGL)graphics._webGL = {points:[], indices:[], lastIndex:0, + + if(!graphics._webGL)graphics._webGL = {points:[], indices:[], lastIndex:0, buffer:gl.createBuffer(), indexBuffer:gl.createBuffer()}; - + if(graphics.dirty) { graphics.dirty = false; - + if(graphics.clearDirty) { graphics.clearDirty = false; - + graphics._webGL.lastIndex = 0; graphics._webGL.points = []; graphics._webGL.indices = []; - + } - + PIXI.WebGLGraphics.updateGraphics(graphics); } - - + + PIXI.activatePrimitiveShader(); - + // This could be speeded up fo sure! var m = PIXI.mat3.clone(graphics.worldTransform); - + PIXI.mat3.transpose(m); - - // set the matrix transform for the + + // set the matrix transform for the gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - + gl.uniformMatrix3fv(PIXI.primitiveProgram.translationMatrix, false, m); - + gl.uniform2f(PIXI.primitiveProgram.projectionVector, projection.x, projection.y); - + gl.uniform1f(PIXI.primitiveProgram.alpha, graphics.worldAlpha); gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - + // WHY DOES THIS LINE NEED TO BE THERE??? - gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); // its not even used.. but need to be set or it breaks? // only on pc though.. - + gl.vertexAttribPointer(PIXI.primitiveProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 4 * 6, 0); gl.vertexAttribPointer(PIXI.primitiveProgram.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4); - + // set the index buffer! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); - + gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); - + + PIXI.deactivatePrimitiveShader(); + // return to default shader... - PIXI.activateDefaultShader(); +// PIXI.activateShader(PIXI.defaultShader); } /** @@ -92,18 +94,18 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) */ PIXI.WebGLGraphics.updateGraphics = function(graphics) { - for (var i=graphics._webGL.lastIndex; i < graphics.graphicsData.length; i++) + for (var i=graphics._webGL.lastIndex; i < graphics.graphicsData.length; i++) { var data = graphics.graphicsData[i]; - + if(data.type == PIXI.Graphics.POLY) { if(data.fill) { - if(data.points.length>3) + if(data.points.length>3) PIXI.WebGLGraphics.buildPoly(data, graphics._webGL); } - + if(data.lineWidth > 0) { PIXI.WebGLGraphics.buildLine(data, graphics._webGL); @@ -118,18 +120,18 @@ PIXI.WebGLGraphics.updateGraphics = function(graphics) PIXI.WebGLGraphics.buildCircle(data, graphics._webGL); } }; - + graphics._webGL.lastIndex = graphics.graphicsData.length; - + var gl = PIXI.gl; graphics._webGL.glPoints = new Float32Array(graphics._webGL.points); - + gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); gl.bufferData(gl.ARRAY_BUFFER, graphics._webGL.glPoints, gl.STATIC_DRAW); - + graphics._webGL.glIndicies = new Uint16Array(graphics._webGL.indices); - + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.glIndicies, gl.STATIC_DRAW); } @@ -147,45 +149,45 @@ PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData) { // --- // // need to convert points to a nice regular data - // + // var rectData = graphicsData.points; var x = rectData[0]; var y = rectData[1]; var width = rectData[2]; var height = rectData[3]; - - + + if(graphicsData.fill) { var color = HEXtoRGB(graphicsData.fillColor); var alpha = graphicsData.fillAlpha; - + var r = color[0] * alpha; var g = color[1] * alpha; var b = color[2] * alpha; - + var verts = webGLData.points; var indices = webGLData.indices; - + var vertPos = verts.length/6; - + // start verts.push(x, y); verts.push(r, g, b, alpha); - + verts.push(x + width, y); verts.push(r, g, b, alpha); - + verts.push(x , y + height); verts.push(r, g, b, alpha); - + verts.push(x + width, y + height); verts.push(r, g, b, alpha); - + // insert 2 dead triangles.. indices.push(vertPos, vertPos, vertPos+1, vertPos+2, vertPos+3, vertPos+3) } - + if(graphicsData.lineWidth) { graphicsData.points = [x, y, @@ -193,10 +195,10 @@ PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData) x + width, y + height, x, y + height, x, y]; - + PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); } - + } /** @@ -212,16 +214,16 @@ PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData) { // --- // // need to convert points to a nice regular data - // + // var rectData = graphicsData.points; var x = rectData[0]; var y = rectData[1]; var width = rectData[2]; var height = rectData[3]; - + var totalSegs = 40; var seg = (Math.PI * 2) / totalSegs ; - + if(graphicsData.fill) { var color = HEXtoRGB(graphicsData.fillColor); @@ -230,41 +232,41 @@ PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData) var r = color[0] * alpha; var g = color[1] * alpha; var b = color[2] * alpha; - + var verts = webGLData.points; var indices = webGLData.indices; - + var vecPos = verts.length/6; - + indices.push(vecPos); - - for (var i=0; i < totalSegs + 1 ; i++) + + for (var i=0; i < totalSegs + 1 ; i++) { verts.push(x,y, r, g, b, alpha); - + verts.push(x + Math.sin(seg * i) * width, y + Math.cos(seg * i) * height, r, g, b, alpha); - + indices.push(vecPos++, vecPos++); }; - + indices.push(vecPos-1); } - + if(graphicsData.lineWidth) { graphicsData.points = []; - - for (var i=0; i < totalSegs + 1; i++) + + for (var i=0; i < totalSegs + 1; i++) { graphicsData.points.push(x + Math.sin(seg * i) * width, y + Math.cos(seg * i) * height) }; - + PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); } - + } /** @@ -279,89 +281,89 @@ PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData) PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) { // TODO OPTIMISE! - + var wrap = true; var points = graphicsData.points; if(points.length == 0)return; - + // get first and last point.. figure out the middle! var firstPoint = new PIXI.Point( points[0], points[1] ); var lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - + // if the first point is the last point - goona have issues :) if(firstPoint.x == lastPoint.x && firstPoint.y == lastPoint.y) { points.pop(); points.pop(); - + lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - + var midPointX = lastPoint.x + (firstPoint.x - lastPoint.x) *0.5; var midPointY = lastPoint.y + (firstPoint.y - lastPoint.y) *0.5; - + points.unshift(midPointX, midPointY); points.push(midPointX, midPointY) } - + var verts = webGLData.points; var indices = webGLData.indices; var length = points.length / 2; var indexCount = points.length; var indexStart = verts.length/6; - + // DRAW the Line var width = graphicsData.lineWidth / 2; - + // sort color var color = HEXtoRGB(graphicsData.lineColor); var alpha = graphicsData.lineAlpha; var r = color[0] * alpha; var g = color[1] * alpha; var b = color[2] * alpha; - + var p1x, p1y, p2x, p2y, p3x, p3y; var perpx, perpy, perp2x, perp2y, perp3x, perp3y; var ipx, ipy; var a1, b1, c1, a2, b2, c2; var denom, pdist, dist; - + p1x = points[0]; p1y = points[1]; - + p2x = points[2]; p2y = points[3]; - + perpx = -(p1y - p2y); perpy = p1x - p2x; - + dist = Math.sqrt(perpx*perpx + perpy*perpy); - + perpx /= dist; perpy /= dist; perpx *= width; perpy *= width; - + // start verts.push(p1x - perpx , p1y - perpy, r, g, b, alpha); - + verts.push(p1x + perpx , p1y + perpy, r, g, b, alpha); - - for (var i = 1; i < length-1; i++) + + for (var i = 1; i < length-1; i++) { p1x = points[(i-1)*2]; p1y = points[(i-1)*2 + 1]; - + p2x = points[(i)*2] p2y = points[(i)*2 + 1] - + p3x = points[(i+1)*2]; p3y = points[(i+1)*2 + 1]; - + perpx = -(p1y - p2y); perpy = p1x - p2x; - + dist = Math.sqrt(perpx*perpx + perpy*perpy); perpx /= dist; perpy /= dist; @@ -370,91 +372,91 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) perp2x = -(p2y - p3y); perp2y = p2x - p3x; - + dist = Math.sqrt(perp2x*perp2x + perp2y*perp2y); perp2x /= dist; perp2y /= dist; perp2x *= width; perp2y *= width; - + a1 = (-perpy + p1y) - (-perpy + p2y); b1 = (-perpx + p2x) - (-perpx + p1x); c1 = (-perpx + p1x) * (-perpy + p2y) - (-perpx + p2x) * (-perpy + p1y); a2 = (-perp2y + p3y) - (-perp2y + p2y); b2 = (-perp2x + p2x) - (-perp2x + p3x); c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y); - + denom = a1*b2 - a2*b1; - + if (denom == 0) { denom+=1; } - + px = (b1*c2 - b2*c1)/denom; py = (a2*c1 - a1*c2)/denom; - + pdist = (px -p2x) * (px -p2x) + (py -p2y) + (py -p2y); - + if(pdist > 140 * 140) { perp3x = perpx - perp2x; perp3y = perpy - perp2y; - + dist = Math.sqrt(perp3x*perp3x + perp3y*perp3y); perp3x /= dist; perp3y /= dist; perp3x *= width; perp3y *= width; - + verts.push(p2x - perp3x, p2y -perp3y); verts.push(r, g, b, alpha); - + verts.push(p2x + perp3x, p2y +perp3y); verts.push(r, g, b, alpha); - + verts.push(p2x - perp3x, p2y -perp3y); verts.push(r, g, b, alpha); - + indexCount++; } else { verts.push(px , py); verts.push(r, g, b, alpha); - + verts.push(p2x - (px-p2x), p2y - (py - p2y)); verts.push(r, g, b, alpha); } } - + p1x = points[(length-2)*2] - p1y = points[(length-2)*2 + 1] - + p1y = points[(length-2)*2 + 1] + p2x = points[(length-1)*2] p2y = points[(length-1)*2 + 1] - + perpx = -(p1y - p2y) perpy = p1x - p2x; - + dist = Math.sqrt(perpx*perpx + perpy*perpy); perpx /= dist; perpy /= dist; perpx *= width; perpy *= width; - + verts.push(p2x - perpx , p2y - perpy) verts.push(r, g, b, alpha); - + verts.push(p2x + perpx , p2y + perpy) verts.push(r, g, b, alpha); - + indices.push(indexStart); - - for (var i=0; i < indexCount; i++) + + for (var i=0; i < indexCount; i++) { indices.push(indexStart++); }; - + indices.push(indexStart-1); } @@ -471,25 +473,25 @@ PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData) { var points = graphicsData.points; if(points.length < 6)return; - + // get first and last point.. figure out the middle! var verts = webGLData.points; var indices = webGLData.indices; - + var length = points.length / 2; - + // sort color var color = HEXtoRGB(graphicsData.fillColor); var alpha = graphicsData.fillAlpha; var r = color[0] * alpha; var g = color[1] * alpha; var b = color[2] * alpha; - + var triangles = PIXI.PolyK.Triangulate(points); - + var vertPos = verts.length / 6; - - for (var i=0; i < triangles.length; i+=3) + + for (var i=0; i < triangles.length; i+=3) { indices.push(triangles[i] + vertPos); indices.push(triangles[i] + vertPos); @@ -497,8 +499,8 @@ PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData) indices.push(triangles[i+2] +vertPos); indices.push(triangles[i+2] + vertPos); }; - - for (var i = 0; i < length; i++) + + for (var i = 0; i < length; i++) { verts.push(points[i * 2], points[i * 2 + 1], r, g, b, alpha); diff --git a/src/pixi/renderers/webgl/WebGLRenderGroup.js b/src/pixi/renderers/webgl/WebGLRenderGroup.js index a6507cf..f661a96 100644 --- a/src/pixi/renderers/webgl/WebGLRenderGroup.js +++ b/src/pixi/renderers/webgl/WebGLRenderGroup.js @@ -19,7 +19,7 @@ PIXI.WebGLRenderGroup = function(gl) { this.gl = gl; this.root; - + this.backgroundColor; this.batchs = []; this.toRemove = []; @@ -33,18 +33,18 @@ PIXI.WebGLRenderGroup.prototype.constructor = PIXI.WebGLRenderGroup; * * @method setRenderable * @param displayObject {DisplayObject} - * @private + * @private */ PIXI.WebGLRenderGroup.prototype.setRenderable = function(displayObject) { // has this changed?? if(this.root)this.removeDisplayObjectAndChildren(this.root); - + displayObject.worldVisible = displayObject.visible; - + // soooooo // // to check if any batchs exist already?? - + // TODO what if its already has an object? should remove it this.root = displayObject; this.addDisplayObjectAndChildren(displayObject); @@ -59,26 +59,24 @@ PIXI.WebGLRenderGroup.prototype.setRenderable = function(displayObject) PIXI.WebGLRenderGroup.prototype.render = function(projection) { PIXI.WebGLRenderer.updateTextures(); - + var gl = this.gl; - - - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); + + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - // will render all the elements in the group var renderable; - - for (var i=0; i < this.batchs.length; i++) + for (var i=0; i < this.batchs.length; i++) { - + renderable = this.batchs[i]; if(renderable instanceof PIXI.WebGLBatch) { this.batchs[i].render(); continue; } - + // non sprite batch.. var worldVisible = renderable.vcount === PIXI.visibleCount; @@ -96,42 +94,10 @@ PIXI.WebGLRenderGroup.prototype.render = function(projection) } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ - if(renderable.open) - { - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - else - { - gl.disable(gl.STENCIL_TEST); - } + this.handleFilterBlock(renderable, projection); } } - -} - -/** - * Renders the stage to its webgl view - * - * @method handleFilter - * @param filter {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.handleFilter = function(filter, projection) -{ - + } /** @@ -145,20 +111,19 @@ PIXI.WebGLRenderGroup.prototype.handleFilter = function(filter, projection) PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection) { PIXI.WebGLRenderer.updateTextures(); - + var gl = this.gl; - - gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y); - + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + // to do! // render part of the scene... - + var startIndex; var startBatchIndex; - + var endIndex; var endBatchIndex; - + /* * LOOK FOR THE NEXT SPRITE * This part looks for the closest next sprite that can go into a batch @@ -172,14 +137,14 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project if(nextRenderable.renderable && nextRenderable.__renderGroup)break; } var startBatch = nextRenderable.batch; - + if(nextRenderable instanceof PIXI.Sprite) { startBatch = nextRenderable.batch; - + var head = startBatch.head; var next = head; - + // ok now we have the batch.. need to find the start index! if(head == nextRenderable) { @@ -188,7 +153,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project else { startIndex = 1; - + while(head.__next != nextRenderable) { startIndex++; @@ -200,7 +165,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project { startBatch = nextRenderable; } - + // Get the LAST renderable object var lastRenderable = displayObject; var endBatch; @@ -208,15 +173,15 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project while(lastItem.children.length > 0) { lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem; + if(lastItem.renderable)lastRenderable = lastItem.last; } - + if(lastRenderable instanceof PIXI.Sprite) { endBatch = lastRenderable.batch; - + var head = endBatch.head; - + if(head == lastRenderable) { endIndex = 0; @@ -224,7 +189,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project else { endIndex = 1; - + while(head.__next != lastRenderable) { endIndex++; @@ -236,9 +201,9 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project { endBatch = lastRenderable; } - + // TODO - need to fold this up a bit! - + if(startBatch == endBatch) { if(startBatch instanceof PIXI.WebGLBatch) @@ -251,11 +216,11 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project } return; } - + // now we have first and last! startBatchIndex = this.batchs.indexOf(startBatch); endBatchIndex = this.batchs.indexOf(endBatch); - + // DO the first batch if(startBatch instanceof PIXI.WebGLBatch) { @@ -265,12 +230,12 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project { this.renderSpecial(startBatch, projection); } - + // DO the middle batchs.. - for (var i=startBatchIndex+1; i < endBatchIndex; i++) + for (var i=startBatchIndex+1; i < endBatchIndex; i++) { renderable = this.batchs[i]; - + if(renderable instanceof PIXI.WebGLBatch) { this.batchs[i].render(); @@ -280,7 +245,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project this.renderSpecial(renderable, projection); } } - + // DO the last batch.. if(endBatch instanceof PIXI.WebGLBatch) { @@ -302,6 +267,8 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project */ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) { + var sta = PIXI.shaderStack.length; + var worldVisible = renderable.vcount === PIXI.visibleCount if(renderable instanceof PIXI.TilingSprite) @@ -322,27 +289,58 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) } else if(renderable instanceof PIXI.FilterBlock) { - /* - * for now only masks are supported.. - */ + this.handleFilterBlock(renderable, projection); + } +} - var gl = PIXI.gl; +PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) +{ + /* + * for now only masks are supported.. + */ + var gl = PIXI.gl; - if(renderable.open) + if(renderable.open) + { + if(renderable.data instanceof Array) + { + var filter = renderable.data[0]; + + if(!filter.shader) + { + var shader = new PIXI.PixiShader(); + + shader.fragmentSrc = filter.fragmentSrc; + shader.uniforms = filter.uniforms; + shader.init(); + + filter.shader = shader + } + + PIXI.activateShader(filter.shader); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } + else { gl.enable(gl.STENCIL_TEST); - + gl.colorMask(false, false, false, false); gl.stencilFunc(gl.ALWAYS,1,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - - PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection); - - // we know this is a render texture so enable alpha too.. + PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); + gl.colorMask(true, true, true, true); gl.stencilFunc(gl.NOTEQUAL,0,0xff); gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); } + } + else + { + if(renderable.data instanceof Array) + { + PIXI.popShader(); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } else { gl.disable(gl.STENCIL_TEST); @@ -359,11 +357,11 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) */ PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject) { - + // TODO definitely can optimse this function.. - + this.removeObject(displayObject); - + /* * LOOK FOR THE PREVIOUS RENDERABLE * This part looks for the closest previous sprite that can go into a batch @@ -375,7 +373,7 @@ PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject) previousRenderable = previousRenderable._iPrev; if(previousRenderable.renderable && previousRenderable.__renderGroup)break; } - + /* * LOOK FOR THE NEXT SPRITE * This part looks for the closest next sprite that can go into a batch @@ -388,7 +386,7 @@ PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject) nextRenderable = nextRenderable._iNext; if(nextRenderable.renderable && nextRenderable.__renderGroup)break; } - + this.insertObject(displayObject, previousRenderable, nextRenderable); } @@ -410,13 +408,13 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * It keeps going back until it finds a sprite or the stage */ var previousRenderable = start; - while(previousRenderable != this.root) + while(previousRenderable != this.root.first) { previousRenderable = previousRenderable._iPrev; if(previousRenderable.renderable && previousRenderable.__renderGroup)break; } this.insertAfter(start, previousRenderable); - + /* * LOOK FOR THE NEXT SPRITE * This part looks for the closest next sprite that can go into a batch @@ -424,7 +422,7 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) * scene graph */ var previousRenderable2 = end; - while(previousRenderable2 != this.root) + while(previousRenderable2 != this.root.first) { previousRenderable2 = previousRenderable2._iPrev; if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; @@ -456,20 +454,20 @@ PIXI.WebGLRenderGroup.prototype.removeFilterBlocks = function(start, end) PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayObject) { if(displayObject.__renderGroup)displayObject.__renderGroup.removeDisplayObjectAndChildren(displayObject); - + /* * LOOK FOR THE PREVIOUS RENDERABLE * This part looks for the closest previous sprite that can go into a batch * It keeps going back until it finds a sprite or the stage */ - + var previousRenderable = displayObject.first; while(previousRenderable != this.root.first) { previousRenderable = previousRenderable._iPrev; if(previousRenderable.renderable && previousRenderable.__renderGroup)break; } - + /* * LOOK FOR THE NEXT SPRITE * This part looks for the closest next sprite that can go into a batch @@ -482,22 +480,22 @@ PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayOb nextRenderable = nextRenderable._iNext; if(nextRenderable.renderable && nextRenderable.__renderGroup)break; } - - // one the display object hits this. we can break the loop - + + // one the display object hits this. we can break the loop + var tempObject = displayObject.first; var testObject = displayObject.last._iNext; - do + do { tempObject.__renderGroup = this; - + if(tempObject.renderable) { - + this.insertObject(tempObject, previousRenderable, nextRenderable); previousRenderable = tempObject; } - + tempObject = tempObject._iNext; } while(tempObject != testObject) @@ -513,10 +511,10 @@ PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayOb PIXI.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren = function(displayObject) { if(displayObject.__renderGroup != this)return; - + // var displayObject = displayObject.first; var lastObject = displayObject.last; - do + do { displayObject.__renderGroup = null; if(displayObject.renderable)this.removeObject(displayObject); @@ -539,16 +537,16 @@ PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousO // while looping below THE OBJECT MAY NOT HAVE BEEN ADDED var previousSprite = previousObject; var nextSprite = nextObject; - + /* * so now we have the next renderable and the previous renderable - * + * */ if(displayObject instanceof PIXI.Sprite) { var previousBatch var nextBatch - + if(previousSprite instanceof PIXI.Sprite) { previousBatch = previousSprite.batch; @@ -566,13 +564,13 @@ PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousO // TODO reword! previousBatch = previousSprite; } - + if(nextSprite) { if(nextSprite instanceof PIXI.Sprite) { nextBatch = nextSprite.batch; - + //batch may not exist if item was added to the display list but not to the webGL if(nextBatch) { @@ -588,18 +586,18 @@ PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousO // THERE IS A SPLIT IN THIS BATCH! // var splitBatch = previousBatch.split(nextSprite); // COOL! - // add it back into the array + // add it back into the array /* * OOPS! * seems the new sprite is in the middle of a batch - * lets split it.. + * lets split it.. */ var batch = PIXI.WebGLRenderer.getBatch(); var index = this.batchs.indexOf( previousBatch ); batch.init(displayObject); this.batchs.splice(index+1, 0, batch, splitBatch); - + return; } } @@ -608,21 +606,21 @@ PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousO else { // TODO re-word! - + nextBatch = nextSprite; } } - + /* * looks like it does not belong to any batch! * but is also not intersecting one.. * time to create anew one! */ - + var batch = PIXI.WebGLRenderer.getBatch(); batch.init(displayObject); - if(previousBatch) // if this is invalid it means + if(previousBatch) // if this is invalid it means { var index = this.batchs.indexOf( previousBatch ); this.batchs.splice(index+1, 0, batch); @@ -631,16 +629,16 @@ PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousO { this.batchs.push(batch); } - + return; } else if(displayObject instanceof PIXI.TilingSprite) { - + // add to a batch!! this.initTilingSprite(displayObject); // this.batchs.push(displayObject); - + } else if(displayObject instanceof PIXI.Strip) { @@ -651,14 +649,14 @@ PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousO else if(displayObject)// instanceof PIXI.Graphics) { //displayObject.initWebGL(this); - + // add to a batch!! //this.initStrip(displayObject); //this.batchs.push(displayObject); } - + this.insertAfter(displayObject, previousSprite); - + // insert and SPLIT! } @@ -676,31 +674,31 @@ PIXI.WebGLRenderGroup.prototype.insertAfter = function(item, displayObject) if(displayObject instanceof PIXI.Sprite) { var previousBatch = displayObject.batch; - + if(previousBatch) { // so this object is in a batch! - + // is it not? need to split the batch if(previousBatch.tail == displayObject) { - // is it tail? insert in to batchs + // is it tail? insert in to batchs var index = this.batchs.indexOf( previousBatch ); this.batchs.splice(index+1, 0, item); } else { // TODO MODIFY ADD / REMOVE CHILD TO ACCOUNT FOR FILTERS (also get prev and next) // - + // THERE IS A SPLIT IN THIS BATCH! // var splitBatch = previousBatch.split(displayObject.__next); - + // COOL! - // add it back into the array + // add it back into the array /* * OOPS! * seems the new sprite is in the middle of a batch - * lets split it.. + * lets split it.. */ var index = this.batchs.indexOf( previousBatch ); this.batchs.splice(index+1, 0, item, splitBatch); @@ -729,25 +727,25 @@ PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) { // loop through children.. // display object // - + // add a child from the render group.. // remove it and all its children! //displayObject.cacheVisible = false;//displayObject.visible; /* * removing is a lot quicker.. - * + * */ var batchToRemove; - + if(displayObject instanceof PIXI.Sprite) { // should always have a batch! var batch = displayObject.batch; if(!batch)return; // this means the display list has been altered befre rendering - + batch.remove(displayObject); - + if(batch.size==0) { batchToRemove = batch; @@ -757,15 +755,15 @@ PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) { batchToRemove = displayObject; } - + /* * Looks like there is somthing that needs removing! */ - if(batchToRemove) + if(batchToRemove) { var index = this.batchs.indexOf( batchToRemove ); if(index == -1)return;// this means it was added then removed before rendered - + // ok so.. check to see if you adjacent batchs should be joined. // TODO may optimise? if(index == 0 || index == this.batchs.length-1) @@ -773,29 +771,30 @@ PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) // wha - eva! just get of the empty batch! this.batchs.splice(index, 1); if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - + return; } - + if(this.batchs[index-1] instanceof PIXI.WebGLBatch && this.batchs[index+1] instanceof PIXI.WebGLBatch) { if(this.batchs[index-1].texture == this.batchs[index+1].texture && this.batchs[index-1].blendMode == this.batchs[index+1].blendMode) { //console.log("MERGE") this.batchs[index-1].merge(this.batchs[index+1]); - + if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); PIXI.WebGLRenderer.returnBatch(this.batchs[index+1]); this.batchs.splice(index, 2); return; } } - + this.batchs.splice(index, 1); if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); } } + /** * Initializes a tiling sprite * @@ -808,26 +807,26 @@ PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) var gl = this.gl; // make the texture tilable.. - + sprite.verticies = new Float32Array([0, 0, sprite.width, 0, sprite.width, sprite.height, 0, sprite.height]); - + sprite.uvs = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]); - + sprite.colors = new Float32Array([1,1,1,1]); - + sprite.indices = new Uint16Array([0, 1, 3,2])//, 2]); - + sprite._vertexBuffer = gl.createBuffer(); sprite._indexBuffer = gl.createBuffer(); sprite._uvBuffer = gl.createBuffer(); sprite._colorBuffer = gl.createBuffer(); - + gl.bindBuffer(gl.ARRAY_BUFFER, sprite._vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, sprite.verticies, gl.STATIC_DRAW); @@ -839,7 +838,7 @@ PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sprite._indexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sprite.indices, gl.STATIC_DRAW); - + // return ( (x > 0) && ((x & (x - 1)) == 0) ); if(sprite.texture.baseTexture._glTexture) @@ -866,23 +865,19 @@ PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) { var gl = this.gl; - var shaderProgram = PIXI.shaderProgram; -// mat - //var mat4Real = PIXI.mat3.toMat4(strip.worldTransform); - //PIXI.mat4.transpose(mat4Real); - //PIXI.mat4.multiply(projectionMatrix, mat4Real, mat4Real ) - - - gl.useProgram(PIXI.stripShaderProgram); + var shaderProgram = PIXI.stripShaderProgram; + + + gl.useProgram(shaderProgram); var m = PIXI.mat3.clone(strip.worldTransform); - + PIXI.mat3.transpose(m); - - // set the matrix transform for the - gl.uniformMatrix3fv(PIXI.stripShaderProgram.translationMatrix, false, m); - gl.uniform2f(PIXI.stripShaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(PIXI.stripShaderProgram.alpha, strip.worldAlpha); + + // set the matrix transform for the + gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); + gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); /* if(strip.blendMode == PIXI.blendModes.NORMAL) @@ -894,25 +889,25 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR); } */ - - + + if(!strip.dirty) { - + gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); gl.bufferSubData(gl.ARRAY_BUFFER, 0, strip.verticies) gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - + // update the uvs gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - + gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - + gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - + // dont need to upload! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); } @@ -922,29 +917,28 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.STATIC_DRAW) gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - + // update the uvs gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW) gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - + gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - + gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW) gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - + // dont need to upload! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); - + } - //console.log(gl.TRIANGLE_STRIP); - + gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - - gl.useProgram(PIXI.shaderProgram); + + gl.useProgram(PIXI.currentProgram); } /** @@ -959,31 +953,31 @@ PIXI.WebGLRenderGroup.prototype.renderTilingSprite = function(sprite, projection { var gl = this.gl; var shaderProgram = PIXI.shaderProgram; - + var tilePosition = sprite.tilePosition; var tileScale = sprite.tileScale; - + var offsetX = tilePosition.x/sprite.texture.baseTexture.width; var offsetY = tilePosition.y/sprite.texture.baseTexture.height; - + var scaleX = (sprite.width / sprite.texture.baseTexture.width) / tileScale.x; var scaleY = (sprite.height / sprite.texture.baseTexture.height) / tileScale.y; sprite.uvs[0] = 0 - offsetX; sprite.uvs[1] = 0 - offsetY; - + sprite.uvs[2] = (1 * scaleX) -offsetX; sprite.uvs[3] = 0 - offsetY; - + sprite.uvs[4] = (1 *scaleX) - offsetX; sprite.uvs[5] = (1 *scaleY) - offsetY; - + sprite.uvs[6] = 0 - offsetX; sprite.uvs[7] = (1 *scaleY) - offsetY; - + gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); gl.bufferSubData(gl.ARRAY_BUFFER, 0, sprite.uvs) - + this.renderStrip(sprite, projectionMatrix); } @@ -999,12 +993,12 @@ PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) // build the strip! var gl = this.gl; var shaderProgram = this.shaderProgram; - + strip._vertexBuffer = gl.createBuffer(); strip._indexBuffer = gl.createBuffer(); strip._uvBuffer = gl.createBuffer(); strip._colorBuffer = gl.createBuffer(); - + gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.DYNAMIC_DRAW); @@ -1014,7 +1008,8 @@ PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW); - + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); } + diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js index ad88e5b..84b5c89 100644 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ b/src/pixi/renderers/webgl/WebGLRenderer.js @@ -21,7 +21,7 @@ PIXI.gl; * @param view {Canvas} the canvas to use as a view, optional * @param transparent=false {Boolean} the transparency of the render view, default false * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) - * + * */ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) { @@ -32,36 +32,37 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) this.width = width || 800; this.height = height || 600; - this.view = view || document.createElement( 'canvas' ); + this.view = view || document.createElement( 'canvas' ); this.view.width = this.width; this.view.height = this.height; - // deal with losing context.. + // deal with losing context.. var scope = this; this.view.addEventListener('webglcontextlost', function(event) { scope.handleContextLost(event); }, false) this.view.addEventListener('webglcontextrestored', function(event) { scope.handleContextRestored(event); }, false) this.batchs = []; - try + try { - PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { + PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { alpha: this.transparent, antialias:!!antialias, // SPEED UP?? premultipliedAlpha:false, stencil:true }); - } - catch (e) + } + catch (e) { throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); } - PIXI.initPrimitiveShader(); PIXI.initDefaultShader(); + PIXI.initPrimitiveShader(); PIXI.initDefaultStripShader(); - PIXI.activateDefaultShader(); + +// PIXI.activateDefaultShader(); var gl = this.gl; PIXI.WebGLRenderer.gl = gl; @@ -71,14 +72,17 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) gl.disable(gl.CULL_FACE); gl.enable(gl.BLEND); - gl.colorMask(true, true, true, this.transparent); + gl.colorMask(true, true, true, this.transparent); PIXI.projection = new PIXI.Point(400, 300); this.resize(this.width, this.height); this.contextLost = false; + PIXI.activateShader(PIXI.defaultShader); + this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); + } // constructor @@ -90,7 +94,7 @@ PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; * @static * @method getBatch * @return {WebGLBatch} - * @private + * @private */ PIXI.WebGLRenderer.getBatch = function() { @@ -114,7 +118,7 @@ PIXI.WebGLRenderer.getBatch = function() */ PIXI.WebGLRenderer.returnBatch = function(batch) { - batch.clean(); + batch.clean(); PIXI._batchs.push(batch); } @@ -127,8 +131,8 @@ PIXI.WebGLRenderer.returnBatch = function(batch) PIXI.WebGLRenderer.prototype.render = function(stage) { if(this.contextLost)return; - - + + // if rendering a new stage clear the batchs.. if(this.__stage !== stage) { @@ -137,8 +141,8 @@ PIXI.WebGLRenderer.prototype.render = function(stage) this.__stage = stage; this.stageRenderGroup.setRenderable(stage); } - - // TODO not needed now... + + // TODO not needed now... // update children if need be // best to remove first! /*for (var i=0; i < stage.__childrenRemoved.length; i++) @@ -147,29 +151,29 @@ PIXI.WebGLRenderer.prototype.render = function(stage) if(group)group.removeDisplayObject(stage.__childrenRemoved[i]); }*/ - // update any textures + // update any textures PIXI.WebGLRenderer.updateTextures(); - - // update the scene graph + + // update the scene graph PIXI.visibleCount++; stage.updateTransform(); - + var gl = this.gl; - + // -- Does this need to be set every frame? -- // - gl.colorMask(true, true, true, this.transparent); - gl.viewport(0, 0, this.width, this.height); - + gl.colorMask(true, true, true, this.transparent); + gl.viewport(0, 0, this.width, this.height); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); + + gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); gl.clear(gl.COLOR_BUFFER_BIT); // HACK TO TEST - + this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; this.stageRenderGroup.render(PIXI.projection); - + // interaction // run interaction! if(stage.interactive) @@ -181,15 +185,15 @@ PIXI.WebGLRenderer.prototype.render = function(stage) stage.interactionManager.setTarget(this); } } - + // after rendering lets confirm all frames that have been uodated.. if(PIXI.Texture.frameUpdates.length > 0) { - for (var i=0; i < PIXI.Texture.frameUpdates.length; i++) + for (var i=0; i < PIXI.Texture.frameUpdates.length; i++) { PIXI.Texture.frameUpdates[i].updateFrame = false; }; - + PIXI.Texture.frameUpdates = []; } } @@ -222,7 +226,7 @@ PIXI.WebGLRenderer.updateTexture = function(texture) { //TODO break this out into a texture manager... var gl = PIXI.gl; - + if(!texture._glTexture) { texture._glTexture = gl.createTexture(); @@ -288,7 +292,7 @@ PIXI.WebGLRenderer.prototype.resize = function(width, height) this.view.width = width; this.view.height = height; - this.gl.viewport(0, 0, this.width, this.height); + this.gl.viewport(0, 0, this.width, this.height); //var projectionMatrix = this.projectionMatrix; @@ -323,20 +327,20 @@ PIXI.WebGLRenderer.prototype.handleContextLost = function(event) */ PIXI.WebGLRenderer.prototype.handleContextRestored = function(event) { - this.gl = this.view.getContext("experimental-webgl", { + this.gl = this.view.getContext("experimental-webgl", { alpha: true }); - this.initShaders(); + this.initShaders(); - for(var key in PIXI.TextureCache) + for(var key in PIXI.TextureCache) { var texture = PIXI.TextureCache[key].baseTexture; texture._glTexture = null; PIXI.WebGLRenderer.updateTexture(texture); }; - for (var i=0; i < this.batchs.length; i++) + for (var i=0; i < this.batchs.length; i++) { this.batchs[i].restoreLostContext(this.gl)// this.batchs[i].dirty = true; diff --git a/src/pixi/renderers/webgl/WebGLShaders.js b/src/pixi/renderers/webgl/WebGLShaders.js index 93cf578..4f3724d 100644 --- a/src/pixi/renderers/webgl/WebGLShaders.js +++ b/src/pixi/renderers/webgl/WebGLShaders.js @@ -1,4 +1,3 @@ - /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -23,13 +22,11 @@ PIXI.shaderVertexSrc = [ "attribute vec2 aVertexPosition;", "attribute vec2 aTextureCoord;", "attribute float aColor;", - //"uniform mat4 uMVMatrix;", - + "uniform vec2 projectionVector;", "varying vec2 vTextureCoord;", "varying float vColor;", "void main(void) {", - // "gl_Position = uMVMatrix * vec4(aVertexPosition, 1.0, 1.0);", "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", "vTextureCoord = aTextureCoord;", "vColor = aColor;", @@ -69,7 +66,6 @@ PIXI.stripShaderVertexSrc = [ "}" ]; - /* * primitive shader.. */ @@ -96,48 +92,49 @@ PIXI.primitiveShaderVertexSrc = [ "}" ]; -PIXI.initPrimitiveShader = function() +PIXI.shaderStack = []; + +PIXI.initPrimitiveShader = function() { var gl = PIXI.gl; var shaderProgram = PIXI.compileProgram(PIXI.primitiveShaderVertexSrc, PIXI.primitiveShaderFragmentSrc) - + gl.useProgram(shaderProgram); shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - + shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); - + + + //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(shaderProgram.colorAttribute); +//gl.enableVertexAttribArray(program.textureCoordAttribute); + shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); PIXI.primitiveProgram = shaderProgram; + + } -PIXI.initDefaultShader = function() +PIXI.initDefaultShader = function() { - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.shaderVertexSrc, PIXI.shaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - // shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.shaderProgram = shaderProgram; + PIXI.defaultShader = new PIXI.PixiShader(); + PIXI.defaultShader.init(); + PIXI.activateShader(PIXI.defaultShader); + /* + PIXI.shaderStack.push(PIXI.defaultShader); + PIXI.current*/ } -PIXI.initDefaultStripShader = function() +PIXI.initDefaultStripShader = function() { var gl = this.gl; var shaderProgram = PIXI.compileProgram(PIXI.stripShaderVertexSrc, PIXI.stripShaderFragmentSrc) - + gl.useProgram(shaderProgram); shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); @@ -147,11 +144,9 @@ PIXI.initDefaultStripShader = function() shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - + PIXI.stripShaderProgram = shaderProgram; } @@ -186,9 +181,9 @@ PIXI.compileProgram = function(vertexSrc, fragmentSrc) var gl = PIXI.gl; var fragmentShader = PIXI.CompileFragmentShader(gl, fragmentSrc); var vertexShader = PIXI.CompileVertexShader(gl, vertexSrc); - + var shaderProgram = gl.createProgram(); - + gl.attachShader(shaderProgram, vertexShader); gl.attachShader(shaderProgram, fragmentShader); gl.linkProgram(shaderProgram); @@ -198,34 +193,64 @@ PIXI.compileProgram = function(vertexSrc, fragmentSrc) } return shaderProgram; +} + +PIXI.activateShader = function(shader) +{ + PIXI.shaderStack.push(shader); + + //console.log(">>>") + var gl = PIXI.gl; + + var shaderProgram = shader.program; + + // map uniforms.. + gl.useProgram(shaderProgram); + + gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + gl.enableVertexAttribArray(shaderProgram.colorAttribute); + gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); + + shader.syncUniforms(); + + PIXI.currentShader = shaderProgram; } -PIXI.activateDefaultShader = function() +PIXI.popShader = function() { var gl = PIXI.gl; - var shaderProgram = PIXI.shaderProgram; - + // activate last program.. + var lastProgram = PIXI.shaderStack.pop(); + + var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; + gl.useProgram(shaderProgram); - - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); + + PIXI.currentShader = shaderProgram; } - - PIXI.activatePrimitiveShader = function() { var gl = PIXI.gl; - - gl.disableVertexAttribArray(PIXI.shaderProgram.textureCoordAttribute); - gl.disableVertexAttribArray(PIXI.shaderProgram.colorAttribute); - + gl.useProgram(PIXI.primitiveProgram); + + //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); + gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + + //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); +} - gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); -} +PIXI.deactivatePrimitiveShader = function() +{ + var gl = PIXI.gl; + gl.useProgram(PIXI.currentShader); + + gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); + //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); +} \ No newline at end of file diff --git a/src/pixi/textures/RenderTexture.js b/src/pixi/textures/RenderTexture.js index d584420..738c1d7 100644 --- a/src/pixi/textures/RenderTexture.js +++ b/src/pixi/textures/RenderTexture.js @@ -5,11 +5,11 @@ /** A RenderTexture is a special texture that allows any pixi displayObject to be rendered to it. - __Hint__: All DisplayObjects (exmpl. Sprites) that renders on RenderTexture should be preloaded. - Otherwise black rectangles will be drawn instead. - + __Hint__: All DisplayObjects (exmpl. Sprites) that renders on RenderTexture should be preloaded. + Otherwise black rectangles will be drawn instead. + RenderTexture takes snapshot of DisplayObject passed to render method. If DisplayObject is passed to render method, position and rotation of it will be ignored. For example: - + var renderTexture = new PIXI.RenderTexture(800, 600); var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); sprite.position.x = 800/2; @@ -37,9 +37,9 @@ PIXI.RenderTexture = function(width, height) this.width = width || 100; this.height = height || 100; - this.identityMatrix = PIXI.mat3.create(); + this.indetityMatrix = PIXI.mat3.create(); - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); + this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); if(PIXI.gl) { @@ -68,7 +68,7 @@ PIXI.RenderTexture.prototype.initWebGL = function() gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); this.glFramebuffer.width = this.width; - this.glFramebuffer.height = this.height; + this.glFramebuffer.height = this.height; this.baseTexture = new PIXI.BaseTexture(); @@ -96,7 +96,7 @@ PIXI.RenderTexture.prototype.initWebGL = function() // set the correct render function.. this.render = this.renderWebGL; - + } @@ -105,19 +105,19 @@ PIXI.RenderTexture.prototype.resize = function(width, height) this.width = width; this.height = height; - + if(PIXI.gl) { this.projection.x = this.width/2 this.projection.y = this.height/2; - + var gl = PIXI.gl; gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); } else { - + this.frame.width = this.width this.frame.height = this.height; this.renderer.resize(this.width, this.height); @@ -153,15 +153,15 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle var gl = PIXI.gl; // enable the alpha color mask.. - gl.colorMask(true, true, true, true); + gl.colorMask(true, true, true, true); - gl.viewport(0, 0, this.width, this.height); + gl.viewport(0, 0, this.width, this.height); gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); if(clear) { - gl.clearColor(0,0,0, 0); + gl.clearColor(0,0,0, 0); gl.clear(gl.COLOR_BUFFER_BIT); } @@ -170,24 +170,24 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle //TODO -? create a new one??? dont think so! var originalWorldTransform = displayObject.worldTransform; - displayObject.worldTransform = PIXI.mat3.create();//sthis.identityMatrix; + displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; // modify to flip... displayObject.worldTransform[4] = -1; displayObject.worldTransform[5] = this.projection.y * 2; - + if(position) { displayObject.worldTransform[2] = position.x; displayObject.worldTransform[5] -= position.y; } - + PIXI.visibleCount++; displayObject.vcount = PIXI.visibleCount; - + for(var i=0,j=children.length; i Date: Tue, 15 Oct 2013 16:47:56 -0400 Subject: [PATCH 49/96] updating Detector to use new ThreeJS method which supports more environments (like SublimeJS) --- src/pixi/utils/Detector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pixi/utils/Detector.js b/src/pixi/utils/Detector.js index 62c78a1..b8d0eef 100644 --- a/src/pixi/utils/Detector.js +++ b/src/pixi/utils/Detector.js @@ -23,7 +23,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) if(!height)height = 600; // BORROWED from Mr Doob (mrdoob.com) - var webgl = ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(); + var webgl = ( function () { try { var canvas = document.createElement( 'canvas' ); return !! window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ); } catch( e ) { return false; } } )(); //console.log(webgl); if( webgl ) From 8c2da284a914d54d6bf681c068169348b5a8b26c Mon Sep 17 00:00:00 2001 From: mattdesl Date: Tue, 15 Oct 2013 16:47:56 -0400 Subject: [PATCH 50/96] update Detector.js; now supports SlimerJS and other environments --- src/pixi/utils/Detector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pixi/utils/Detector.js b/src/pixi/utils/Detector.js index 62c78a1..b8d0eef 100644 --- a/src/pixi/utils/Detector.js +++ b/src/pixi/utils/Detector.js @@ -23,7 +23,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) if(!height)height = 600; // BORROWED from Mr Doob (mrdoob.com) - var webgl = ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(); + var webgl = ( function () { try { var canvas = document.createElement( 'canvas' ); return !! window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ); } catch( e ) { return false; } } )(); //console.log(webgl); if( webgl ) From 91562cea08bc175bf3597f97db078961854c9913 Mon Sep 17 00:00:00 2001 From: Chad Engler Date: Tue, 15 Oct 2013 21:02:36 -0700 Subject: [PATCH 51/96] attempt to get a 'webgl' context when 'experimental-webgl' fails --- src/pixi/renderers/webgl/WebGLRenderer.js | 32 ++++++++++++++--------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js index ad88e5b..e6621ef 100644 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ b/src/pixi/renderers/webgl/WebGLRenderer.js @@ -43,19 +43,25 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) this.batchs = []; - try - { - PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { - alpha: this.transparent, - antialias:!!antialias, // SPEED UP?? - premultipliedAlpha:false, - stencil:true - }); - } - catch (e) - { - throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); - } + var options = { + alpha: this.transparent, + antialias:!!antialias, // SPEED UP?? + premultipliedAlpha:false, + stencil:true + } + + //try 'experimental-webgl' + try { + PIXI.gl = this.gl = this.view.getContext("experimental-webgl", options); + } catch (e) { + //try 'webgl' + try { + PIXI.gl = this.gl = this.view.getContext("webgl", options); + } catch (e) { + // fail, not able to get a context + throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); + } + } PIXI.initPrimitiveShader(); PIXI.initDefaultShader(); From a73763ee194c845d40a82112e6d764854356d492 Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Thu, 17 Oct 2013 16:26:02 +0100 Subject: [PATCH 52/96] ie11 patch Tempory patch to force canvas in ie11 until i get webGL working in there --- src/pixi/utils/Detector.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/pixi/utils/Detector.js b/src/pixi/utils/Detector.js index b8d0eef..e955e49 100644 --- a/src/pixi/utils/Detector.js +++ b/src/pixi/utils/Detector.js @@ -25,6 +25,12 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) // BORROWED from Mr Doob (mrdoob.com) var webgl = ( function () { try { var canvas = document.createElement( 'canvas' ); return !! window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ); } catch( e ) { return false; } } )(); + if(webgl) + { + var ie = (navigator.userAgent.toLowerCase().indexOf('msie') != -1); + webgl = !ie; + } + //console.log(webgl); if( webgl ) { From 5199e6e946a672419c2055698e40699bdb64c213 Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Sat, 19 Oct 2013 17:23:47 +0100 Subject: [PATCH 53/96] Canvas Tweaks --- src/pixi/display/DisplayObjectContainer.js | 2 +- src/pixi/extras/CustomRenderable.js | 3 ++- src/pixi/renderers/canvas/CanvasRenderer.js | 17 ++++++++++------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index 68ba15c..09d5b0c 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -72,7 +72,7 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child) var previousObject; // this could be wrong if there is a filter?? - if(this._filters) + if(this._filters || this._mask) { previousObject = this.last._iPrev; } diff --git a/src/pixi/extras/CustomRenderable.js b/src/pixi/extras/CustomRenderable.js index e9812b2..24b2258 100644 --- a/src/pixi/extras/CustomRenderable.js +++ b/src/pixi/extras/CustomRenderable.js @@ -13,7 +13,8 @@ PIXI.CustomRenderable = function() { PIXI.DisplayObject.call( this ); - + + this.renderable = true; } // constructor diff --git a/src/pixi/renderers/canvas/CanvasRenderer.js b/src/pixi/renderers/canvas/CanvasRenderer.js index 641faa8..a1a7352 100644 --- a/src/pixi/renderers/canvas/CanvasRenderer.js +++ b/src/pixi/renderers/canvas/CanvasRenderer.js @@ -195,6 +195,7 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) } else if(displayObject instanceof PIXI.CustomRenderable) { + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); displayObject.renderCanvas(this); } else if(displayObject instanceof PIXI.Graphics) @@ -204,25 +205,27 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) } else if(displayObject instanceof PIXI.FilterBlock) { - if(PIXI.FilterBlock.data instanceof PIXI.Graphics) - { + if(displayObject.data instanceof PIXI.Graphics) + { ++ var mask = displayObject.data; + if(displayObject.open) { context.save(); - var cacheAlpha = displayObject.mask.alpha; - var maskTransform = displayObject.mask.worldTransform; + var cacheAlpha = mask.alpha; ++ var maskTransform = mask.worldTransform; context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - displayObject.mask.worldAlpha = 0.5; + mask.worldAlpha = 0.5; context.worldAlpha = 0; - PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); + PIXI.CanvasGraphics.renderGraphicsMask(mask, context); context.clip(); - displayObject.mask.worldAlpha = cacheAlpha; + mask.worldAlpha = cacheAlpha; } else { From 127aff7594766b751054c41f12e9d8149666e810 Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Sat, 19 Oct 2013 17:43:06 +0100 Subject: [PATCH 54/96] Canvas + removed --- src/pixi/renderers/canvas/CanvasRenderer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pixi/renderers/canvas/CanvasRenderer.js b/src/pixi/renderers/canvas/CanvasRenderer.js index a1a7352..1e927d3 100644 --- a/src/pixi/renderers/canvas/CanvasRenderer.js +++ b/src/pixi/renderers/canvas/CanvasRenderer.js @@ -207,14 +207,14 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) { if(displayObject.data instanceof PIXI.Graphics) { -+ var mask = displayObject.data; + var mask = displayObject.data; if(displayObject.open) { context.save(); var cacheAlpha = mask.alpha; -+ var maskTransform = mask.worldTransform; + var maskTransform = mask.worldTransform; context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) From c512bd35a451da2bb024db425bc1ad337d0ac77f Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Sun, 20 Oct 2013 18:26:25 +0100 Subject: [PATCH 55/96] Displacment Map Added --- Gruntfile.js | 4 +- .../example 16 - Displacement/BGrotate.jpg | Bin 0 -> 139735 bytes .../LightRotate1.png | Bin 0 -> 213699 bytes .../LightRotate2.png | Bin 0 -> 173189 bytes .../example 16 - Displacement/SceneRotate.jpg | Bin 0 -> 113742 bytes examples/example 16 - Displacement/index.html | 168 + examples/example 16 - Displacement/map.png | Bin 0 -> 96515 bytes examples/example 16 - Displacement/map2.png | Bin 0 -> 72052 bytes examples/example 16 - Displacement/panda.png | Bin 0 -> 69177 bytes examples/example 16 - Displacement/pixi.js | 10773 ++++++++++++++++ src/pixi/filters/DisplacementFilter.js | 58 + src/pixi/renderers/webgl/PixiShader.js | 19 + src/pixi/renderers/webgl/WebGLBatch.js | 53 +- src/pixi/renderers/webgl/WebGLRenderGroup.js | 2 +- src/pixi/renderers/webgl/WebGLRenderer.js | 2 +- src/pixi/renderers/webgl/WebGLShaders.js | 18 +- 16 files changed, 11050 insertions(+), 47 deletions(-) create mode 100644 examples/example 16 - Displacement/BGrotate.jpg create mode 100644 examples/example 16 - Displacement/LightRotate1.png create mode 100644 examples/example 16 - Displacement/LightRotate2.png create mode 100644 examples/example 16 - Displacement/SceneRotate.jpg create mode 100644 examples/example 16 - Displacement/index.html create mode 100644 examples/example 16 - Displacement/map.png create mode 100644 examples/example 16 - Displacement/map2.png create mode 100644 examples/example 16 - Displacement/panda.png create mode 100644 examples/example 16 - Displacement/pixi.js create mode 100644 src/pixi/filters/DisplacementFilter.js diff --git a/Gruntfile.js b/Gruntfile.js index 5511724..5f7fba8 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -24,6 +24,7 @@ module.exports = function(grunt) { '<%= dirs.src %>/filters/FilterBlock.js', '<%= dirs.src %>/filters/ColorMatrixFilter.js', '<%= dirs.src %>/filters/GreyFilter.js', + '<%= dirs.src %>/filters/DisplacementFilter.js', '<%= dirs.src %>/text/Text.js', '<%= dirs.src %>/text/BitmapText.js', '<%= dirs.src %>/InteractionManager.js', @@ -128,7 +129,8 @@ module.exports = function(grunt) { 'examples/example 12 - Spine', 'examples/example 13 - Graphics', 'examples/example 14 - Masking', - 'examples/example 15 - Filters' + 'examples/example 15 - Filters', + 'examples/example 16 - Displacement' ] }, connect: { diff --git a/examples/example 16 - Displacement/BGrotate.jpg b/examples/example 16 - Displacement/BGrotate.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f33f7d453d124f40054115760a0415a21b04e70b GIT binary patch literal 139735 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 dr^rzERs0CKwGPZu<1Cv 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≪ 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 Z0H#B*9181k+sPNHr;kr+AISa>|JjdZ<#Yf5 literal 0 HcmV?d00001 diff --git a/examples/example 16 - Displacement/LightRotate1.png b/examples/example 16 - Displacement/LightRotate1.png new file mode 100644 index 0000000000000000000000000000000000000000..44966cfed50a834b276533f8c34adff03fb5e33a GIT binary patch literal 213699 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 ZfLBC}NRr`DM z31kPMUr;q?)TfV$3f6mHDI9oUg)Px9&W_2PMiTHWz7(maKxP-BN@uu_+yVx#>s(Mo ziDD_8m4<{(jHx9U8+r(jN2oP(mMXO|stz=a0vl0n|M|}|$DSP6>1g9?VHT=2YMkhT z1JT|{-dbH`0wSWwQl)~R>Qfq!Oo`v95LHq`t{Nk{Au}pw$gIDX2)(oxTNMlu&QUXA zlRypPMMeXY1Sq*Pk)M!VF+Wh-N}dupaapph8FbcGx_6stP?b3Q*|gPNMnz^HMC=1C zyij8-3JQ!k(C#l8D#}c$Ho|iy&vX_%Hf>c(d50?zq0W;8G!kA@b3!@cM4MfyCxm3O zrN>e!f<)aep)yvnDn-p`wq+8-s~|&n%LV@CVuXz!Ckt4rFV3o>?eWUV^+dOCA$lV| zW5w?1v~d#C$O;yaAa1!Gb{|XN{X28uLvthecl&c3GifvhYmrwfx{TwNi65Qf%rlK{<)F;P=ji`3In?>W{e zbruyl7iroGaUK3vQIv{zTyw8mMqtBJMa8nJR0yu2^9(kZP{d<_3OtE=AW2dT`S?O} zrbIV|saY*eu>oCYR1z&~Hn&Pb7Kv?QrL;_C7*iJMLzLU*8u%(vL=(88kh-N2o%p$W z17RjW47cmG%%Uqo27R}E10OjSLle=U5xm!n-h~hFz5?bKj>DSjNhQjDvQm7dsB9%g zuSmfZR79`7nESA4*JK7ij^bxrm*g;>v>)%U!Zb-`mMT57l=ihtc<-{OrfY8D3;W%Ys)fx6S>2z`{494>F7;`b@MbaTynxR7YJ`deX znM9tIZ&~4$_abY&6!GE}hXv(bK#ur+ow$~0%|p_jqAwvsn8FfyIg{h<4I|a!2xtKp zZtDT^`|zjt?jZjT_Fu=9{LVd=c)y)1nbSFKffH~mGRh_r8t-;AFql#gvVz&^gt`*t z_+dm+KQ{bA64*nl$_ObLLn8FjJk~AbRw7fE6!k@EX;%%ZXc>X@E_3A(3S;9kOHkI2 z3QE`{=FRt|{7+zlNdjqK;C6P3Lr~tIq-auy26jRv{E{OQrqQN|52@IbaxwwEVCAEt zDOxrnc|oT|#^9nxb(pQl3T6gH2esro;h`U+uW(MAv6NVoSu&HliR!debJ`g_LgI@? zxNaV6GAHGPY~o9&q+woAO0yv`iRK42lJj<@k+x?oe0nX5s+p~hpJzlKQ_2!_T!y@~ zd0Q*WGp?kii4?EmiQ%5e5p-M5JO2bSgTM>a6_u(6ijq}8MHL&mxTlHg6L3k+SFQA> zIrYPbzi82P&rKL12mm<@H5azutE05wBxh^&t)I6noaW1){ z@GSoqr;(b1ngojo=~)3S$hS6e>|F(WgF4r$m48}cZb@|nsJh_ny+Nl3bQ*6yGMI`|56j!J2W}y9%o#q0-@6dqF2E7gV63VsD_6l`aEVDGgVYuo zGxntxUFmFrMD>XgujM)$z&9sLN-E$yp&}|T9*xW{VDk$hc`yC;Vz^CE4kjuR90(<@ z>;YI!I}f@5&W2u?QaBCN1bNAm9}G!i&1I9Fq$0A4h{Y2dz%fSBq&WV7W@;BrUZsdI z5v-t6N&+{()ZbM`hql$OJ{*qK+8jUBunWE=q1Zs z>a}axrfDmUB&YLSHmFiWCKt+9N>kzUqY|Yu+>}{O)xp$?!87lv=v%0bO{0i@z~Z7V z`&;q^`UL@#Vf_brpT6k5%AldpFQ70?Sk*wrB1&haA)=C0&Rez_m`9~}k;H;NrIc!t zOz8|k4&zS;@K%S#88`-j*T<=Otck>l2gx!-`#AGeh}6D<&G_8XxiIT$+KqiRpVGo? zO(`N0I05AUK3|8uwL<17T)IN|goFxQ5JZaM=k=QBW!{~)e8CMCoSF|>1C9!Ts3elH zEr{eez^YjMl4ypISgJ00hxZf|hD#cVwyceu0xZ{t^?bIdaZe`Sn>i~-<;E1t4oodH znZNy`q9-I!WW_fNi2vk5n1G0&G5P`Z!a)mGyYm{Q*n9|?~ zT(P&R)-29#=7}TnR*OuW%MfZz6F;v%Gh!)C6qO|WYPlNvsX6UE_2d5&c)xA~wYRm? zX7*@jJ{K(alUERJxK|DTCvPI^MO^iKJg0V$ipk+q zSL!m@@i5Uh@tR}nh~9u>A9%##FlX;MW7J`1ou8gf-Mg?pe{fwwTff!Ht4DAom(Atw zNvXjNX&9&h?hD|PnZ>kSW2GtXcT_~Ab0O6sD~ZAcil!Mx z#p{e+Zc=VRMN7o0(~@SIkq&u)pN3+Ea|KOA&{57K*1;sCeFkw;s#_OCmMp?cjC|4+ zYzRu}U`Ey3l!}nkrA1Vdm?Ka*LmPVY&ct;}B$C2B%P2R%Sc8RRk(5Bwt!0Bu#NrjU z*fy$wnn__+H0n#MDy5xNiavt4PbG0GW+(#9b)XX{jF(FbqPD_7GyOJ~c+$j3*_`$_ zyi#9te<`hc(`{;%3ft+d2=$R;rp;9{(8LH9SxsJ%Jlfj{%5=Vjor_L(d-eV?LXmY{O*K$wp9>it5&`|_qn4LqZ?g)YRE_H6F8H^4Z^`LNa5y&M$HU%oiPP{E)&PRS6jw6 zq+(b)eHlP3@=E z@%x-`#d@LnX$s%2x@7FADqeLILmFPu0g7}EG|BP2VW{{EBedtQ^$G2ivpXN#@4t5}Q zZvSlVvssu24xG>6!pvnfzShwuIEIB|j=H;3sjK!av}m#yk8lLDE+~Vg8s&=aK+Wp2 zRbdcHgeEpuXj+)cHH>oNoe{>Vc#brO6P2dF87XJGMC*~ViwSjb*-WA)KL60T4W*BS$_dp}=NMe2UG@~5 z>K<^k>1_0#1y;lvAWL9nFdxu3iRv#q=13BUU@3DFbP|$c7%cP)9F?CR2C%f8X~sDj zQ3?ST!*K?E;2^b`3HN&mvI~vUDZKY7#m_Tmku;Ngi`jt!#k7dl#7BstzOwOK^bK4G z40JgZQN%F-YeeEUkqm`9@RiDKbXY~6eu zm+&Zz-%V06u7f>$iR^&|M05`!pdT|TJcnI1uC?pvMR z8MQPOLwiOd$U^tVUE%Yn{}h_aA^qjvWZPz)TrTJ%S#h~C1ZPIOFJd{);G#JhKNV-d zPLv*{@gAV6X1JwyZj=*EQZh|NnB_Lsj9u8qXQo~pOtt{y&+2K&1XBEc+^$PkA{2ov zFYGVES@Ng=!iMZdT=h>$ewq8t`1HH*_j!X@AZDm+*)8Kfy0vg3O)Q783yChcT`L?P zMuxBj+u{0?c=2PpHTbAFE8r`#Yqgxaez*Y%(->FxUl?F(sW8JpiT52-C-|n49sk8I<=&Rn2@jCX2Lf4B4DsT;{TFBn1LG zDyF&B7`KfYDYx=Zvq-x&+R`jRX1+zwSK8Uq1eOU`hUdAKJ@?#3c2T0DvbikLZUOCA zQPpC?nUhpu;%vz=OZ~SHWbu(hnA7ZlskOvlt+LWjpGK~n{W%-1JEw^pAfW?M&!GBU zI)b?GFknt#FoKl24oYmJ7?)$JF5=_yK9Bku@$(}xx&T>}*YRsOOFAnv1l%7;cr+AF z!Fyx}bzF~hnkvIBDl{G`Vz1*pbP-(FMJY}1Mt1#JovI^U)HptbqyXpAUI$|}f@i@b zxD`SyM_I29k4adYYMnkRllW3E#>%lu3mr7Gbqd&!HAeLtW>Q3uDhc~V8?a&iK-XC= z>q=y6oa#PHGnk?0na&0XNgZVd)JSB$CO~tgT99WZDwLI%#92mSth!S7_u3TBTw+2r zUgiZVUKy30K|S-_TSHrG^RWh*3o`{tB${JD0$0pTl`{(5$gNhq(OT=?Ok1wt%@)>D zr<4~=jK@x^g2%RSry&Di2f%v;KleEPojHv%nr`S|AD{5bM6PuiUaEm_($8r_kf9J5l&e8Bij?SKPv~3oPyeFYbS3;AG1sbVTXuj2;cBLX2K&`?U<(lN7 zSy~svM%F0JMEsb`N;N?%IcZ#{!bw!r4--``(-M&h+{6)JAjoqjeB(+r#v+>zr4#Q9 z1QR9YG;~_@D1s(JpmtE#lgOZ1TL-yZXbxvuLUL3zQ&6gGbJ^02R^4TVo!Yc=;)@aefP5;ZM_n{M8wS+4mM$!os|+rq zd`n3+H|^kdv}%l?PYR8vmEM|;DJKvQLHXJe!(=`x@zkOc(O?In$ejm46hlg@<_t75 z5bElJFF7{uNkns|pEO#(W~ zN_lz7ixlFF0Ei%igi2||i|H<4nTF6%Ll=0!vQP%fN}eUjEi+kL0*Usae3_|4t*tX= zGId4}S1K9=stW7H1^obT&kY*MfeOa-4xAyF0=Pq<n!uLV{5lFaSnoxa<=|$NNxcRFln)Jnin7d>mfJh@SGan zX$HSzJDkGbs_-y_(lbDGkN04`!_7D%=8S#F;0X`lOdc+nqPRDpAx&&^BN#=+HEjuF zY0YDa%&sQ7=(Ebj_`b`CuEVmw=zzUZm#VOxx>Q&5w)=?QyPaq)o_os~yv<=+nl>J{ z_r8rpkKp~^%0+=)i}0`KLZ7kyj$cExZg17o9Bx2XwFcW^N0Z}fWcR=;4#B(nosK5p z9J)5A)Hkp53eCBMnk%YEo$#1es0*1wCWxfEvU~cPOz1Y9a>XS0odq{I!_c}pH)Dcc zfXy&a#7&Zv(Rwa@fp~z;StHdIuaT@E_cmyhs^^c8Mv3(-g4nw^{C;le5=k!$-Cv`` zFiqq#DmTb&VkEX!ca}&jaZyt@bbC#%Ql^>PB8H+6(;n4Q7CFX>QZy$O$;aLaq*CQ}uyK$S55o9NEkGQfsW7jF~INyY7@Rd`KV7;%wG1R-MIo_vK z+sLSVd%fsP=lNzq2=NdZa|}_Xu9-k8(^q!PfnM4N%Fhz2A{Nn=nu|sqO*T3s20J2X z3y33GZv|>7M@-T-!>f)!A)%@yruxOXqK5*o!q8QjWspU%=L#!rIGetW~jKFLtLii z%f=KWPKQ$$+POHw1-!l+&VvPP`lw~lRsKI`RBf7^*HPRaY=P5F?hkl649D7w_u1mO zlH!GE4j~dD8BD)u;Y7Es@_}fawR(OGT_t!5zShUD$4)~snw}#177YHQa13w5G4$;& zL3v|WB5c8%Za_wGW}4`>TZsNE@016ZiMMRIa=D2$k}gIj!t;@ZhwA*AMdoq2u9;!( zWz=1XWF$C+_DmpG%jv{1NA+1DZ_0Nb%ah&kOjErr>K#mI3~p}Y0B-P^st|Q?i70O| z|GLsVx2iR%lULex$|^dQ>(aXEAlC#9!Uix;QmY9%X|5(=P$=lmhB^ z#x6`u7Fq_T;N`s$zS)8`q*7kMtG#6jn*IwVt;;RqvKzo1(Ou8Q76 zJu>P(YF3AmmFsY5QJuQ;8Whr&na+3k8JVq+b7W_b?!~2L#Lx*!Dq~TDJ?l76BL}Rc zG<0nb>~0sb0yqJ_KKVvmtCjdS;>I?dK&pZ>JeAFvuxJ4b4SN`bGuUeqoK!@sLB6a9 z8a7@SMspwWGEtEYc^4Gaa{)4NkHEXEC;=uS9up?tLpjaIxVdtmGfXA(ddYHQ81NCp zKmefKl>6*3IR%vKySmi_7n^-Vr_3DNWL##^`{Jf+*B z$!N6;b;qrFfavWzi7v-B*m+c%63g}qK9AR&#ddlzwt8*1J2ir z{9IK+H24_2WP4mSUcQ4H@z}jM&Q-4IZ^>#m+=t&UbyQo`rY?N&*mQ*kdlJT8P=6OT zK&z$_n)SMBpTZH;^BOG(2Tn~K1DBH$b`X3PqRE>X+NNT$VPc*>DHd!@nH|tS3NcNn z>@#a=rNEj5{+X0Y8OH*lK?Q+bZZm};Q%Gzv3*EFUXAWG!dt_y(2;S<0gGv125(P(G z!k{>36wsLvl<~KYRaO-{Z%pZ`HkL(0YME&*2LNG0CB&)Jm?-7|1cumU$FR;y@J)*Z zn;kWIgPMxM#z|>+l`@&3p<7>OPM{w34f>-=Cq;I?eeiZM;_o$hG@L`cWqHec<&E6XZdr(@r5(1DxkcG(n%3a$gAZ6%mvL zm?fDgyg_M2j#6ssNlVuxeVLR;IR)!d=O5BXQ)=DzSZk}wJ-Ij z;krle$CaBR|Bufif5|A(jVH}oR*O~c3tH-PDO$ekuS!vtxf%w3m(rbn<|-rsL)s9o z?F(AQ$Wkun`39mL$R5}!J-C_ZH*tLic0~u$krhm1oBkbM$LuKU*s;uZAdTW}IBQ5I z97F$s^Eiz~0KkgY9}b(c;nZ1w-xKEgi=+9 z5;T#SJKcu?G;LBRHY*SeM&Kn1cnylu)c}zUtwqIL`;x-h;H5h4nipCPVMI7Vc15XqwP`_GY>ihb*ta1F0rtm`qb3Wl&)HLno#78oeCHGSi zjV&^|U6Gh{sRLa)0mHZzkCR$1lK#Q!sEkvIa?^M_)a?H~wxYT_I^TYY`hVybbVVql z04+_IpsPqb^5U{2fv%|j_WkCf_mzk z6`$9paSDwzKXN5cdN@h9K8qE86sz!!-y;8+?L?QH4nwo&>3BWKuL>LB@vC))Zv~8c z8&2TwE++bZ{Bz^OWfgZ0%j@h0E26@vzvpJ6XX1diG8$d&pwMR;=Z-% zGJ+^rv2%daUip_)ZGNtu@luH2A8Y^*D)?I0|NhB}fmZP30A&Df#=Oyx9WLIv$L znXtHOENh30BM&k*R@um2g?0iQR?AsoULY@`cNgqi(k}CKYL_gV+)GHR1$mM>1ruqp z=M)so0fHVTbE4*HNhP7W!eu@i`UVSy;*|a)G)OA#h2|RVP&E zfvH;Rr6XWkX~_s?d#TdX1A{h%zpa1?*{FRO+JcWC!O}on$;5^29*dq+!T9?C$j_|2 zkr->JQ>_4>@vJ(9s84?7#<w?iDeKbt6YHE`wMvN2X<`NC6&qFh8V>6>VQ)Wv1u_DJ1~(pD#@7Bjd{vm! z@$@A`o4=vk?yvFlAU^EoF&T8%QDx2wuFze1*#ks(U~7ybN&lsJ?6SSfB0&WDlLuiEEKETS%Dn89y+(^EJ8 zFnTXOYur)$+MG`P3o?W2DZhLuNsiWA)IXol#P9+QXDLm%d8%g&LakDxo+AB&p>J{@ zp^MTQqOrVNj6YL7DSe+6`n(~^_Mtgd@OULA{E`$RYf2sAwLc)qqLp@1#rVsbGaew}1aj??kIRL> zD{L~)4P@a zPx~U=`=5NqR^F#dyx^s88xA9^0q zixNF}iEWlL+<4vJT}QM9&wCcOZS7c85a|5E7H?qrP9gia_%qP}+!Oi2G0)-({v({v zuiw?#s>2UG=CLZ+&x4nFntcejcHYzU9h7{b$J4+I91UNW)8rjKyJ0X*&oJTUNJ>2^ z(_^H_av22#qh6^{E3Z*KuhK$yO={{4apdUM`MP8fBE|yez)m1%bdEG#yKKt1ZqZ1k z9E}$m4wd87vWqLE9LdGewDlws)me~D5U~6~6IFoJc_|YZC^C|~C}$S~Vx|R=*vNE2 zZ4t=vERqu~Sl2dc1eLGUvOvvvj#8T=NJ^@SfWr%)z37g_Wh5KA5)PjjRuJmr4Kuba z>ltMBzfnUMt+57gCv-G6*rCbXYYw6IIQj-LOX;8?iR$Oc4Cp*r0d+LCTS~;|&S*v; zS-_)s;yyc{lh!O>D6%YuiZ+gE=_=29DXlVn1ha{*$I)=9Y`qSS;b)dB$z7k$bl7~X z4lS96G6kAw8-i@x@SqQTQZ{v)1x*EoX(l4VyX(lC|R8$KY+0+u_FSQaFbysWQ0g-=O`&PnLgz%VE%-R(O{A0JbGMeqlXnYg_ zCYI}JJZJE|fhT^d|Nd51yySWpTps>kP>>{UoviC&@H@^jYwv$Y?Hm zY#GPXUQj-Fu9HqZV$9BX@z|WF71;L^4N3>PpCUO-SLrP5;_&R=W<;VuO>C8H@Ozy=_A=O9C9ITm{YMDvr2Wq-NNf}w4 zaVtsWpPHymLWY4hZDwn$OJpBrt(=Q^jHpoDvI&?%V^;_1N;-?gNbYoC#)N`G$*B0B z83i-+!9j?aJ4-nV=V6#!4tz>!fqDuwjn4TcjBjqZ{J;a$AJxb6h~hdll_v`#J2j>w z<_tz`t8_-{No3r6qd~N#&_^zsT<+<}3Tn}@=S!4_sN=Z(x%9_!E;ELTIwsW9L=RiJ z>!8_ynaB|sO08X??#(@vEx^cg{XZQM&EX`0BXC=UP9jNG2}($LrxH;rll(BvO%jp{ z$fzQ6!bGh?ql5U9GqtZEvaXZUnGIZKMHf}1Boo!q5=4+Sn8Rz7A1o_oP71-Ez}QgIT%eHh=*g*`lr zRro0G_?z!MPcZ%OOG`Sk)DfRdAZ?k&0j-6RZ6KEU#P<;W z7{fny*}Yr>yULJThLYZdpRdFcPtTmkqv11VF2GL5Hof4s$H&4h`2{mE26J#b&f$-~ zu#Dr8U>sg%XeX}ly~awx5}EKK!$^JlFY&bRkMQ~U+i|3I+i^>#9?0qNKj7GhJ*|E& z68meBMowVCZN}m_>8R3^!h2y6Rx4r*bAhC$!u`TdfvJvD{#&I-Xap1ALv5y#_Pv%t zAl;`f9ggEQ;JF@OQ~GWx&?Qu`x4Tp!Z6*Sw&9FcP5lS&i%opM9tf_2-b~2o1NDO10 zbOCxASWuIs&{-&ie*(8aVP7-h%TJ8&NU8iVCbY)KYGUtIR&jpW_e~8}5Gl zId%lGp`EdeVM-@-W$qwMCU1PvHN9kV=l)lqP(Y?uCyt?=l`vEax}_VO`zmMf;_y(zmS zF{!dZot4VLkPdnbq_aB(>u}~xx+=_?<)&oDlom|`RWwD)hPPxK=Q zrt1sKl;i(Box$4sG?seLR8Me)-i*&tg_%_kI@$)(y@bx$;cci4d z?kxFy8_RVclJ~b^nRGw$I35k3b0Q#_nolw-z~{XCdZJt4U001qlg*2I7e7Pm&48>XD7jY@uFp{ zO-@(f2l^DQCR&X)Pq;oN3GBkqM*kdaiLZb*-G;8Ie zV`j8RqS}7kOim*tQ7m@TIT@2g^9B7KD5A;|NIch3BI-o^P;}hWIz=s6z<$dL_E~l_ zYUk68;1Fps?B*OCL1iP>4vWpOGeF**;M({VxCI01fPEz*|8Ye&XZ1d#nV^z9FUc1f z>cHhA&RzU)m~PH=Mu3~ZStt>z@z2{n0vS+2#Y~ZGC)tcnQOYa^v0XtFC-lyii88WC zR%5EDpOooh@}Llw+Z*HsYbj-lKFeU-(?pxOQUb`E!p@Vi-Zwjh1Q`MUuZ19{s(emu zWVRU`Ln6>u82{d!rWe|@8kh3OnKn(Hz$XsnilM|Y%dl6_KzMibENA%Bln;(4uAG1ce>|V5I ziEhC%Xo7_Eb=(u!Z6A!wHF_nE8ArGkTkQl6{*DWYewjsZ9$tQ+e-3B! z!ONA(dK0(9#?J#K#e1H;T$kL6eajf}$NR!D?^%ys1yk_rpIWBhz<~zWwt8^_r@v%n zdZ+7X7=$zygV(9UPF(ylWum(G zm*5;W!IZekxxyTHJ z=^_=>+TKNMYk@ViZJbI$9inQ^tWq}V&Y@+X0*AjCKOYUH6?OJJGM3E}b|9sdU}RTQ zsW*^DrJVp_?T<+AsvTTLo%02~=3oY*D4n9&g7cM!9F^LN3s%}1wV;pZ^mkb{5Hf;* zluBr^4#P0k3rvFBfGmuS{}z>?^eZhB=rSqO)VjTX-&D--=ZO$ z+hhypSA`?!!Kc+S+73f<=#ktH!147SC3oszP8DY9fYGn6WU3GAU!;r((jFuqXIEhG z_U8`U;$I)$N%Z5m+g**QI>Iza9B5yr)sU00fvuV@b{?;qfn9t)R>tcQqyF+eOLW1W zDrdk;{zI1%eGh)QaIYw*%2ID4#yY)Kcg!%-l($_$bOjE0CxU9>knCEz8d(TrIGM(kqml={Nf0Ac_i}apr;d${{)%hhd3t3$3!LEaGKaQKq6gOSEPb+xx zniu0BK8s&1=p06xQpE|3-XQ{PqN%+aSEr5zaq?e?rf`=AU?bMN2r=80p1%4VqT^rl zH1MBr{`(y5emkE3yqqq4gF^<=ruvYRl(aUS(%hjrs;=P8JFN{*_MgnU7~+Zx4bXy&Pi zNNQ20M3P1^A^SVEEF>s!Q5aNGA}tpTd|@1oug3>eM^^CmxPaxRPEF)I$`A%R`Ujzb zoS1=Ku*X3|7Y*6ZmB@%!J4!`C6S=ZPzaTh+(2x#r)TEv!dW@f6Cw1I>`Rr$CF;N2|c+{E>BczFx&-=r!YTh#^{8q-Qb zY*{)nXq|yBj_O}77bpikYkvph0zUE#V$1%=Wcq+cHC(dvlQ`kON0#w@ zoUiXvA;l$~h9&+duTiS(-Xl*wE4ck)I@ZGzcLz(8xC zW6}P%Y#adpTl*4h)6e7h=JYuGae-DKduW`*-|x`%zY?$8_A_t-AICPo8^0rS=*NK^ z{0lFjiesPmvWPBv6BZaQ%0s{FX#49jq@Y-Mi5l!mcg3cYt3qSoa~Szb-DV(nK71g018hS%pheOfaDP!q8CNx?0nlg?o(I9Xi!G5eOJ zB^Q88B2-pVCI(3$p^N$ruHbezW>f1Ws8dcC4TZVDb5kn9ckuVb6U0MQN_)3D9K&QZ zdvGjjD2I81B{}kalnkg^A^%=zS`Szk<-~2aYjKm+2ksP zt{c(52-fEfWXCNbQ{?G(CRt|93rgmc$(5gnzoo*?-;fee#{WmupVym0d6Bl7*czUi z(=F;*iE}usLzIn^88se*Yr*er_~yo}7Z!uYv@p3)v#rAm2f9?EJMa-El_zGG+7jB) zKfo5g`7SJ=ELuVMc>(5V9C!F4SpH)-C`BOO{4epsM0jusR`fgIEZ+I0D7Sq&oWaLn z!+tQg>EM=r@azVxV%W}pT>4%(gZJG`^c>vBiv!wcDZ>rh`3cy}A^h)o6DERFU%uhX zY0@|{j|;y<-@OQ7XBviW@ew$!pMF5ubRMeoR;3MWD0czUaMf#4}U~$ zqm+l9qZz{4Z&<$+2esyf8Xd4|)EqMU0T}-EufjFJUj5FS^}V>PH1Qo=xD%>X(+4{; zcqQKdd7kciIZVK(JyoijEu`H!?fo;vd_S1c{82cCK}0`XLh4DC_I98~Ioxn+a}BQ2 zZ8Xw7N(~_rmVKt}+beSp4o-n8T?);Vp|BpAiWZ%Mz?Wlknl2bJQz@fpB3dAX5mZ(4 z)40~31c~Q@#yF^Gxv0ThpqS*BmT~omLA5mE?@5+uyvC&#A322K^Yjnqt@(P~N<}N8 zMsYkC)*V4idpn#(EM_whQBm|p{egJm*mYzCQA{YubJm*0VUTRUm55H+|63gcaU%i| z6>1KCgdY6f%oJ$Xa%RUX$2A`Gm+rik&L=!9t z*Z%WlM(Vh(is+x&a^VPk3%^$y!u6AJc2L9d&$p-#8EJbR;{Pd)`g278)d4Q^c$(au zQxh@5++&{Rkd&o8Udq1`YSgq;T&pjR_v`-OW>v8=-~SAv3t-eQ?L;=>evygkQw>+rLfpfvbp~i9=pD`qU$c7CD2FZetuhXdm3N8WxuOr7*I$jpzZt z7`H6lyG%_U%l{1Q-@k4r`dQwI4=j^DQ5gdszZNT;kxXZwT+^5x%HJci7{b!H`5-M# ze8-AUz1v8l^U3chl$1Zbg#+I5eB1%#U{m|G9K=0??q|C?f!6D7y1S16nA5;&`?^=jWB?-!`5 ztMnUubwFW->=>ks)FX~VB_ewylaQZ{PC_1wVAdE$dHOU=h9;%HaFEmtoI@^5OH-uf z;G@a1q6APz(@uoTLrEj)Fv788$Rh(A_Yk@xV;h`7;4um$Zev!CSz*Iy-L|T0Q4b+F zf@+5|ps1YGXYUbn8TqKD9~?oeqrjP2Q+vX)fzTvAWR76eoK{Yy3fpj*4R97f7nnm^ ztFj|rX(W_#JwS1dT{==2^FAuQP(&P<8!R}?eb|f$&liYq&+_sf=XpUvu7WJK4)Tym zT5~$F=qZ#Dy$v~9e?i$-+Xg*unSHzy$yvq8*mG-(8RPJ%J~Mrs1aKV zxx`K5#2U;odMB>EClQ7}TcRObGsEdSn#zeq;jNAS`ZNz@x< z1cQ+iqA0`g(eXv$i8!QyZaQF&V1EZ0c&x+HM4O}*>pn{#x0`4 zE=y9*N`WrOQ95TVq+azZa?_2dC@~!s17Su*QQQG#;uOciqEPK1La)=l64fW=2t=Nj zRO5*=VH%bzWdkllXme8j@%fw@ef~Q)fw|;^NG(Zc#kf-qe{0WcV^}C2n(!A*N_&wZ zH1U3j=F@IO{?j;@29vva>RRP#;$BbPn{#^P|KQF)jBKEvRo)QltnhT|voJKLm5Q3} zK-J0_q2%NIQ)5waHt%~j(X+4uHlDVX6mFDPX6UsK5>0PVJKJLorMvO{9+;_jJd@~^ zST(iAlPsP8Tb#jlFy7S@CD87~B?{f$iUa=J%?OyW9iE9eCwX*vDCt4izi)0LdJC`M zht5;yvgOBG1)L^TChcN9(X0T=Q_D1sIV%{vLO*b7uSElfOk)E+c^?+g zDOMoD9a*hTTxSV3IOq49ua#)6Ymr^5!U_q?(kF9KVqt5QwT{K6}m>DuXz8WEaVh z3|u(rLv*Rkp=1nJ8_(;KAxMKdDGjksJR2Q1xpO$#T#!k0u0zqwL`uW}wxdRD+JVJ) zOEhOY9YQeHaYMNsm20M>{y}Ia_eWVlJwg-3@X{ojapwoG7?eXq4_W=LVhJfGr|Mg0^X;GelG2KXdu_c<*l6SCP3 z6M!#z1-a2eBnD45NyuJ`(-ihr&jv3V&qjViz3`_iZt^sT%YOE58T~2h{!fQh#To6w;XZ^d|Hq&1 zC|koFPG77?F@!_j{XJz0$^&MvKtO&LznsEresI^5oVWV7Is*}!G3oQOu${A5s_SsQ zCtzs*`4G{`@4&?1vxi~eVY}(fmvo!2e6}9bAlK)x(D%O!j^>A89$t#roqH3% z=;Y0Yu7Y#Gah$!=iH2}}EthQOl_ix|J|mIR37J^+S+~+}S9`J17?FfXlP^lbO-P<| z7_uy3$ehNYlH%G7gm*farHrM%5N%m(@Jq^!z%LX>@+DJeoE>jb7CoJF^G2_}3Ii0Quep-trmeVL}h&hRpB}!RY2QF^PN>m4|B(&R{(J{+b zJe8z(E6wn-XpYIp@m*YpFd#_4=nvk$obQka+)@i+Or zNX(>cB>qRS_loD|=w6lXylbdoXXl57?-0d!)~QYx@UgQJ{R>G=i(#Hx_fL{p8B}wK zcYOozmp7==l}nGHGKgq@9)Ig*t&*IYV_5U+GFovX_S#-A{kztrr<0#kzM>3o-M}}G z^2{C4x<8i&IIHGBjraPg&uh81@-&9lmMgyhYNA&o6j(XgF<^#6IdLT-fO}w45O6no z_1_#jAH-Gu4aBQ&dNI*Y>?)C#PrEZ_U|ST?d=>E+((T*0_m#qQ{o0>*Lmc z1Ft!b>=K!Ux4P8`^06jt!u&BU z4@r-U4fxApOuvHv&1vI!V7o@`d*7kXK}tr?#m&H89mVq|VElXfHR2z>f#~Zn_OrOt z7vRpd@c!fX7yMbY`h`U6Ujb9_J8&-WimRA?>eX1dIMD~+qKkIr3l-gTf?=w#7k#h; z9Q|_uJ3z$0iFMug5#93|Tx-1Ug8xsSH-iB4z+ZaW_yY`aMS8rJ%TkUi16rr8tzeg) zBEo`mSjSWrbJU)yP*R`5UaP_>)411;1S^%EMA5$?Bg%}|6min?8k2Fn61#%VMDyUiIqYR)0(2!@7s$Og8X6Nq`0 zD#h%Bi%M+H`YeG4yI}G3(KQV70L5GYm6YXKVhEw6pnQ;NaMPd`Sh4k9WIlmecZ71J zA&4HiHllzxqvzu$#VO<-(Y=SkN0je#{GLr?9WGFtoq+7_1*$O5Ph$c551%#PRP<1H zj!ZXGdgmHbIOJ66_4L@sH2dHR=Ou4Z5vv{;mm?p+9z0|~Ve^qZ;3a;~YX2PMF+%{) z5pgEZ{XupT?rF59xI$mqfse)^z4(!Hvx2kNVKE_O=z_^OcypP8{xiOR3MS;62yVOa z9?#joOam`{~;? zh2#u-9h}3Nuj2nRYUBDgs&Q_O<9T1vNMraWjqZ6c?GQ476$m(opG9=|gJoH1=t_MK z&oMmwC+a*`B6HaA{ctq@Kb!{a(kiT$A$YR+<9M&H>hZFZVg8OaFM#<#*l_gYM3?=x zz8@d^1HY=srEPD(d#+dKcKCyy*1_pq`dgmv`&kmyL?66&&s@SbpVqvnh2wCvFq%>} z>)_a`)aEJ5w$3FaUEMkq#scVRU7@OM9J%3~uruhD=A~mt!0eaI#Oe&4<9b91PLKue4zZx0v(jgQ9tjjx`f?r~2EA8kb#DicldM8BbeUVW%u(3QZKsS#^4cfYeG_fvn zZ`3rdQ#p0qZw5N%FX}w*1#<)^EhE@(-^Zw694-0}8_e);HN?<*a{?=D$5cBob-rj6 zQ{0y)Dkzz$&`Ag?YEj=sgx&qz#iX=32@?4HKK07bsoM@J&%&o5u6- zJL?j1!?!Yx;DU#~rnJP9!6|gLWTc;)xctAQ)}jr6|FZw(yIsn27LjwAa2Dx>T?HE}tg^RIf?oPi(xYurURg08sX+mTcXbR4&L<#RcM zz@7hs7U!$(>9e9a>(dkc)fF)858$RR&?1!%hVGxi*5C0ZL?_JtT-608<5jp6w<3rA zx$jjN>VJe2D4hY;#{z84nJw5I%-8^@`X^TrU59IV)nPngbm^usFP%?cs+g7+O`BFh z^*p#+9x%i6x7=lw=qGW(`54}dWBXxv-ocq=%26B`@qpRfF+~m})+=B{(drjzSx1hk zt!N>RM7TjL#G4!w-YSAnGLtX^ThhBqBX*uQxb4T8=@hXY4E!8Uc=~`k1CIPx!q|CUQrMLz?$R4VSUSZLmbPx`T=Nz=rnsD~Oy$CoBaTFp7 z-*3GJ)gjiVbR|OWRE_*D?QjyEMm6gg-s;o{a2*bUI!aExR&ohyXnE8>7`NE!OMHxYG7Au$N7x*%_Et=L7ks~;4S;0yBOlOAPP(cMsC}aaeQO}~4fP)=B@!hqbjArph9DATk6`(=)~`{0LkG8#hHy;zTn#@*`IOH{`NzZfW3ed8 zhgnwrEF8mvlzjMFr(N?(Szd+FpKMcYpiQ#}J@xNw3w(3*&YY@<`1^O{3g^zeI3q6i zaPYzb(dd^w&5kqWi>En!?2ez*QV+KlICCEVW=Zd`T$IlhF-G`x!{45PBbbE~sn(xf zD~hZ6NyK=AO&c()M|KkbJBe6w@VNT3(XD#Jc`CF7I%iee{zhXBQJqZFqiJ*5Upt|8F%`kQkv*vqSI7c{# z`36<{9Rk8>IG+?*)wuK<9HWpJC!1(C;H_lhxxXO&hQZ>|=RKBLaK_MM8ABJ9WN@_z zsY6ku?K+%7z67esbz}>j8A2YFcGgGD+}sRw%Z&5!sO(dTW(h*6Xg2y=zZvq{;!&YO zhak{P9J3z9!}jw@Lkk7y>Uwhq+wE~Zm8xmA$k8m7E%`+~lf@d!z7T1l2-C)U_d}jAt5BthFl?*7?A% zx^&<6BD&xCKlRjkX6HDZ!NS=2>;6nZ)VEp7w+l!H&)oj>TToo>v$(7OgwuY@9cosJ zJBQO+Kxi?|)clAokKCjSnHK=pEH>egFU3lFC*r_A`~oeWasQ8S26G#+vJtBcVkz{( zmV5~I<;6Il3-{sJrk1G5TRZQgJ7EL4r!ZQI;4FC}ZM`5umHqjSE${^T1U#kp(aUvI zyQj4TJlNYHG`vN7)(}L@mWRE)0#Wyo59r`z3wLQP40YS4k5fbYF4&|54n1 zb`CGlzQE}(;)38}uew^%51g6wB51tpWr{lDrZgjzI7Q~j=*s`C@68wfJ8x2>&+mQm zQ_QN$Q_eb2xAmtrv$*&zij0a44M$CT-|1=dkL2{o+i*VXb4t1$oJU3*UIlY8*HS_7 z{yA(aE+fHM)R;PX3>&qoP*u@v7!;IC&ID;P&^98>tj?_vXW;O6?*bVdoCBAk!kmK< z?v*qV@tlD_w-r}7gFI>+Cmr8elpzd7&E(KOIBTV&Ggj9RdIr@9*;A)-T6rLvF9dObyO{ zL?PUa_DPKmpn+4l{*BnD8@0@O9NF;HgW4lFUq-P zE+17b_*jIV?-D~vNA}{-hSkp2teM27@STWD|C9+faXCiDmMMEbozCFIWxCt8?!p1$ zV5edCUWgN{?Og`#gC#TyPx!@cL_g2L?Jin8I@Gz$7nG)z;Z*feT3+_@aS%j*i;K1f z$93(ICHfKqgX1V+hw=_h?a~I4G?#EkHX!w6#zC$>a=^=s(p=JEjK9R0*h{PM0RuZV zx*kIYz$nd;oAFxYKKo&i&%nW~ynMg~^7k@VT?p9IxW@Qe0m+h3Z*lTV>dlP+u^NmAiQ`cAg=s!%B&fkI0Qs zC(#u}UhZ_^kn;~?(vZMfU- z_&hD<$;IJwpuK<E-wSlH4jGj67Hriz$9H)BpMT1L-T#4(K%Bu8w(HQeI_tlK z?Ro_p_=h!)ShAeMA~?7QJFtbWfE{utX!((8T&x*fs5xwh4foLUgJ_R)!AFO5!0dOv zV!)kqj>*coyf7Fd%IPC#1#Rr#o^?7eaNv)1u`tio<`>)a@uONYV*ADrP%)gh;YMOn zuVfq;qU|>FxQE{fQ&Cr{>(jUCLgfsj7n%P?M*rY5zWN(#Ge+QKw!V&J=;as=cnBAG z_}QAN@X#4&B}{|C(G0(i(`Js=H~yeHAMV2*z~{{!C%WwSaO@ZA!haC&zxKuY-iQ8D zBO|8D;4FygHkjG!ivPtMwB!2Ct8=^PSBUO>DI+yt{#GjfdiW+?e(Xq3e%izNIC}VP z8TD@`X*h5D&$xk)WJ1){e_3h`(<&uZ*2%32Rd?R*fzznlKwF=#8W)tog5b;wdmOgE z4@PB~su^MzIftbL>wOfV=N*}Xj~v1Xl_YVYF&(sqCnAT`i6{!k8P6sJnaz27{UIua zXil1;?x&JYVw*XDP!ftWk4|IX=>YP`>BSljP16#XwaMNo{aic>H&4PP9vE{EN1bvu zFs5i8CPQRPo6ky?fIJZQE5llvQ(phd0wR4cQ@%V%$k_hgZC+4n9JDN)&ZS&>;4g@- zdk+sudSu0}fVA>D<4pGi4EO3=we)lBZ*hh0z&hQuI4I%r4Ffbd!)C|9@6W-S5cS~U z#^2I_hXWhV3TF3MDc3JwD&T#?Sv0R>-m^?KQ+b*T?zp-if!TN=R>h`HNPVjFRIFe& z!8Wj87aA|1Z{xK8@*$$P-$L{%1l`>;^u*__o(gBcF~&9=@JA4k4!~I7I%>Q^JxfRE zdl2v3k0A3cSgQTIX?bc@+q#?;tj4{qPCd!202lnPU?Z=^*1PC2S~StOC`wpyl~S8< zDjLSkd7rI)g~H9|$2INjVbUdJ00-WsJvVk3YjH<=wwAE8daoMnwTRyD|9SikAHMln z`hFn-;cd!U0UPmye+DOkY-9y4&bsf%dm$wF+RL;|yYdx06{!n$5*wixn`q^&YJfNW zFpNBmbkeKMW}Y>eL$JB~_w{{OK2wX3`;iUIV;NocJ8C)}f@8S&*Hx`;!w=x|-@`IR zc#j`H_a<<|j!R3d*D#Jv_>6xcnPb@Wn(}EA_p5`bk9dLDa-;jock0p{y3tF@UPj<; z)vu{kOc-UFf(VNm*=|7}m63LE68#Z&e<*tFrczciRw7HIlFIoS$gTsCR5Pa&2GX3B za@uCl2kkq|74(_0kBxdyRB8$^)yK>c9JA)Mqf&o)gY^a0Q8`&$kDQz9a0I@?@LQ>; zcr-|-d~2ykCeJyVw?|4Q1h4OsF&O2Rm42G)1Z3QvK?0dfUwRg2cX$qC`x`A;W4&8j z)V;w`Yci+mkf-*T7vKbI7c@@cN!QQ3o7zsT-)cv=e`<)7IyuPX5yFqcQyPH zA)nB)YHAUqpnY=9tl3wsystG z`w%|7u~UT%r!{_w-sAzqbh}?}GjaHSAHH9SZF>l>8^!AT-X}Y6^;9^6l?eJyAzu0v zg4fscaqY5d44cy*hZHis7}Vt(=^7ioG?kZ;YXfiR)BlHANKVgY_VGoolE}yS@8=BG!D34x&Bu7R?s;^LeB3@jnE| zaPudYSg?~!s|_#uYeZkb#<}{BwS>lHCU$5px2o?X@eY*C6jv0`9x9k*Xum3gIz-I))cZg&osQ1hH&_cB3VU6+lgVHtO;PG zEtMWm-RlwQ*Oif$XIc2~1BO?OpiZgXy!%ruI$m>md z|FuM~#_0^qErycvYGu}E<{#n#vt~sj4!)|RxNJX!Q~gE6TR-)X5OF+h6xEOG3^u|p zz5{lY@hdk4YKpEUDw#OwJ76D9V#)s;m-BYhV)EaP4ttL6fAUI%O5es(ZP62#Y_oRV z2XVn)3dgg4Y?;i04J;#onrC$(SL}m0dgo>@!!tSh=dw=!MT$1!K^Arn9L21Cwr&V! zC7nc8(St?1_WM-y=FV5jASG>hfldrhJg5$YB?NdDfoBxh5Rb!7tc8Kz^kdqA8?%P+sP+m-p`YqBniR;5EF|7bDwv-*8aUfRB9W_jRc9vbP&80ADez(a8rD3eEilUTa}yqQR5@uh8BZ zA2#>ACcjBWtaqLOF)Ihm#_q;zc0K*&A>5%mv27bzQLoz7u?lf_PT7DN>#H!mPe@-s zhVLJN1Ng!PN^5=nf&X{10&xcWaqYj32>#c3XFNnp&k7iu!(ZV7yog~Edo(6lmTeSE zfAm_3Q)uwulSdGJ6VB%-w%M=UzD#Dpj(|}N9L1jetd@beJj7YSs%PnQn2v&@hRh5w zmrMBn92GGvjg2}lW@Z>=hcO64xcNtP;U0o9?O&YOHtuerbHUY0Qh9GXReG8IAPldz1!) zvzNPHt;U@3JwHrsTshEm1@!`dJc885O0$uft z{cp~U{!G-%n2G*w+RkD6m%>DEoJll0dMKF@nC4M@N>A9#aQ}%7IImG&dpCSw>F4qM z4mWzYy-t&leOSZe@LQL>T&M5@%$u_U4rppaIs?GLT4GrNufd)F!^%w$AS?K!f+)_1 z2IBW*9rqd)vd&wKX-qGbF+Le$EqCTemKn0sh#?7-fc`o*NyG? z0<6H-;WGWkon~tPA8`cY4E_@PAF(lA%4MIWc!dnP{g0O@_1Ues2kE16u`g#V>n}I{LyY_CuZ_;F8cc{*!7PtiN8x zZrJcY@@{nwJcP!zb2lo7`L?>-;+L8SOjp^fP}Rb1m(AXP80IavDctoT+fL z`y@8jRqs%Q#*#5b{t5H*T(0(6|GKb#i_xSJK9esd!m@I~n z4n#0evgfX{-`CpnX6^TJ`#FzZANN1PG;<)zo3O`*{cR$O{u^fW8}@t4qW@1Ey;G@h4e2e=429 z5!}z8ZJTg?_tK3LCRO^Ui(r`Zjsdf!zHpIF!#4I}%k?~&0W(X(Zo6EsuZTg{mO&8p zZqmie(SK@GsSFcc|8gxGO+2EGffo{|yQe;_eFLsF4qc(szq1FlX~kIu8_i8H@JBz2 zyLvAS{uZ4D*!PDv;EDGhd4|^WC%%EG{O|GqK8@N}!m!`_6L>#-?gl((;0kMQ;eBcq zO^4gKI9q;_=-6LtM1I|S)j@Fm^}%1$rWhlZ7@5Je*pIa&BV7g9cSXvJxJSMh*bRuHaOS*ot3h=e{}OGcjz4Hwfsx8_sf8nVo)8}1p+=s24GiO~SG6ZFeviI3wPrJ; zcfx>~2;f|+2A-SJ2mjuh&CgM1#ZHFj4A$JB&0se2%rC@~#XLj6nE@N$BOg^{#gcUKKN!WPw`9uXE*^(#7=-ApPX4-@|&!Kutel`oAw><|5+T{>l7)(P3#zL#L*bf zFfdG&XE1nJjUlB^dF!n(a4w2=UDR)g=MF-@A)XwL9YfG77%(T%AC;BD<7z4?s{?6V zHOg(<5eg|Fl7b@$rKiM>trQ?^*kvj!Hk%(QD?-*tesIKcmG2cyZ+aZ;$rB zDqwqynB96N7WQQHZAwC8> zx#nSo(oYTRV&(MjPMq=|BJufin2KAG%&ZLrn@@$Y_fZjai6DEnPX%6&a6F$xV7&>!#`ViVTzT;_ zR}f>98Tr72WZu-D*1nvnZE*^@XaYwElTIQ9O=}U<}cJ zSA=}njOc0aA81XMkw_fr@TPhAw-htY{6su7$5A|QpljZ(+RgX>qLSb-B#<))o<3f{ zin{n$&$YF@sd;{3{-9l+L1H~G{ zfm*`y%|gdG>F76vIfdS+gfkG;_Ja)Oa8yEy)zU&l-_udznU13V@ED@{sJ1V^hmz2w zJsQKOJSSuizN6M3mw93aS4Ye76g^d6qj%_JurHg z?)f4JU9et5WEF!0p^isU+KePL7=_CjbYO**tM0TH5o;eeJsn%^=8@BSPuCK+es zE8EcmgZ&eyqfIedfEgi!Op3EJywsz|-{zCc%sF|1$R; z;F4X{mGC+DR@KY>I_IFyt(+w+5d;QI_;DBy_SpXM%;*32j3;^QNyau~j3dTj92sM< zv9U23Y%(GU0TN&kvO=qcTIyEloL&wU?me^C-uu)&uljY`uRMNgRQG{Wx^#uYKNCK*9ySQK{ZEi>_>5p;DvZQ6QFV$A#Xh zBPn?!X&g4bLXk2guA_0_TzRHLxE!$@V_i?#cga86#({lBLj%S;=w@Wmbh z?qm1s44DC!?q9EANP}9Rq)J*nNTn%P!C7PDSi_7$>|dZ!SYyTE zwMi|4iaJtHcar>k%~d3KG1U_d!%XtrPQ3m!&mWTKIE5{x-wx+U?>xH(pzAFjQH4!} zDxuRi{>|bASr%*wK!~U{qS_840=NWnw)4LxwSxOJ3Z=}_={Nh(&Q5k)V6*I z9KswtpL-bZ?ZYPj7{2KPFa$pezjfKv1*Xo8^EOsVdEa> z#glo=Y6VUeJrOps+S@4EOz4EzEI7$i^Sk!t#T^Dr~~yMG@D{-%ywrEAG*=pZ%up zpB@yAmo%8YI$?jz^|~-^MHnj=Khsfuky)@j#;@SKpZBRMU);a;*-9nFztbT$p(pbh zKW~{k6P5X#8H3n4JY!z`j2VW}pPsg1>5@y zqUPn;=JbOKC0+A8jY8?QGc`ms&^52urb=Pd?r3K|)1*wJauOh!PuAR`juKO(XW#(# z^(pF&>+uBnx&D83-tPVPn*QAn2kN%ZDqw;j4l?_0e7PE-q1{?LFF_7r@LDyalU-5a+?M>+V{Fi^Yb~a;*WpdvL-Fh9a-%I!7{12Yz zL~umY8PBn z7j_Va-8$x0JusRL;O=lD&qucMMwl-X&nJe;|g3l>QtOc-dfaxMC z`GfDYq4qP{5Z1CT?{0j*AA8AO>aCiB4RUt6Xg>X|wPOK{|yH@8t zFLuKo{5dVK6Dh@X7O4qVz2G}p-g55jSq5pbIo1>6Aecxi5fMZE$#a}o7EwqeNyHG- zOfknFdln)>sGWQ^lSBs1A?3iEweafdr*;^E9GNLrm zu|~xvNvIiwz6IEiYrBsM%uJ45Q863SjxYan1rH_4GLpz4D z5thb$fEtQ}@6p-HQBgAmB*tK?Mi%Tb7_`qDxKT}*^R>6A(6bj{ zLGc*-d=#G0afDRcUZmqUzlnvp?cbgq_D5=f?(Y{d1gymzz(RS^m-RIlW%LTab4DQb z_EYFU#BDT^LUKeL)qB!I!>$@s6Ke_SFq@b<%1o)x+CDb8YS_%Yy*}!y#`;!q1hphW2#chJ7NhF^=kYH$x04F^eE%q$at3WBn`8R*+CNoiiVhCFXgV9aeooW3 zv53qX*OvcBbN&zgGVah0MZ^(MK{OHjaF}u#+Mo@jj11_YJn~lUDd6NkX)wcn25{?E zz#-{drVXE0yS;6FkO{#3d5ud>A+3|^<^bjQceq6r8Bg*Y2D+BNS6@0*#K&5SfZJgPq z%wn}gJ$UGy8?g+w;Xt;|NwfR6EP8M=OP+A&9&mGxyx99-oem8sKJdY%x*CJU@hz{f zAH&JP);o$SWoGq*UT2`5#rf#ZE`o+WcgA=^Mjm%np(*bvlJqBvf3eT)_54tud)J=e z=CG@Og($LrN1qIGT5=$!#%fg&ibBn%wxL}rY(y?G#~BM)eYOv#p@!D!v?dxeDr;%u zcS%tT64F?rFjf|$SADOhq`Eml=&OByf`x|tU;k#UW3aHDe&^}@d*J8PBV!XDqbNx` z{g-d20Z1t%vP$y0a|@iSI*n5@xjf1HFLf35bZiJ~m{QN(!f}@_DK;-PrM%42N8BGp zaB~v>21`;#rqXe%F-)6*Xu68xBK8i%hO=f;gXl#H`Ex`I|2!jy#r{#2nR+4mj18Lm z{{UBgxgwD+{}n|dO+Kt1Iim>-jq|OgXlbw@Q&+@#b`oZ8I`h@ zMrD8evkKx^`yAZ08@1lY%ex&ix&Mzeav(?8?*FDpCBjeH`A>s%)$gcLkQ6SqGmTri z<;BWS@Xg=RsDMT3=e$SjhU|IZzS+OTbTjKDMDzs%pl}X(>>;94Cp{3Pnz>Fh3T$Fc z`yZapou$NVmGMz7duWmL5I&#W4&8{$x8lw!8A>G6ax#RUS%_4c!zy?y4(o^a$rvJ8 z3HL$D4`K!VPh9pA+dl-uu=Bo!HSq=iwnE&u=2ao%g8nt0-bo)tsPd7mx?;&8hrzP*Wi|dAt>I-V%4qWtmaXp@oi~a&cya(WPZ2H0? zH=W)SIaDY}!vAx-Mhf-X;@*IC78^gB)HC)jL|D)YuD?}_-FWsvJJvOirZIlmQ%vD>=2&BxUDIImH{3EZ?fUCNVM_tux z&~R~XLdAZ%)D(Mv0wZZ9sh!+a{Q^Z2WuzFn*qO{@TW@z~(&`7N%_vN`iUoDj-k(Y8 z3R6ACAvTb;&XGz=BZ+_B|H$FRZec3I+di)(bWBGI!Q&bzjelpHL7!2y9P0s0`!t}S zPrprJspQt;>7M?o4!N1brCR}yZOK&%1Yy+s_+Q|?7itaRaC-9PRKUXKD@F5HYqhzz&m@@@9O>;@iU^~NL;3s9{JxY^HNj5 z4>!HodX^s4^++d=^+iHr2~n@*y4DBQY9X7AqxnUm^6c)HxD5UQlb*qz&$0WX&_U~n z#+_4%o+c=9)POs~3z3;$yizaq%WY8EJQ-7A99|9MFoe@O!=Yn%@67S@7=s1A*>|Eu zSm=P9*<4q2IENUusNJDo!Imw)qV91||qDTEV!lNJ>`6GAA+$23&VyLM{*=rwR2 zCa%WcP!WA67O`Z~;rx6hgo_+1i^1nex4mSSHo(yXA~Gtr*~b&*w)$6TltDq2?&jpy zjr{`_-Fxx*YV87L-jux#`9+@aKmLqj%?G!rVPesG<#V47HY`o~)ZD`E*6EjGKy)RsNB<`H|a#OIa^k7Dq3tpn@?&3bGEJV3YQ_@E0SYaV@f{G zHy*d`p0f8(C7(|vwTAg5trR(lB7`-qH>7E$bj0RAqklo0CE1j@{^c6U?)wdu#bfZi zZ+@RfwFGf6QO%Bg%FnG(kcZx@(F3DZIy6Kv(Q~H}q4!O+5S8@^48`$}YgA1+Zyr&@ z!w8vk$H~CU{gXul66BPJTAi|L9s zAa%GxH|Gy5qOWjCPhY0Vi_u4`>ednVH;|%fI{6L0GX;r$C%*r)Uvu3FALLZ(;8b2k zKMyPE1U}ybBl6ogL3=HzY8 zZTsvqG-_S}KYx!4_AqY1_aAcZ3S8JnAdlNV>CT?=Mo1~CvZ=i3HIe->oa2BAc_XED z90y3wB8I0CB^4X&*1S*!a_Lo7?l%6r|L0Z6uX&wDAq;gl{>zIy*F*2o?&R%1t=l?& zyB7H_%;R5}>Y*2z4>S^`?@j4Or5qc`8cE70aubav&ykioCAzC-Emv1R!ak$N9*sdr z(nGO>c_vZj)2?b_tJ&*5+t;$BC>_c4T84FtoI}kdI*89_Z2M;tG*ik?G@Brk3`)~2 zLSIPt@w5MrN{~g|87RzKKB$xslv@^(DeF|uyyqwH!d2R>^STLdrUS!y;cH%?5N5t6 zf``pxL>aB6d%CSk^FH-HEoc*+bo`_EEpE}WOVlH$lXT=m&OPsQ%8$hLL8Kk)Xq$da zmGkjWsX@8nZJOeox6bNQP~bzjeOJPO9mO%XajQ<@SU3HEf-D~TRUHA%qB#GNLySdb z;Z(A2>SfPC#POF^`j%^*#c(=aG?W(`6?Alklu*{$U5mH@c-R;f7pe;GZe1l)px#@bB+c$vX+#x)dv9KThG^P5%_ezOc`dg6Mg#nV4%y*aZQ zHE{YMkxQ&A&`albWa{Aabz0#5-%WPMk#bY{7916u^bL*H!@N>9DBb&8n>CxX;14RSIo+X*=_Jr=2eN5aZ zkA-A=LYjAxBg>jvH1_1HU5v(uSq|8t0Z7;It#-Ubr<1+j{-v7S+{}jdm*XwQ^Y z?|m8-c`TV(SdbYw=Q}^~4AVoV_TG(f>Pg7dPvW9&#Ep0u$G`I~w=lGkF`GE@k!^~c zphv>|yIX{SOY)5aT2qi&Bm?S&bGGt=Hv77U%iIaMiyA9>3cbIiD&wkOQB()}1%`KB z+_@fpk9uyK|6e`xi3c)77-dg^*Q(?`Dt!+F$Pt&hjKS3J42vPi`$rP5J{EQddvg7K zNfa=c&!bpYkm(H6x{>*t%hM*mGn?=IBY zWz7?g#Y)IPef$|31IX9Djm~|F1XNg}KLVq4=tY{N%V&Fw>m93dzZ4%1DP(Q_^x3q$ z(P%LB)4x%p0z&f`vZe)Qi5#w0T5E=>z0kjde~J@@N3!W=gOdKXqC1{Gr7ve5dn{J( zF8u|DVII+mciaA5hW&bJeJNY`yRQZhNejH5?iNS1!9NM*5*s=_g7^Dys>`rNj>24# zq=5Q*lz*HnANe^J%RM9QlAc73?o~_&1b!m(8F2 zN60dZtkbaFgUi+9rx96xy;8N1CWa3-rLiH7kprQmjE+g>xb3HOAI#a)u#jr|rgx|@ zVY4MW_SxM}z{B1*==(hOIb6D%U#~fRMjJB^EAu23UEsjHd0&d9tc)a!FDv1HVe}_$r+zNZz#O-KeHLS;N_zT$4*Fc4gw4QBafb0D! zL{$3+b(Nk=Qn^ClTRYCzn#MicvDYmeaQH34ttrS&i_zy^cj2@c=ekjxM8Vh0Go$5iwsDSAvzR$^M zEHZC+iPjXlb_YVc_cyiG|LWgWyfzmgp?u#84HA_M5LUKxqW)(gsp6J)c~4wR>5SVfOFe!RI~#L%4jl4 z+oZ>vlE`Il;Vk1aF>3V$!xo9@;%wz~mg`LF&F_1c)UNq%*|6gEn{5}HO$&iRkD z?nDYb@z)jM9;1Sl*K5b}%u^RnrOmsw35Nj*%|Et?spuns_ur$duWR)OwQ0| z^VnW^-J_QpFILcKLTYHZ^rKt!JEV1&^vmz5(w7FaFX6i|4g;e)J7fTg_@Q6a5t$rJ z#r-qC&uE$jYN=J+rCrcWF)e8;kjyz6 zhqcyVma;-Xg1^243j*8tkq1=Ls7Bs=gL5y#N*TuGnz~GT7~0Tfe~Vz}e}1{b&pkWF zz(S$F!$FZw!_F<*C4G*NV*G0DCy?s;GvN$3Ho$l6)|LGl zT-^CxxN+FW(36W8Cyvmhf~VjUqs*BCi$O^l+R}R`DuGb}>ju(L)2zPF!c=2KJtq>$ zZTP{3P*Qq3557t1vafiPqB^8cp%K0ROedjDWQZUsyn%=J6cfSOfd7 zA+&{}?`vQ|4@#cj*G8f6>yr8@nGS+6aDh07WuojoZ(nK18|J^lFuud^2g)CJiqQkz zK1m~WQz|Yg{b!35q8CeT#QbrJ*d-<}NxxM?R`onPXlb`6F$Y|VxB|BGir>)g zXh|C(I+?_Nx7hej!eCjKAS3Xtf2T+xLR)7agETy)g=(%jMnPPs{Kp|yG@yJh z{OgsUi7c%b8x=sZ!#0&p|II~o3bP!rS?vMKazrR8yN_|`jj@H<362{6O9Wv*w%2v} zejk9%J&N!A#%J~S$8bBgf8DvaLznHs@2`GBrEh%j*)j&Wc2B~%e{9S7qk`ycztr5L zHIIsjUl{2fBex}ro85GGvNSI?D!`Kb7%tpB@H20NeBOe4{s{E<<~tOeu<*cf<@=Uu zo|2vpkqe#XxoLS>G$y(z7;c-qNO`@A97-egf?k&JlsVMsCUEhQ`SkMF5(ej`SbXS1 znY7$b+@DDl;TyT@Ou`8C)m?@a=Mi#*qK3uShsXd1pgsVP2L=FMbOx&tI)m6R9>oY0 zJH7l7@$^GBXmtQZ0RfwIT-Hm|?cGAYrNTvO#t@duIeNcRjRF}9z4kcxtclmB z<@iG}hS!J;!WbgdIedQt5gwk)Y24>|+%A09ZbQK}T|R{E$+kO?gA&d{a8nNkxBS-9 zZbxObSQB7Mh~2<1{E|XBDVuE4qE~#$Pg*_UvpS@SMdR)N0TQuF`wLdwq=+1P+Gp<3 zPULx9#^skOLXGmlk(f;PFg3#{n2LY$uudH$YKX|XC*SVejqgy;zH>&`3!Ny|4}?(i zE@fQ3>=46(wT2SfJZdn z-x+~W!rS-DpiKI-4JBh;U`S!1ekg%=s)rp&VS-4&`%JdUsKbR^^$3kZ@Cke>>q2CC z7gNsog||L65Rn8f=JaDq=+VR|M5N82!9`glzSKl#Q<54g6Xjhd5Y(8Hk1)Uq`=Y?OrF4Piv*DrdXPZ91bud0ea)h)LTWGi`(>`%%W#-VrX`W0>JfoaQF)9$|)*Emx-_-NYE|i}6?D{F`sVRZ}u|={NGn(aKsyk*mm@qhs z->i8c>9?{hMhA!S{ymoVF=_tvmAVQ^BtS_%iOaAD!P0MDtwVOUSo-}CF5~T6pABPx zgWikfdFPsQcN*K*#06uV2feX0SSZXaSk1;qaJ3i|!oHg}4+j|e3mxpno zegty78yEK>Zu{el7#Ui+!SxW{*kE>tbtUF!LrF7R2%;40>S>KVrD|k&6=9`VbXNrF zu3U1tce4k)L<6VpfP(0FD0Pp}G;;%M@w#1eGY4z%>}qZZF>#ZmgM$r$dD45&8ZZbg zZI%jiBN~b@uaD1|0?Kkm2BY|XLyNvPMU1aAdj8&0KElU{zp)as#0Ui574OdB;RpFX z6~7t)zRr5;0=;RX*fkvc1)ehR|A4Fd0iuWQ&97K%DWTm~A6RS3yOG=gpCta;2^4kG zRUN@D`E1&hcW!2Xg{6vOhw%wlbu-7b(2}I!9C`}NsZmHFp~WKKKNn+boVeD&D?-+W z^mtjfAy&k%#y!DIoigwv9_%|BMU>HS`rcpJg3em;49f;cqvxH+Bg-v6jbBc?SuJA~;L z(x%W;XWm|Bhv1Oc+@wWjIb(cw=>19qL1li79m1R!zC)wu_DN0uyztAquGj?0qBIM} zOr0{dN+b_wgWvQn-7l3ly?bHxg;RCuuPL1hBX-UhVKXKjt^0pLQ&KcgT(7HNsq+_R zU?6f__WosB(|F>oRnW)%$Dvw`eEda1NlTTO63RRO(jwrPB+Ie+Zj%D+dhAM#5SBlZ z0Ie;H@s~KIt&q~o4yhzknBNWM|Fd6L!*ldT+$LNa`qz6mIQQm{RK@6bKF_)5J@qUY zgL$0DyRKZw(6yLrNGjyK`&AG;4X z+Z--nWC%BSoX??05oZobCn5n*ET`4B!ERNR|m z6fo*a-|w<8qN$w>h9akj-!E>P56S=P9OPUuJcJO|F_( zoc9!?gR8iLCK41;JBbW>5k4_hwA9j2k(Ve!KGXD$b5*CbUj+Z3@-X#|-zv^B4tgy! zyKX+Yewi^L<`z9Lic?Mm@0(gQF14%KL%}mzkYaPtdV;5sDAm}q<`6pLxRs1B_>AAw zrXUh94wG|k=0M>ZE1Rx)qJ;8p!wU{>V#vFd+?in)!K*j%du#^&Lkp3@y!fPj%bRi!JuJZF-V&aFA(8R$=2GFG_XPYV zxD~G?R9O`!>7vK()>P^mXt?@nt&fqnh{fiu|549~3cE=J-PM{hVqJg*;Fmq71!1nI zqaW0{t~ZDBa`p`s-}Hp;MEhjLyuw`+q5J9iFa!KfT*9HKdZx~NS`r(SPc-b z>6%yQTmtq4@oJA;qD;e&{ec=MfsN1W><>mGoEiQMpriqpphWPW$DF-i_<0M`HV);! z^V3x|>(nh!KajlPCwj6IxWs>o!@7mR*ctu)6x^53;1u5UIsKg6MH>!igV{86*bnSg zDP<3TZU$}f}(+zBd;ey=EpAN2drsGB~ zWy4|t1?=6aF9kOa191}W@A8!juwbAv8s{2Zt`We*H>wF{t6rjg3*;_Yw(r-pFNX$(Qw^{BRi%=Sbkt-zz4Y~JSeWadcu40rue?_G zal#rtWxx)N!&j7+Li&CizDR(LM#yWs{p>$3|rbyq69YRMCOF?=P z5GBw!u%{t3<++q1^n@lJ{J7O6rp@h|bDc9yd}m&eO1_3i-f;sPm`W<$%t06+gahlp zH@LnvFcinRZc0H95q&fXCB5_Kw9dvJ1)lMW>y_4m4Q7lS2pxUuy@ohq55d1xsteWy zNR7d%fzSQ8LRNVlsKCdMX@l9uAJuWUoe6c+IE07u6Ugw(X=l^W#`R2lB4qzFdRN%- z&(zi9@6bMj2qj%{oz6&@J8JDT;o=OzMs+Rx-HY@63V(e7h04s?`pI@|Aa?juCAWBa#0s{5soza5|b=z|gyx|7fO zP8owjiIP6BL*1nEJW$e(K}q@d^2c%hr!TN*>|}0@I|}8!?!hEz4;O#TUxM}hB98l7 zi2KVRi;uj*yA5|6?3{T-p(Wc!FU7l6JII&f1-G0Jdzl}*{s%I*WR-VgkL7M;r-#7h z;_+wj*jb1pK)W-?_XecHmuFfQP~6g5T$2=!FPOI}v<9FazIgqmyemd5rYO9jTVmI;&n?a6x|t)Z z5+{vfR8ll9Wi&1^XCJZrr>z!n!V1Jk>~XRO`#+G>2ew#!V2jlUR+=G5?|LmM9H$un zj;kmj#u6NVCsFvZ*I+g=7O{{V2j{F!n$Y4*gQITYJchI>E%oD4;}UwJ1ea{Xo5I)Q z*5@k1@OG{FzD5Gh?xo$+pbx>G=-ss2Vo@Argu}XvLEC=6=5ySz7;5KX9E5Rg8qY0F zBheVpC~z8Yi3p;_)YF6@n#y8I>J>yNmGf=afdMII5n=W>p-f8z9EIEZV}+aCU%L5| znIM(=SCnqW3%sk3mTux+NCCX9rAt*YQ{+i(clmFs(kC$-Q?OL(G!8t}Ghc@>csE>w z|DuC%#{Wt$Es;pXNw6*;^#IN>zE`2yG$i}~Py!%HLA6Ln{X$LYvi3lcr_x{jGUH8} zwy9<^EW`1b3Rg5pK^Z2_HkX4iMZ z7#LB~2X9achZX06k}^(bnTf0=^X%?^=mHhG4VpQH6RI(7zu#RLt@XFKQNMq^cYRnx zKYkw^8H87jlWjMA2to>(c07We|wHcT=?X|u!E3q~IXL9qLMx-exBs}^um$m&6DN*4a`>!5K8w-VdQ`Xyo>knaKweNtu1OA@mlE9J~zGSf*-5&`Err z#AZ3WbwVPAz^-T})IE_)ZGA0;>{%FvHWci7~mAv!B=QWWrC`mp~*FyN{oOQDAEfsjkPd>mA>( za~3#byu(NU5y*2tsc>(O>14M*K^`2R$?wVUOO<^hpm^%1@6kfClxa#WP?IE&Gtnp^H+3j7i2FRzS;q0s*l%Kl$JfKxFz!&l&^9>=Qr{`++G z96=DZ=WEWr`BH?^SY0~~t6MXM#|N;Qe&KH2)-jyk^6yB^0Qcw+!jw;JIzRtVbmXPM zET}cir`$q1=<|5-%yFHBUcTh6ZwLI99lx3Tz6a;sqZ=Fk#zTGK;aiGq`&~PNTeCTH z>u{wNG_^?`_S%T!?+VV3Pq81YYQPJrp?<7qCTqdKv6}y|I(Bh z6pQ4pqn90t;&>k}YdrT28H&4CR1IJ9^n?;YuKkpXK zIcW7XgT>zzi9wil)nu}GTuYJ$w^R1LI1=-aJDYAJBu1;(Af!>kV)ca3-If>S+O|4@ zrQ7T~V!I1{Rfd?g^VNNl;&SLl4=NI6g?96%3FAE^QZ1sHBqeD{a{(scdX!5=`G<0q zri}!tG_MVD^miF4WOImqr!=SPSdebP!$#x)ha|7hyXi+uH+%^qhv6Vy(pUbk;KuGN zjhVL;sOs3)0u+CcZhjgEQb!0~_E(_g-mkRN^x8>-&A^3YD+izfulj9;pK?|KA+2m0 zW5n^$8?0yGAECam{?5eZRDhu^CdG19fgo}Wz`8E{UsuU&jpFrb5LvU?NP zC2756GWaMyU;jWQiBmfiMYJFVZbNWBbQM$*o^OgnZt(rTg7W`y7?J@<#kd!`;*&k8(3-YejXMRF3)B7Z5u0UW&?cNkA1t1fmfvEyKpaOGGiP)x1p4wHJh!` zaoHp8{F83dr~nt?*o`{2O^BKlL?ohu}7hzh;NzX2`Vm8w^ zg+V!~0K7#6;__!*$f9gB=)%{WzG2~Mc(UBQ#;nRsOITc(QmVYwE_O(25#36$rYVSC z5vU^+LO5kyjPN~5xL5uN9P_)BM@r{C#$|v`PWE(*LRK@Lg;~?hMvZ=B#k6mUQ=6g zPi=69+)yCtDn(ZF!BQw*2>;~ROpezitdtx(orb)wGWtN_E*W)c}U?0;n}|qHm}e0;YVOd8u-nv(4(DI+M{sU z9nSso4bHs?t8VGIO5ibk_C?sYKm4>x=3(r29WKk~)_l8-0dDhySi)aerS9ALY6V=? zFJd5p6I}nWh{T2U2SDUnWU$3j-1Vs*->UZ}r0+BQpqiO(6RzpSyRHvreqy-`S1*C; z9cG-E4<3O8tXZ1p#8Rxx>TV96@0nJ^Wu45;m;J8MsJZF+h9Gw6<(FI}^#O#M4PodE zlw=llS-4|vU(!2uTzEAe(St1m{dvRkmvP}&Ir!k!Vrfw~SmveB?0{DSIw>ytSO6x% z$Fu-bzx9~=(LBHErQCA)nequmLr~;`9MWwV3^bvP4iV=-#gk>-CNlmVqVbV$wKN|c zQ$j)O0wEm4@gB$Tp2Bb99D&FZ8Z}SM%dayZA*P15T0{_s;AB0GZoa2&r|c=Xc9Q;r zv2z%Lv@3WvX-JzhLo$${g<>&zlhr;>Cbf`GQYYw3ynADI?QJcJDV(UBV{zW12Cdns zf%c(FA887xV~RbZ+f3<)(vV-SYbew%7(_L$n4;{akL2uwrJ>j}(k`poLv)3`Mn~L! zDB~H_G(r@vs*V+&+pc89Ao%JT?R%hM5Q8x*2BIuyHLAeFONyxpue~Y8uEg(zE`!fG zkv<(s2_5-RAw}PHuPB8Mf|L=nPX^&7I(@(LbY1$(+IdXAAWkyd^5fdQy!Umui;N2P z>6Kmgazz=DMw`Zfy*}(JCjE8IdBclK0?tg^){$LU=- z+%Hyo^z?PsecYP@$EA2Xy#76KrFI|I<bGA1meOz6_-^qYY;3accYUn}cwxUjJd0 zLY6(>itXO^B)lzrK1<#s99w>ubASEvZ?iGr@Ojcb%e6eu_qb|aZk53t_igyV1sVdw zh#Y~jUIwFIn@B8X%Y3oYvY@S?!-^ICqss6Ky#Lg4@5To*0&(1ub&@9WlUr+UcoHH= zuY3>^*si+<6z2>fo$U-a6y6ZR=O9Gpxj;IZ+R6N&E5yrhxH@i0Q4;Z^44qnp#p20o z!VlyOffFcwOv^AYpLxybW6@>s%*26r1`G71wt7i%x2#~BlJ-%r-(?Ydjo3iNw;FRP|vi4jb-W3`4{MNJ?l1?;SPI zA3jMqhMye9Hd4holX%><#1O1EkNZ+rv5u~D)jWh+PtHAC1WH==DBM^)j@(0WOl6uT z@=0x>nM4q2Iw|rE#rX{DEyZ;zsWZ%4A-tCKAk>orai8m@tzep_o6Z+$RJ4~5A(3WZ zH30^T=qL{{z2(*Dhi)w)7)s2%{4yer3}IyVFvNsX&;~+DH3l^VSxhTMLm8scsSJ>p zXd%{(>iUo*?tnTG?0pd!>#U}^*y$y82Qw157ojtcP0vX4TUjU_NLFjQPOBw74$YGt zae`(Z@3_H@rK_zi+|(nGIJl9uCBb#}1_4H0`@2Dm2j`8mhk$JrOeK+VmBxXCpXQ-3 zmhIAEHXNmopR#RX`+t5t77FX@*qnbX7{wb+rQq6XR&fLcaINxx2i99qZ>0fF`v6Z zDE>yL=9;rLQId5QY@zgP8KIx_{51mbdB3K5nA$0IQ5SF-G73L=r@1J&*ool}mV=i( zd}f|lMC>?QXcp23TfoHl+X9t_E*GjsBkKbY55HSc)EuyCe{1^6jIO#=FR(P@6C(gQ z4nj`L%nXZp)uQJt&mT%l0cG6+qK5IVZuo;TWK*exW3TdYpt+}WHz(Ky6G^l^qkGbtX2p6_-N zV>Ow0`{{mTFTo0n4#pCL5Tl+fIlq+2ba_u>T(AbSine26-$ACHeitZ^8B{be3Z;7E zj1;OUz#;`n|G27{EZIf9=UPBEhXF6jB5foz!YwffgMs^b#$ zTdsq5f<_LZGb|}Yp~`S(9DGZ=qM@>KJa`w->T9L?JnI_H>hEF@?D4&js~d}T=B*rg=MK9oYDd^(c5cYskH>M0I=M(WQWdQ ze(Zl+|7E7ipG9M#%Ra}*+6%0o$^t?N`J#?m828Pw889mZdbPEr||hs7=X{iU75$}zUm>}2C1yya*cEU;t_mr z+<1?0JYz6We~(M@D|dXmi~$a!iRJMwgepV+{0(MYW&g_bc;6wjh8H-1hRGLNvsK?P z@uN!ZQ=tx5{T~ZQZ2a zJaNKuq!v(mu`PK}?~gxX?pEj>N;Munw|s6a;u?m(OE76&y;?W0loO@C$dpx-hM=tL zl**7v4p}0BuC^~-1u3$qAXnHBy+v&xi^joMkkOp!qn0w4d91ARC^ip65FS?_s3bn& zG`2C0eaG>SMdD@GOwo_3_a7kAewP`8t)^__JY?Uayz?GI;1ZlgSQtlk3&L?I&U{iV z_C1O|qMc_FqcGotOp1L4!&czl;;OmJ(+PAooru;*j(f=>2Epn%-2(9%3qA8GH!pSWr|zpNW?w?AJqM-x z{r9UYa~zKQ?z^1(eLUZc-|l?k+hGi>to7k5ojcI4?%nweS}Jo6FAjW*Y{ew*;`5+*AHWwzps*$fvh0hvyX*S!ot?ScFqyf|(wdusLR~@+ z1;aYTURgAjzvWj51I+d8Gm8|uj+XP?e7xdE(?J^cU3zzX zGs_Hyn(*z*dE^TePj|6KPt*#)VpuXC(TLh%%!0DLA0vbidHREO=R&ndHU1CLgD-=6xIjA-nqCaAF2IH3s(dYzCDaLwH>ADeUXjiadNm0c# zQmj1``noJtt|FSPyAP~4%DAjI9;2(tTFC;}AdG^?>Mo)5Ink}qCO`raq{bk|VOHGs zb~fY6`HssvbFMwt!KUY3V^!e_L=J<97RszGQNqB6Qj8F#}=iZIgv=UeFh9@j4C^UWl6A$Qdo%k*+K1lXK z?C&f1?jLST!`m!36pwoTk`ajoQ?KwmsSjkD!;er7k^f9Pb|a)uyzNYz zwM1_htPccn_8A4x8_ZcV$U`@#mpXwnC2aMAOcos8W0!HE1p+w+qdX3rN6g41Mk|6& za#E1f#TdaP!MvTIkxld#r9fPD7E@segjK#-818&da=i5XwHSO@;gy0CVkB@9HWnUU zHj|`SB3FK9B0gYBbb}cHNRQubOG%+Dn#qLy1oC+*xq z4xz}GG?zpaokjeLGESaV(CXNTQgu4?$B+A=G;c-|@a!3dYiQE_RPd_?MZp z5+jA0${HM&lJ}fQ9YLuz%?q!ZNFw>2cmpx2G!&6UsaC-DU56#N6qdctG%5@hHb|YJ zUG+}Le;R~NVe7WE&6ncP38JYC)tn2jv?jX7asys;bZ&<9HVonSIG@s@2dOvUyoh4T zNXZZ@GN7?dD-f>Z2V=Db+?x*N5w{^1I;1%oWn~w&KRp%{=Mds+R;e zxfgq6G*Ax`6>zlY;07Jfnb$8~FA^JgjWw9{vM-x5JdDp*6Ff7c-)9PZcDXT?rW`&v zv(N3)w9iW)PHF`(4nK(PuYlxDU|an}b7D1q^p!UF-sS>)5Vma@r12Kk&*8p|!R^|G z$m17bJiZrtcokM}YxgrX2Daqhdl`&teQ{&pll0I{Mm<6Pw&mY+72#4#hCFy#dU!6k zKn2}}UoC^MOkf?ZY}DLwD9!m=UhnUR5W&MA!6U#J5WQa#$_b&W*BT@611_jAGJGxwh* z#a1?dv1lBXuadZhgzCX~d_v@gEA@SDM?C$g8+`ZJv}vrS1|X95^q?2e*&Mg4)CPFM12Mq3Wgz+WW7wi z@1pX4nTngo9T^(2-1%mMj9zNd!DhE`M5T9&^ZG0{4ZG|~<-`u;nDU7YV)H%CX1zmp z;`^!bm`MysqbG$^w_{#s<-u4ph=uCOB$d_Y7S2!ha;|z0tED0+veKPp1htd6w8)^) zzLBzK1a=m61S>QLOJ|Z!qRY%`2GibgW&;J*VehT9>&25L8x*Zf1=}pe)Md z^7(G>LVQ!=`4AzirPVVG!DMm~V#l=C6q>h`RnEv=Qdtd6BS~~IAjN3b4>BAJi_J6? zOfA(A3ACDXGSzJ!+9hL=umi);W@mKA4Ggs0+~Gp%6}A4-jb7bx%Wq_cvyh2`Lzlu> z9r12vBDgiz1wkFnk89c}D4yeK=|qBSFSC~qFH$td(T(lWyR__KbA4KxGFlDgoJ}YF zRygxn+}Xdm(z&1f1}=iFsLw;8PxR@m0(KA|zRJ1FzKSRT&sW1ZY&xORItLy5;T_Js z;Y(JmhS6B{lymptn2ur<{>qn>n1tQR&&(KLX&rzc_o?-|B3w`JeP*knZr9^BTTyJH zkQ~_vzS7Yp;Z~L24`e>nN}qoP?~m3qcLqY&Ka#omzTB;-L7Br4)S$GRi0MY7CxM8d z%$0~OBcBfxZ-GV9F-qowO0KMHT89cApV!Fa6Zv?IdxvTAP>V`3sIcc*!pHB#5D2ov z8@`{yUKk`W3sr)`_+rGX4&ByXE6BwTUMCA*I({=<5M>C4>`@dEi+U9yTrMdpQ67as zLu2l^gV%N6B{B1y&@6fVs=z1picHP7MhuqXk}lR$Y3G7qeOyG@q}6N_E{Hj z8N7ebet}bpk;u;o>3C-v-q^@YVgwS@54~4JWgMZ2U>)1rsF6Uq75luzJnLoH?y$iZ zvxLtmxU>2FeUBk1dg>8T1ZNVZ9*sdtPUjXeDrwzdD)I717BL?6r1u~elaD9AYgu}# zOwvLP%fr|09EU0nr{EKHT1AOn!<~Q%%0e6JsI1Gfq8(QcI};dl5W~^bbbi?uBEp!0 zN?AlAdqr01c3aGr)+{qaBk6P5iN#}A6_I24DVW?BhG3$671qyCno*Dl*HTEOQE3EC zrTWN?WdMv^GEP=Q6SP}HjS9Q?DVt&xIuLC{3ornRNNUSapDb&+Fh3_vdme@&D-bEL zD|)Ey=1vvT1n2t-w|*z5Qw2A7G`RX2?BiH)1A{?`?E05-d~DF!1s5ZocrTX=u9Dg@vZQ{FNbm1h85d{yETcGw)*4Fz2!FLC92`~Ef|P9mpl_= zV9VjJFUR@SDwip;fo&!X3Zl798}B^qvA+V}pT;d)x)Q%!8t6}D0>oPjLvX4tp0z(Z zkhzh*%r&9>`}+8WnJoT#Q-p!;=RyB z6qcjSA`aVhVrk)XNr}#a)CaVKGqb^6YCNi_zU&f}_$+$RW-#)+YTmJMyqk#dN*Y$$ zd!?nDysvWIlIrobE{5J4QYlztn4}3}I!8QtZ9)rHu-1C89baZ%V9j^=hvfK5qppZO z2we};>H-Y+vpF>a?gYL$hVyv}uh}nf4BH*UGopjqtP8C%QZJZ4Py0*gp{1Bh zAgM{ZYe92ZtOpFaip1_%QcNCq)og^r3yR6!H|#t!p&s|4=6Z+Lhmi15m}lM9;*mb0 zjCCO^sF&6`Y;b0#N0nO&E03+ZjPf`S+0srzZ&Vt>DAohYl-|NyjmeNyFw>atHe_e%(NUdjfu2{jt@ z{J#RJeDf#t5|YY#D~!$OR_ShEg1-Zdz#$l}5Bq0g4B+$JgXMhpDqVFPlsD_8SmA&C zF_nWg@F8#7?R@JI=htk-?U)K~#Vqsh9q-oAlZDs2nhG8se><;9!^h|lZZ1px@ctW} zOuBOme6Jk{{Y3a^sS!4N70`TjnaJgJ`j${9Fva7=L+WIj`_2qG;DwJz3(_g^iwI%N zi+Z2xMTN%20$9z|0R^{EB#;QauiBb(L0ks&=+#gNlrzl^3(GJI$6i!@FoHOC9TVZi zbN0*u=S*Q~Z9^M;GHW7>M#+?BaNXQ*H_ebKu}Ws0$f_`0m*6Zjthy8;v&!4nlu%n5 zhNLFILNJuR^M~+!LLPyI;sQn>pFyMstuWYL1aYIDb7zLktfSc0O8jm+wyz^91M3CZ zS{(bR@-f+DY31?n&E+o^5riJrOm-fyHRsPhneYuP)u-G`6`bxXI0>tHB`59d=>+ zmf#;fsL@RZJ;wD;pQ@$tV+jv9zhe=I0{4o~&yY9o^HxE_Z%$q%(<9u-fwQB6ci-&X z)rd7OJ){zHdepfOLV5qf7u0YZe?E)|(>}QKPcC!r=i}U!c_pp;ZWyGch~cMUP@0^s zhR@&m3g`a&SM_*0Ff6xYyGzeJU1Jda5p1LlKkglu353G`&{Hm~f)806asFT6Acqn7 zb~-F`LNh%DO*kw!Eb|>)xF&^W1m1eXyHV_a5D~#Fu4G9;#pP+0j0AGmC~|3x>d<%; zn%}2C!(4vH3Z&jVMSAg)V~m)4?<$Nnv~y8tnuda$Q(GgA)mZ8k*Ra9o)s5fA*Jc8nxx{YT{av+SvkS5-MI3 ztF8HnN|MQKp_}5A&#ZBd?`4LtD+;C86Q{;i9sJ(pPa*=tC9+2-m&m1swb_<>gQSyi zZyRJ=Z8u%kQR6UNEATCRZ>HlW<~nXk4TbY; zx!I=Fd&+CEz>k?b&rqa<6^hLXAP0H06(JsV|4M8pV14<=xI*dD>+Ybm~{&(lc{97qVI( z48XER#zcZ!U4v2|^b)czMHDax&vt-NNE~(x&;3;HHT8;>EQH7(4S93C-zgaZXz^6+ zLNLxAb38;~YsQ-i0V#6LyXQuh#C(39kb6nzuP9{w4Us%W=Br46#pGaduJu!kcV=lK zo&2TBSethWZCP{?g<-t_*7(z95%yXj6oyfn1@%JG`1~D3FjJdLX#?_b4 z3zO8uH{h)ek%=<&q+Q@8&EncMY68_Q=9ar!|7z$ND1Xl^>LpS%4q>%UY76yb5tj+w zwNJ43ei4P87KqDkx!!!NAMFkw3T1L!K6Ecn*Jhfrs8UJ%O~+^|@-EY@AeO{oX{cjS zdE|SxS^!+^0ndN~aBnE`kOMJ>XCjF3ol&0eM&Z zNgQNpB9{#AkyT>1t0;;jwPns$nM5D4aP8Hgu?Q_$vreHrUBT87u6YS#kcWPotuY{s zzBSyZ4pB=m5)DKL?Y!xH8%Ckigt@@y_|D|XjvJ{L**!-Jw{B_2&A|2#ZRofTl;OtZ z!98*?gmp6^`=}3chj~@=tShbaQ0|jZ?mItTA%fU_OpdjI<30UWZEY}n8KQ;tr}eYP z@%zs~_x|?nTHZWz19tmOc=l`c^$Ye}RDkXN8I=DIJ&d2hB{{>i6t2!VjL7ZS-|v3b zc5%6LAA!{FKI+^xN6%*rn&z|3nvb^!w_*kl?4;ZRb@^rIe&tce9KLt!o#*fc7z^Bj zQgQdgh-c=Z>;^jUeg|rjs~&(i-lp=Gf~9wD2yH*^UZ>Plj~51?OukEuKeweG3ZsKc zH^3OIkg3e40XEET4)(TgvufleB;P+dxx1Ay>QX>dM!lUo)0{L#+Z0OF7 z4&EnelBh7f74u6Q`cfg5y!Sn>%eL*oFTJX##pxk$SB7qlJ1o4k> zs-Ilq+%Mc|Mgr3Kj@z7j=|TA7hag0|G^I2IWAN^mIrlRh6lbg9_C4ZGyB9yG9J9x+ zbnY@l9=~;!j>lYwM+foieK1T9;4FT3uS#_-<53I=Gy7~N}X12kh4*XUc7rL zaQ1oEC{>h*$CuJ)=9Mxn7CD*s&Ro~i_AxC~tBSm$%M0OQGcUPX^o3UlsD!UR>xQh6 z^|PXAE7YsV)W~>Ku5kjG1qhPcl!(2SccX`@Kuh#TZnFaFk`l|L7+mib=3HqGog|Z7 zcd^MLv4J(BAi9&qj78LxWf$2boN__nteN*+giyt78e}S!EOzPmoKgyj5?*Y6SQJ$V z$Dqi^1OeTe*23e!rYfP#$yE#gWug?ycFon7j=&&{N-8J>h_v5<=Sw7>3}G4eH=-V~ zQ}k5k)A-Zb{jGTSUDA2$eX8s`i_lZ}Md}6P?(7kl?pqjxBH=WeOgfU&<}TPtZT1+a+AN+SQB#%^j7NzwcOT zsE`#K3Y&+)_3kzG$fCY>x!06!RA|s=4Q1ESXfY;84IJUSg|yPT(c|B-b2?sqf5li1E) zxMF|)F*Q6>_|E%q=bwlDZ#Wg3&b;|gBm`I~NdZ^BKmc5lBw#?F9hK#f2?*}%`0P^r zJ&T(_&}-hv-O`#D&KnZKMOI9z`C--qvRp?lhRljRPD#}msMe#BRxhWp!dZ6+xFt(E zS?KoMO7S+65>dAuw=gH3kxa8wY9Y;OdMK)k%p0_gIeeS#D+M&K*ygfkuVbz{*itCf z>&%ky*7~;eTBYQ-d#!-+OA-JUYtrW-=W%XoIFKAyN!Av?Pv(-~?NSoEd z0wbo;K}{N_ykCZAUW3!xkCBZhoy_fSGn@o-Y=|t3)GpLa>1IZTm|LV&TGSd6-m0t% zH;vabgxIJ?52%o?UP--51W?l@UsyWQDbJBar9q+Da&KsmNGi`r#5`q<5>yE%9+UGG zNxG%Bx*@Z5&l|F@FhW9Wo(x?&_F%FpD?{m!Y@LgKE@JVV&RE&C{SgjJ=ZA4kyEMYT zGGSU3WD*p6sm1J^>EnCX5MD2V;vR#7@5dQTB6k18E1mm|J9HKgCF`B|Yz?+? z^#S}2I{oBM=dS#ubN}OJ=U(+FHb)>hB8RUbDmf1K=2!Pw969SGp!Y24gUs4!_90Pd`-|i z77L0JtHlB9kv&lhxJ6bw2|m2E>%lH&=4i9n*p^#6 zV{RT*MHB70V7p#c1u2Y;NMfFhE2gv=1ai)?<5@bULlxGgu%*a!Dz$=^^1O(*3?=2q zrCH3AVmdnkS;y-J3`1kya5%3wjWuA<^_+E2$Su zB#OMf2$9|Sj6sB$&MbmP@;yc5Dv}{&RK}P3mC}3Q!^xgva?veNOPNVhNzR&FoH`AX z{#k`m=v9YgmO;0WW{OYKMO+YqtCu=WpE)Lx-lD%dOi46=v8|H+ zL1@XPfU8P2_83s1M&qEm*HTtiZ1zTNq5Ttix7n@Ry)4E}Ww-3s!a`MBc4>_ybTg4& zqI!)Wc+WeX2uZcI8#$hg>ZLSLh*S)VQvD+gqL-4 z%VZQ%Z)p>W#Da4MBaye|diUdX6H2YbS}W#C*J!j|QxHdpCsr1|4@P0hsLS>Zm2UNT z*mZEWlvVR0D1gr?cPpWuq>lLMuiLfYINlu)7Lv~GRooeQh4vsq_}#0VyBUu97MtlZ zHSFBS@!enh9Bv*Y_sMIV+Xm17>zr@nrOtg2QuVzs4g)i)HVQ~<4Sqo8 zxO_j4Q{0WqyAjX#;4$PB_Na5XR4p=u9A&P55SJxasO3Do!a?Tb6C?s1WVUzXw;O(f+0p;6HlvT z{{!>2jE+LqZ8)QME{$Q4e?C)%Us|6)W(7oFxAakFkkZTwVLlcMG8d0b-WTd!-|gg- zd47xp#ET&r*aSW~gYTaaP9Z526FMsMZQ)7h^RAq0yTMHzS6mX@^rNb9*S|`j=?nhN zKAFiJ=hiqI{UG7><*saQz`nQOS|WJOC`lWz-BBFNfEL(;rEz@d)(bTKTS^Lx@|AUw zUB05;maJLPRmQ;}iB+AzFDNQ=@|O4M;QQvcs1+<`5aRx36Qj^tg#XAbU>|knakGgo zl&p_zk_bVH$)V}mlO37;%k8%(TCQwOxV}|Er`}01zt5Ct&9ve`#V{MwAR(zF$0BcJ z{pcc*;y@&=DM)lBa!}JEvqU2bL)D0c5z2to7t|=|-?P?-(AHU#aSlW5A1Ixzg@o%b zILicB4WP6XsvLJ5p{g8NnWZ-+zA3d|ri^u@SiH7cK(4-@p@~#+D=JSGwi=I)IT})A zcH$Tc(4(-(F;tCj3MtomVJX)>Xe43LruPxKl}VPNhU?OaG~lJe*?pl!X(E+cFt+uq zBP5n(t&k?SvR>dA@IHL`cHR;PxQX{?RzOko6>iCl^N%8eK$PH4VgFmQ@Wu%rHaub# zsHO{Vy~_Fj{1u%Daq3n?2Ux9-;ZEGM*||UXcm*YW>n+Y*f84pPhn<_-0>NMF+~$ut z_h;Yj+-n|ENiNu6#`y|Z?XP~sY84!q!wzJ>gdG1a7hoJ!*Q6N$C-zU$Mb3J48Q8iG zA_Cu^iE_w0gok?Nfef+u5u_+AH@K#qw9%L1jqT)G(Cv7`VaWK?puGW>>rV5@g_8Yf zQJXaYd{=4{c)wmKs)*>JU|vJVQaW|P`&-(_TZ2m+1QTKzDoz2h5szL4LlHNYEA7Jm zs#J!C?wV(06p%}_P?x4R?EtMChfL-o@QB@?az1ecp&=h=fRw&kBaE!eLg~9b4zieh zZZlbf)L2RjAAF3Gj612@LMm*KrF3QruZwgHPvE@I~1M6}Brf}AM{ZMSfP~k^`MQwo;XW%HdFge=lE8(!XrZq8p)773KJN-sqPt~~h^_dsdRnhA<%fxmeH zy`(Y9h|Od17-|XKv`d=ABASV5mtje~I*(wzRNkVpn8CH3@1~2U9xB|(<#VnxOPb`| z`c3)`gwUu^M82;=wT03UrK$+4MlrYW+IC`OSg0~BHQJFPuB1DRKAg`IMHq^W^@Sov zWHpsqtSY9Ml)MtKp3 zcy@}=g`Y}4Wzl6ss?c_E)MpX8(PoG+>jc($6#x>R{ttJ^$Q%M1z8IUX{ z*_~uUvdApksks~mA+JICw>pB(s`1e(+<>pSL2P>(pVw(T`a5nKYi(|}aCx(ITUG@G z=jDcD?a~e4c(+PFdwBg*uH1t-vbD~IQJ=%X(0Q!ib@rsSvf*kCxxn z+FA=>F1%)3nO0(y*JW;){@C4X+EpUFpbcHobMz5G6ltKdU`;KVi(@`2YTwGUpfO=z zL%}APEH}1;Oen7f7RtdjgaS(O%|h$gq>~xa$T~B02#kf*QndEwA=&pETF4SGP)$=K z63%8dli_qBD1AZJZ7z%S(w2J@$eec3l0lSSvapM0r-fb9=Nw)>21l>y8f#{u;JFA% z>V^BVtWt7kbFx64&u4D@8@cOW-w(w$f@9?@+)c_eltX;kRFpBWF zh?)6NjOy6bSi^D^Wpu?N>bt2|^(73RYI87(5W9}scFj66s*?D7DJ~P;6>_T|ehI21T39I&BcmjgwGbT9@xjzeJ+AO;h#Lu@Jp8!UtY z0YYMu(1;k+l3J}+cfWq~bfC>JXDb_;hOFWx(!YQ@jyo@aWT-& zvlBh`|71G*McCJndA`p1Zriwf0(X)5b|_#6^tnOAYSCQpGSu8R&jRk!K}-I;(5Bq2dNK?H6DC&5QY z-i1KlNRtoP{bde*!W`XKP_Fc$53(IAd0~0Xr&p57gu|V*ik(NHvE+O*F|yMj0^ zUr6*^ehQw?fxmF&|AG67ew$DI|MUk`4PHg9^zHn!?=f6EfBN*~aan+u=PRHDD~c6{ z8%xjfon&AO_$y3zlYXDlsjU0rvoqH*krBWwn!}bdIHsJFiNHn&{+?dvKxo~9NuYp= z-zBRoXCR14pq9zS8X7zStz#OCHy||YESqN^{{R^znLl?}S^^EE>*6|*awwxbHpT-` zF9UD_C^~Ux!ibHSB}W&6v+6?UmQ_o@WTI1*#|A1$g8PU{9Pig5g(h`fYBdxgcBdm1 zayv>xIz+t^90>dC{Oe@kcTuZRk(7x2Ej0`2ww5&BT+#9pSEjGF(aC91x_WgBg|nkX zAN)acdlK`HZZpu8H+6LMrQ8BoF%ShH{sO4-tpnaOou;#-I7ym61V?;F(8 zaek8Tyg5c#0`=|1(s5?*jh{S=mosz%#|-x7jR6!ueNs0AOSw71U=CO+qx!F7B-sN1{bSJB zP|5RD@AYX{7}0D5El;)L)ZVG z>}fc-Nac;6LG;6KvOE74Cx-uzQ}|0CBYF|o&vN(|`SZVm^xQr8HN9Y5dq=lx&hHIr ztXW5L`zAVseZ4J%E_`PjL7V4!gRbbrLN1-m?IlC5=i)>b$nhW@PsX5bozAxmTB@ zA~vV0qhSV1q5@IAaEIz>gO8#Ghm1$4&Si5GA=8^5#P%f00$zWL$$+micfNVW_ry$mt&bU*Og$J*;;wH5!$5bwr*a4WKi2D{rBb=g zx5qwTqcsgTxQko!-Lzfk)_eJ0=3;w(0z|`<>U%bM@|n%|bF9l*Lhx0M9QQr|KGO(m zZB&#i!P|x5CV^U{EDFYp1q=GBe}rxW+FvGf0ic9Rr@*Bz`K&)RIn;#Y59`b@TELc% z)$EB}$rQvgR{+2mNe(IIMn0s}YJ{3`F%D7>aS+d%ECrB***c=mW!#;p3Q@j@e-j|C zZcaGjXYz!|=Hyg)%?>*YEmTErCK>Whm)W7z;wNEu(Lq5(3q|QdWIQfFm}Fg3myB;U zatAJo3tP#6C*2~_z#oh3g{TuB^0ip-_ex}11c7Ws1uyf*3;y@w4=LZ64(;Q87 zR4VdgLEA2=_PpXR4WX~y#hSlwLy$+orh?YmTT3s97yXUE&9C(r1Z|~sGrCN)E_2T3lnW8ew<3?;WkU!;Xf6eCp16*lSn4cP~P(57*&14++q&O8z- zYjS0Ra%84568wV_$M{z0F7xqR;b3-~X2;EAc6Hh2)Zzdo2H$bkI7B~xAJJn!VF^K! zgCvFHFAKDMtkX($c4V7_#z~cH7BDg?%U1p?sG*bm?`=y26^cF$lCip7)wk-XAuP+4 z!5eHg9SrWp=V5KoMjGp0WXgJWrg-oXQ4xs41-=KK;IBQZya_`Stv^LH5tmkv@_l@! zGs{rgG1#nhJ|eX(lUiLOyS#asIF{u$GcOa-zF<&Y+dmv=mlkJhPS7J?pF+R-@~-qCrz;^m&9nSgP_VKHg0HLZb7PRQe)W#L?g9_ORCd zYLfHaM+w-I`6Afg0}8y-x@xP|>nsXSn49w0__-%jOzqH~bh?{>?hzKy{lsN3LQ1

c!kmnT3fWq}n8 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

IVoQLb$(XwH@NKb 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 IM6N<$f>L~g`~Uy| diff --git a/examples/example 16 - Displacement/LightRotate2.png b/examples/example 16 - Displacement/LightRotate2.png deleted file mode 100644 index a6e63c01b721611585c5c0337fb06b0714d04d92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 173189 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%0D(tFu%iSmUvCHaDcCRA! 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

F_Ld-6A#TJ9MBb=+JbjW65q{B>VenMagW~ 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

D* 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%0DH{%cI44m`nP!5L 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 z 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 - - - pixi.js example 15 - Filters - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/example 16 - Displacement/map.png b/examples/example 16 - Displacement/map.png deleted file mode 100644 index b734788fbbf3746500c62e8a6798d2479a35deb8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 96515 zcmeEtXIGO^(=Ht)6r}~ENf)UB384l=RHP{=MM~(1bV4WeUZbLh5~Kv*ttYe8|e|J#$@q_FQu(Jv6+>#Bhy)f`Woc_x>GY3JR)= zM=FX-bQd4{LF3016f`2P+S(6wwY9H5^!0Lfb$6nmfLx7xGUqk*m|Y{u%lIQF^t$=I zgyhb$CnlD4JlDQ;(dlM<+I+zIX$^N%WKl&ashEd;YOVTvvs~gqvSyua;>48-s9aF1Jh7_r9y?FS%XHf;_8Ni(97w=H`h77 zU23FLYs5Lr*4V+QxwL9mmqpzsuJd;DZ4bh}WWln1OqXM4 z`l_C0^-~EW9a{%+z~e9l(zp_{6O{N!#w%dn5Mg6HBtHQ*tm{9JCKmkD69KSuriW>jZLit zHc7vK^hp(4=H1d$VGcE!q$CU2S8d4gxUhXJSHk6NT+(Y(X=A2k@bysPxH%Sf<6y7R z$p0~?is8duvS!$g#7BdZ+t-c*E$H0|XuljJ%%^TeIVQ@q z?lo^Q{M-0<#fMLSj-rNz#oD0V8vUbn3&UT|-k%kF7Qu>u<8!LdW4Tp7i-g?_lRUi< zCLShxs-Ns(7xshC{ z##7E-2jkBuTx{CexO_Okc*@tr<;PI<+~7y3G?9ku7Kc!6v7oGVdX!FWRku z&sFg;)!Aq8%NZW94yT)Aey{sA;1{@;!)&tbOPR!FL~pIU_0M|=90RvFhL&!C18bYw zQ$C0^#|WjbYR#TB>jca&dTd$VNjPs;T{nGZS;Q8$dF7zx+VA)sL&UPe`xN?v`X>C! zhx?0kFHKa+=T7+6^zbu&H6uZhf1eDA-%%A%x^`ZwbWIf|bj~^AvF2I=Mjv-|L#|NW^8wRc`r#(zyVGpdS`6s>e>wcFGBKQ>8$cA0nl zuK}Fr-6@*q4WKB*fB(!IOtHcZ`LB_pxgk7}vO!}*qWO&I|FH{q{_Bh(-T!yz|L@NK z&7c1la_1~xHfUhwmC;3lUx4v+2$nzCDR91rEv!ojx>)7Ty2}M)U|9NDo$FK* z;oGd!{Od4bg|{iP`C%dTB@(9`z6HvfgZi>=(Flj!H-8`RN}i9P`m{JeeX4 z-9GIVC-DVhJrAyZcSoJJJ{(k{*WF(;q6_!@#|bOTfA2uKgV^`jXPU(CwaxZ4Fy(^7 zfR%&LKW2z?g&5{w+1<w!!?Pc{6hSp~e{cS<-p3oF);IWw<` z0-ri+p1O6&ka?D>_VY{t!Z@D(&#n>TLupz;KO|~TuC|GSlbO$-X@*S=#@kL83Fk3d zDO~tFf#BVAw0$!A`0l}}1dsc?;ZIL`#FGsIK-~8@io3qedfYn~On#>5tiK>bfFwK| zX4}48WdD>L(6VrfOg^A}%NiaLEj}osV+h@}{UK4Vj7FG5mUcM29w5Xfd<(b(fW_~f zP>URW&xkrd%CDk?7`63ieqnE7{wk`fyzPBSfCE8qRiT;}$0FCC#P_`OK^i<0Q&VZE zxjc=d+tel+*9Ha{yk9ZyJiaaYq3~rplVJ0v)Qw#Ouk-o3&!guLtoGZHEo_3UHG^*98d234{(pR&~>Moj1RB)ZRGE6gDDxG zArL~_(b*6&A7jaqCEHAAMm7q)`?5cvoh(v~@gg6am2dNyc2_&~gY>5uPW1nd-ix=i zWblaI{#Y#D6+fwntCorBW zZ--$a4lQJ-N7wyp4d1%Yv{p_+l-YCb=9Cx**UF7#stco`bz+cq6(&mz=Bvv7b+bn- z+dVR3)vDyHi`e_t&uYA_pNVf>mVOsuh*a5mJ7-s6&H4`Fp#8$@66?@jYW^{fN0w*q z%B{~YPy>-Ny}@ykqerHi!H`YZn}4N)*~}muWK;3u`QO4&$I(uS=Zr~f0@42cL(_(N?Fz`g@}x``CUcJgO8oG(2I9v83t>1Fl}H}Z z=s;F<{8cM|lN;*ho(>D};_PoYOPqJ7L5L5oDGjtvQjk9@ZRuNbzYAKuKVrB&&8Vi+ z1sg#jPp>nphYuJrGFGh;v~x~h7fOf6Jz>(a{6?N$d;DYds-+YRbzJ?VpRo>0`$VRLX_s~Q$p;&(e{v;juQ-M*5coeVwo3a^fX zhpWB2lY6N8ua*qQHXL%S^ndBM*GHO%IE-l|?<`7V7uGdtEHkxRZXA0fFfNC?J&lpu zLF37M+eF8DTuMq9Hf{3i=yTa%!Hv`9IcKI{JXv)4v_PzM{L0!`jF-*0T|+8p2Vv~h zf?I{Zo~#sUt~*$KyzM8JvFgz)UB*SEmyok|nA_cO%nesbPH2az2FXmekn?3t7r z_s1fR-_Gc?IAXIwnEU{2{8xg!j5(R>0|Zsa#ny8=dFh5;;pzMT(8_)n;>gwYbc0H5 z@e9f(cB-^}!naoBp>Mi)%gwiAL(0gZeI%L+AdXvI;i?9nSAY^72FyNIKS9gM)Vh<; zs18KZDn2u(Z|_&}C*Ts&N#9y9ho~=hutKszg1CNsGbi2q*3q%v9&2L#b<|8XgdG}w z^!eSvOu9yxo5DOu3}}&1tTJh1MR3X|_%XUeMqPxjj~wq4;?1Evl%w$9W&dG-A6wY0 zv|oC_jFGBg8@WoFyHQV|o8N$i{v_KDdjH>rv%Va}CGva?Ut84Lfl=QsNd9N}PSH*g zt!G66&5${uo*fRU{SHNwbo0JpbLIiTU7=d8K^(5m6~AFwOj- z&`T?2gKf|7Jcg;?kVf$>?w98ARvKGwjD1S9vyTmlqOp$WQ?zXWg~D=oI)p&$vq?rw zS*St#?&PJCJGpyhFaAM+W2-$Y2Iv8l`IfO}(JdU9FQn{lvr}lO@#(y{qnbTz+;;!_ zs!5&$9**6|>iFlc{z$t-4j z@1y)+@RRF-=;R1&7GeKx0r`|eJx1K-Ae}9kJ!p^1?UL>`~yUv^4-}F}9XvRg{tE@7{ub(>5@pPJ?>5b}-kh6R3O}G8t8^35H zW`%dVYmA=+Qiv4>u?G*m%rhk(vxQIQ+q+mz@_it)byd{DcATk&wS zjAYzDf<+FjBn6--zj;XD_D!5~8&;n(elW6J#O-cI`E)%-2WJA&w4AB~YSLvuYY6XC z{2fEtX+SXf=I5X7iNOmPvs1D&#qpv=8CQTVFZ=G*=3{>9DR&|3pvqvzgEV2p=T6YH zD%59L@jHMDR){sb-N&xcSvgpYFTJh74#9nW7+AzUNP})#JmZcaKX1&VAg^`27+HAR zM2LkFXic_5LHmaLi9dNLi3o!og{^s~4R@Ni;TP#$ZFrLO503en)3O3j0l5H=0~6<~ zjjQY`oLx~y+&P;Pjoz+G8eMW6fyx@S6%8ydnA`f(Z=(V{gFgJ_9qDxXHe{YxYS<=! zijZ%{`J_NWw3CfOluV4qMmm(7T+aLe*HOeTh>ELIw(k z??h#qyf=36DQ6G(iE5vVtjBi>J^@h&D#vUB8MVOl^0NTj-%1wGu|LozUFjO3?%Nv~ zC$|GCZsx2s^|9-hU&G3auMOlM%b1M+3_;%02`OotY^1=8L#&XE7 zw)degzpmEHJqT#=sWLCzNzmKb>8M-904@tARD3#NBM+lGm{7r^>>d7gDRIA>@qIbYiEnwlfu=k68x6}yBjFyU^V8f{43 zRZZQBcXBX8ewlD#w_iiyAN4&Fp{+ay4%I~ajKn_Ol1jY`j_ukHTO7edC^@u z#aIen!@78lmBA}BX4lwDa^AW*?gXnpRCkVw7+-Gfl&?-+vx*fjlqsU299raX=(2(> zp|pK?__a+wE?9_x#pbf>vSKFe;FODHzCzVeC3xL;~@Fy?mLSV(7rS1ICYz?DlM zHgTV8WM%vfI!>;JMho;jY0WVO{$TQ`0>Bd;C8Vynj4r0{&jie_h<~i^0Z$F;<7dLYtK~Aso5zl|@ zQlf}UbR&!sb+v+b`b^b^iXHcqCR0>=o>@_=7q%M@k1!<>LLLSnB}3#oR4l~xN!@Ju z@@D~74!D}-SCIGPG*Ul8DzJ|$-fxBVS3#7-c9*h08s()(Q({{=CH$f;iwy_$RDXKt zz%NfLJK-gM6x2`pBf$M9=m)pvzpADS+4fwc*)^}bQdJ|QE5R%PRMw#joCHsll>-TIsLlOGs%CXlA;uQy2#OcV?XI9xgRC-gwURzDD0J z84*(@U(Eu@+HcyyddhHfx*S`e#ul|2yl)2VU^It6+`%(o6QTxuZ_ z#(AiskxkAPJRW#r8NAE)%%BslStt?dAhj9NwUfm8J9TOTbebX;+>@5_#0TynX+b3s z|9uUngPZ&EdV?%hE4Gv=@zEzC2f!>I0;YBlma99JcnV6Ifs2U|#0&=n=Wcz}gl%~H z;Y8v3ybDR21~%3L%8EA4{A|jEcF9r^rT%c!KBXKcym|F0f@j__cP#MV5#B860h>yS zlh(=9pii-w0;hXO1*jM&s?v3q;)kJq5NWFwepRc#sV)x0n}cyijMOSwjmP~R)oBEs z+S+BNPf%{x^8ne?s5JI;|}yf)q-ZPI(#rI zs3&ni<5-fFsC0bk#SNdtE-bMH>hm>_6qu*^W9;kT!?`6Ko9#{|{aRsQn!0<|2sQ<_ zY}!1o@4JEIo!W>+QHM)4>c^(jX779k;ZMT*%T~I%crm}jwO)Y8p_I6x8p;Rlu5+*c z6{m0A!~A6cb86<_<7a($_NA;;Zjfc-KUG;I4s8g?-%%ufp6h6KUlwsbu-)u{e8=5% zU&lR{NwmSF5V$I^@iL+A%d*`*<|!U!vnnqTQgHQA@$DpqBTND4bG>&OrKFAAMvXzd zx96rRq+8ocDp|-NUYy4}*}6;07pe;Ib$i}*b zyOn9>v-#Rb0?$>*6o!-NH{y*XjURlVTX#!H$PI^nZgKxwD|x3gMq_2<%xQ&IwS`CX zmEno|zf7#kI>xL08n-C_R%OePo_E`WTP@(=r0~pp6B=YAx0y1Q3{|eCCMawW*`8ZY zF;V;i`8y_ygP;18_zGzlR03fK9&EhO6{kO9Osdt%amA+}A*JO24G8Ou^GlYyh6Dkr z<5b|3(gDr=ukVuhf<(2m8G)7@eM#0}S|{(7B+oM|Gqgz~_v_nA9=6YWJT~%-I;|T@ z8NkUwKu4Nub2ndnhVP8|3lpi?{_n=%JM19uBz;%B7DZzITvK<#6?6KWrDs3C0hG z_fT03Cz=E-kICa)HUio!(u;-77?Et2A&7C~qEMO0%8D};dJ~{$4X)s>n9}H`_=0v; z-IJIGDtd_s9)9zW{0glGbA&mZ8kR5L;gRLm25q$mqkRd3+tfWucYO_OQeTV5HF&tH zCgr9Ozh|=2UIPZ$hEA^DlfU0dT#7UCA(N9P_WIOcof>CuS`~7~fVxKD;%BXvgI12P zIP1p#PgXKH9QLng8aC5|!BoBduCo7%dRbPut+abdj?^9Y@>gS3@18opOku2X3`uS| z9ZLxviIdf!=_!&bNrO7>*(>-=R<Otg%rF5dnC)S%gm8n2zavsFyMU)dJLH-2-?)*76`c3=U~$XsL>m5*{w7(Q&oUw1 zPk2@7;+X#?D>#+QG?LoChAyO0gmke4;-jRI zg^@Zqtn)#^ffa2{DX8B?W9MhN#jndezI%dlvOkhk=`t_+bL}+)B|`D}&GxaoU$!Ba z0;Q>0rY^cDLTLGTf=1^Td(u;FiZPsZf9UOY<7aHu`0s9HJX_fDKt;-gPX+f_PuQsv zT{7xq-abdm!C|%sMe zJ<_Ss>nxAhh!tA=9_4XpQ=YQzmS`2mueU<(H|r$MIp*a&B1?qYAKNF}Fr?gUy6JCpi{nrZm!gdkSdFT8D_CE@9NQkB3T;J4KCZza zZG6Z{HkB)p=V%w7Ns%CTdl8MMT6Oj#RG!x*73LvybWB-cQFPvx-aqlBd4IFTM(qcN z9-zNC5=wNqdehza#ko`t@v3m+PeP;pl`19KB+IVL;hlGLdG$Sz z?hgSj2Tg(!4M4L=yqh%7)h1lTJ&sfV4IXQS$U3Q6m5c84u0_(=Ki00OhV@;G$F4r11 zNT#ce8%ecxoyywrlfJ62-^NSgC*AG3$q2i=%-h!Bs~}N2g6|!yK-ew)3!p3v@!vjU zmkY-i&Yw(C?DVIZ?*=Zgblq*uxF0zd@$+Ad&6@V6{2Pj@UObEHX}hKcO3iEMD&53? zyq|!jiswD~Fi~kj;wubRI>Sw`CY(m2z6EmwYXhX0ZM8mds#|t~rh!gjy_-_urEYsp{cA(&16;Y&`ixTz>wR~H(4b~*_ke!SODc`r zt$~KmK)6Yz^M=HhLOR?8zS+WlT|@RJTscBi6KrVm53paMbWho= zFwSLh5?p{Rr}Fj~b&haOF``4nKC*pIry8#T*>%wR_>~Knw_*Ez!Hb{kjHrX;&94kq zm&q|8X7qh{!KP^dq=~RTVPH4>HTHg_POgn%#Slzqaoce>pqP#8OV)>sP`fqh*!?dF z2v=2a?t}L4#(x(l7(CP@S zVV#_LVZ*#W3&+Blp&rA+F|*}OZexRI4dVAuqPEd{4N=-k@k^00s`drd3= z&QXhB;sK5ro&1lQ4)2lKkdjxCa?`r}OC8|8@$-WT*|@)hY5TXfm5;^!h4)IP)tKzs z;D-xUIHoz=w0P+aVESX(UZQjZL6D^p5Wu~*E1^K9r(fa7k+_<0@Y=cM&q!MgNQu-H z&(fHZRskIM*?fkFfXBiCU`{7D6 z>b15}7Pb6ALPz~e$jh0~gmQN&wD;%S$y?wJAhSj#cU8x$krN!Tm@V+n%cSCJPEUnj zHO!I5P!p2D6W(98h(zC)X1F-44FNA7wqc2w>YbIpeUvS!*c1mK-ko%qd&ob0{Y2Qw z8g;3;S?G`yxy0IVvM3gQ(O}Hq!kgGS2*c{cjd-GHj0K>+PQjdy2S7SAG8`wy<{-!Z z-2;U$wtT8{kZ#WswuPcT7?`YPqiUL+IfX_|^G2K4+hM(UGq*}-YL^!+Ia;pf2Ttx? zdFgW$Fpos|>ma~tw_Xlz)0R9&eA=6&KzwSjp6JDo>+mZlZ~|n58gg|WWx9p-PA;}%k>2yj#P_L3k8a0LvwVbKfQ`j4(FB`Y3AcF#U{lUo0 zT=j1U1|N@))-Okg?S7n!vhk=1UZ9&;z%2m+tHq(*q0_o|#BeT8X}f=5M7LxK2|*K* zE<|{liC@I-xB0eFwm(ARf4RO48=S=DgYIcH;vOX`5kv|iOvl&ycma7ltnGemSiyON zxhsj3_X50V=9ezH$UP_0Kly6A1RZfH#5ngep%f5<#NZdfqUADFc7l2t#GUJtJx!YE};gS|wYy9BqS za6rq~7Vc~bE)QxY+O2SW`h}GRyHfrmvm2KMaHl&>^EWD&R>=G@6ukW`Ee6h35xcS( z=RU%yAAg%GzVhh9RGA5-w}|~C}ENbk6G6#+V9j3KBNU0 z=BM2u2R8U~RwOS?nSee^L*Rh))5VP~?8}x?NuFCqhVCJ&{f&Phj%|}VX zD$>9wLLs|j;bMPoIhaOeqb-#+1a?#pr4aoRx(}E=hIB|?&|e$nUd`Z3N|x2i(5aw& znl0E#S)>ZV5|oed>WU#$^u}v|fG0Fxj&8w7(-4vcYrW)Y4ba+NyWe0Jho+@gHJV+Oq59&c0L zmS20sjkIZOh@RHKB<%`_2{;}7A%DLrM-5%h?jqw=+);@)D0evKG)O+~V26%FED3dv z3BT3V5g0y$RGfGl{9aqcIb49^5d{xw&x7LV=x_DKE$#2DC5*eXkfmuunx0+~?cW-( zb~X+RA&gpRataXeh1iLJ5I%|H3L{I0PNzyZJW@TuhmAkeqi8^zqKMi8&g3P#Q{AJM za!Ur7N45YaY2kVl(~BYfg!WEOecvuU-oG(>#z65LK)YXuomE3Nfk1tJ?S1DsaYJ^MGEY&`#cbA+fN*YWp)L#I7eh%vcGV=wBRv*Dz= z_~aClSC@F;Vr64~$w9c)bJ3j&Js7dHb`kM6HU8G@v_&j7B-Jpy6b-%~k7O|qzh!G- zOW+s_IvVn64YZUa;QEH@$6b+3Pj^z8zKdCc_c0ln_MWxNQTqMtf>>6+k&2ECqppK? zSEos1Qb(J>-hRr^#^rU>iaf_iR|TyXa@dz!Acht~*M4P7iqW**{6biV*H^?wHJoBw zZp;5EgXl3|1eRO!Y*(}qI~&|auhf`=44SkWOw+85{WJgq8oS`VbS5|#n)h$k0tGl6 zSB?f*>^srL>qm{(WW)bhkNe;VeL$|0??=jm6hu2pNDhVQpSih<5(5^3Y`9d#wHDUQ z+cxTeLbnh7`H6t2@N;!J8L^<^`kEZ^n7dF9pj9;n%)+PfjU3%TPgnCTaYXNc>Y9nW zaNdNc{rODtd8ki(bKm>7$+oDb+J$ZI_{#T0hdS?f|Fj z*e_fQ8fjYSr3#u(g$o@};Z4h3J9ilQS$+J@mF3!$cU9g%+oajYuZ^$_70aw|Y6m9W z=hZzY`|ov`>&!HgKBKaJAztH8M603Viq^wNVz!^~bAB2;kr87vC2n>GhXp|O%9N8~ z>&$tMw|Idw&%bz4;X~0f+*^x>v3qk=i5_@;$?&l}P^%36AI`o*nwvb&PohRx-MVes zS!HWOfDA+*JDKG-dC{0g0*e;C=jj4h~7KSpIoa$=f z#s%Aey)9GtxcH(T?{dYGE74yDtrxxmuRzw}F5lxDq>kF|qQZKmC!~9kDu9D%ZdAv1 zWGwV-n}DJ^=grBhx_n*ty!3**&r4707@BQ7IY;y!$uc$~S>$B8CipMWq!0CRG%cWb1Zz_ zLAIF`)4XJP`p%uzcpSwMo!%=z>$ak7C~h{5;e2Z}-ql|G;?MNP&<{B;1U*aiCc2&S zu|hM(zsrY^85lFE6?A@hnn-YeV}ztkd_@rZT&Ad2`l)oKxVw*Lz!`sqO~)5_Cf(ez zTPF0JO><9{I+@VIFps6GKio5jG}$YI*riHU)FtJB+#1s@!UI}i zYDz?2YEd+6L#ueeB(O#Etm2(j4)q^DHl9OXh4C$-V0n5WuXejeSC&a{5b4NL!9LNg z4smJ5pdz5bLGxzwiskvO-LbnA>2#_&k%OyV(ierPSJ(-Eh6`vQA{{uHU~~93W`_OT z+rmm%7D{p2g4b8wRSMfJgOEn#W!J|{4|O7oVrXB)qpA52tC;T^?l$CD2Zjl*iO1$} z#%Eyw7_WNI>!`-r3E@iIGbftclt9bY3 zBKq>;zVeeuL;C?IEuq5fH0Ant1e7^3|M)dQZ$VI`Sw-1sEs!z42V45KK06p`nvv;V&g+xTHZPH3DsKXViTsQ{U55CpP!(>Ix3<7ThugHQl{QX9qD*Pl28R zd7sPS9|L|hd3TMSZyIS`H(XD8bmqpY2TB;T=5d(KN@JQ61kX&2J-r-=$yMOB;*8)7Tw-D2w_$V`#Uk&nP@|NZmPQ$MJoY+}NE1v^q z#hvPYe@oTBHHX6_Alu2%I8MW}RN1%*E`Y(tek1wUy4(3LAhJ`C$SI3B;OLVy=yW&i z?7V;py^gpO<`Gc8Xnoyv5ufJlf)0uq;tFt!&`UluCOqlFQG+^_+D1YCd#N5jRi# z;KlgjXZDg^J-N9IZzsJ*8FWnk$wbFOLT;W9R}9w`hKSM5buV#mCbLS*PRizLMv+?% zT8ZcJOW~?r-?`1j?@95;jA6lY0h~hXHWKX8QV!iAF6V0oA+m(ueUpMRUlg)?H^wvn{2{BciqwScFld1EzI;ppY|F(81j zB3a}!k#67FRpzmzR3T;B^*qmp>t&YgV4S#NvUbGoEmv#cL~s3ST2e^!?8hi^8Nafn zw&%R~E$})UaH1KL8MO9?pUFiLYyQ4$?Xu*2J0N1e895rpM}7X<9A4-BHBzlJ$BJ7v zV9L)|QQDHE;}_+emjvB3ah6{tJ+Y|^2A)?25|I%z6YN^IM_30RbSmD9uMNpY)ASF} zXc*ZH zici*Wuz6Y3rnnJPGqzXd#okunZq7<`GK0o9Sn^GMnjXI0FbpX3Fjfe@)5Jk%+l|#zzp(o9o`}7+(Nu8T7)t$S(~3$|i*N>d^7U{b z$?AS~s>ff0o7!ONh4|N`B+1Z6CpMqvf5(wX!)({MVR)*d8uQ8uyzPCd6K#DqY|d3x zfRyFlJw_AWh?nXt_*mh0vg$qx`PYUPU^snUDG9|leFvtQdMlHR(A34=v+%2LQ!_Jz zw<>kLHEq&=)3olvXjTIg&(P#i0o%3UCn!zG}UbD+KFBEi5cqyN4S<3vgP+kPx4Og4J6x< zZj~DF@g93pg!X%|QJh0v*oGxeX5ua`0RvmM$-c>G|E5}#niAmAFVmpCgJ|KZYqv~8 zz#L1T`OCF-|`BZp?0o%(R$cCs7;|6HhGnTNAkZ<_oq_6*|Y|4Rp=({N~-Bm~NLtNj%k!wh}VwpBVL;*E0^!GK6$l(&+>(#jN z3vPh1H^w~^b;+}qOB0U_O5}Dqo**Y?OkeqB06yQHn-}g{PLQb&LB0*5&VQe;Ypq?A zjVjX)8VJf_lMF*&e*(z&>V4;*fk)r8aE~)QQU9kEv|z(_r7Yxb+}>9%Szk)o;9iD6ZTSz-1w50tMsCG#n)i{ z*z6eKz|}s0iu17>3@#o7&$lVE!Pa8gE||Jyp8S>=Q^i%6WQd@kW9*+Cvm z8t8cPV3{JqtEW?SaBJ_ShJ$DViA$ES2+1q$*(-fNc4&o)OtN4GL--TOH`0~s!r6Ns zO7st=TpnfmVq`;PGF4BPSxsspsI~;@zlT4B?_d%qc*QXNKige%%5m}mkbok$Y{U-f zIyPSIDH00m*;F|dF)8wpMUT3!8@aq0M1LNh8jwSDkz@z3cb7TD}>3o^kAT@iHDS)p;<6+}pS1n#=6 z1onu&mS9zV$alCCDV4yJOL`tltktu&;`#2)WN0dSp*aV?OerPVtb!3;nF01{lMGb` zyBf0I%-=pV3+&I_3MXG<^G^72diVYUc5%I7fy|zmG}`q}+v@MNliFufx~~{8ah5>7 z{^0a>xTYSu$GQN0YfSkKABw#zUFpa>>052!;emJ1mjSo_Hvel5-^>*$W){86vLcof z%pHsvfi;y^H3G2ONC98Pz1X3$leXXYiG=edA znY1)Txc_&XTJz$HRk_nwa{-?vua`F9CXbU5+B_gQpl99#5WXe=Ypa1x>UQogNhf5? z`lcyWc$@P{nHd5NubjfbAp*dL*SOXWyC-e3$KM4}NMJsGcoJ4U-^M%G`*czNO?cZU z?O@AQNxCyJ%VAxI-$3(d!h<|w!Eg0F>W9KB#a@77b1^91p4zt`WP=z@h|zGGl60;$ zQg3VdBswbzEj?JnKQ~<>c;-Ay_Dy(#HXL2_tc1=0;Ib(8-xy)Rg%{np{2k1<=3xCx z`rioVBR%jE%49+gtjQ3eJJl@}afG>j zS$-~AKX(aoPhJ2MlFGUo0aP&Zfmr$BM|m4P;1Z6U!0`+Lry0X5N5ANqhK zYOR5k#$(l-%X^sCx!+p|4X%FYqa&5=+BbSKLD^wmV(%yvof^H_R-%#S z)^agvd6y^C6>7bb7e{5)O|qI-i76Y(oVwOZL3L~0w>H{$lTIoNT5S-|0!E6LFwshu zoqbopI+KJq0?Y3Fk;l0=LYEiX;zV^~70hmXQ9Vy(>|s*Ri4@tLSibs9;k7YBSsY$Mt7$RHRSEt&Y4Z_KrD1zVF*+qXfuPop5c(SUKrAEN?zVN)2^}Xl!H|x!IZiB zN1ti~3qA84*Q|%Tn0YJ%~usbYPxGN6QD>p^6a}yeTcnOLycw6T?10r z6?vnunYqJMWYaQpZ0?5vLcKjISkax&TWk8k`TKI3(gGz)-)fH$N41>Dk9f0xdtuff ztSG?wdWbiivNJa))&!H|qvh^P|dy4oF5qUR$f{#XxQI0w?EFB>hA1?SW;N=wL&+ zWCY1s@XtpP{(}6C)F<;9P2ztOmv75XTOEb4Jye@Y{xdMxv3bAc{y)tJSa%hEtr05G zZjC$e{m~C7B;+JR0qq7>t?UuNfn;?jPDbPkg`Q2@+cF2u#4sy;JSJXu;a4%K$djw} z*;u^0xMh7&hY!MbvdJ?_Iy?BSe>PZl13wR7F8rmo(vJJC%e>+QL$EOEN>AqvWBN(c zNhcXcO$Wn~>dTh+l{6zlxIM)QyVtSNktZGSL}PGxFG-m^Wka65g+aMIlT5Da&Jk$A zzZ%Bq`c8@S8oUF^q!NQHCReY26+JXYcv{L81%p!rThC$7J8y%4TJRvV)e|hh+a*I_ z&d(2xyT3dG!NCm{O!Mc?0;M|r7gj#rh5U|q9SL=rr_JAkqW=wtBzU#X?38{A$#HJW zmp@!xBPe*BmYq~Q?7{LTjbQ=z-T&kO>ktIChB>Fn#Gam}JK0OSZW^^|Doz@!w-{|* z6{~+%1`A4{J!vhOWiDxgpN$kZtH|E=kerax_nvRahhLJdP8Mh>JnA)sqeqMwCp|EC zYFG-p_4cp)NDr8nR}Wk|cPCv=6epWcw*=Fu>z6gtu9DN=wT(_;nv8u@T{R>|B`~Ua z-jixCh7Xe-g^{mFp`?A_!cVa_N8b8=ylv0Z-^Prg2B6Px%m}u#6c!aF{oGS9FU(3w z5=KdzG-d``4&?Aw__T^A7#wq*iv!w7bXa2K^BW|Rcum{oeN^k-3B@2z7OryfzTC2D zNz%t*<8m9mg^w)TUnVBb8v8j?P{Wn+uU0=)G&GYENc#DyA#ZNU}LXUd#lobOp zc(>sh{@Je@d%1_HsueKf=B#I1)O)$Ro8-U* znVzHg@1Db3E03U;dAAwRwM9p!6v;}IR5SSonw5uo`xmzmz3F(x%bX{?Rhe_WjXS|dF=U^%M-fYMyLMyl9hx{})ZW~qOhHsaoimzJMBoumHg-5U{(G{UG`t!@E3iVrp&7s z(qz*+M)#6?O)~9DMq!SB(XBTJJLyV0h$14TDa?jHvxS>hxGaz2PSn*8Ivl)>`-1d% zR`k6!=OkJGc$~a=I4c{(*4(WGM78VRfp_X^<--w`Pf9Qme}b!VG^wDDwF>!Vt|H|m zC>aiS)^BmolCydmz0utFyg_2YNTBDU-P+FlWa72lS(n6vkgF@@@fiRKoJ@fG5q<3M zYOYzD#ix!Rz8M{{-dQuCs@>N|=H+C1u{<(5arw{0z5cB1htF3EBV_)BDqVQtgfVptzV}Uhj{#Ln<}=%oYk#NaFkd4`DUIY% zYYBlsqM1O$iWG`{t~jUksFk(`8RG5m^Q+|mvuM1))aulE{1})RnjWFe-w}S}FnUNN z{B9p@8cyk=|ZKE@fkBH_sRT=Mgv z(8qGwJ{5Z5057U{KneAsb=UL%jFaULw7|q{b}T-Q1WM^BH|{V0xt5oFo*EU#dxJYh zLj@#VbzNtRzis&*teRAjDD_rCl9M9E;^~n&Z9cR1AxY{=hU^bOSZDt=R(x zYixG*3x%i#%l#%~?pdzKZu7lm`BPOh#{a|9S-3^nK5w58mhNt(M34|A1QrkxMH&^P zVd-AFySpSL7DNFbkZzXl?p|u?-X#}U;KlE8{N8`zx@WGLYvw#ZcU5g{b4LPUpVP)w zcL3no$AJY&UAqx`_B30W5v|-(Np$sm?3t2ksjq1QNx9V`7|{mn z^ZU^(_{Hi&pP`GgolzFROwRMTQpj-zL)U^zzF21B z^f#%lcOT;j-1peFLhXxa0gzd)wn_8-I+sN@cF_u+#;RqnG184IJBF#~ZA=(!m0n4qCa%B8bsX&5IuD4?V83&4yvo}V>K)WC`YVR%#vIzg zRe8rQ*YrpXfu5yfD)q|DKlTBv%B?X)D~Zi3f@%w%UZ-LYQ1!7eKQzopkVf!Sq^S2# z{i%bp(8}Vxr;nh_fuNq|`)6XF)U-K54tPu#Rg8|H1^4B6=Z{VcS(?*~PVkHy8PlG}99JsDitV9VV`mx#Cu+Ngj3_ z^FS;chIqxor|91YCTK(;U;a3u9JZ8s#8PM^jT-0yPXNqhilD0pF&Qq70&TmnvRaUdA5Pr(T7h_77 zLM(9hZp`;KMf$xHbHkCeXgyp($&a2^6}$dvibVb3Q7uXPX`$< zkj>wd%#~!*T}}{+##HxpJZzI~UXe4t$nM{>pNqnYtYmA7$g}XlrxXiCR_aRiL$BA4 z(22x7ib}KWM(I{4vvs_`5-(3)B0Ce%Eq=r&p7CKi68osrtJ<}``RGp^VIB2DfqpRcn%_FYam zRD1!#C^itqth&BQx6av0btL#eF3j|{h(LHj@qXZcHkItPW&~9z)%7RAmvv0@=)Hih z^p@y0JLo$Pqg$WK4^l}MFzagl%dm|aRHZfEJF%_m5GTv$kpFPWe|b}buK z8)4hI{arMGAUcfr-+9a~^&O1v)-5z9KZT3B2iYnYLNygP@Z3Z5XTuex z)(m0l|7E^GwNy~gwqcXCc$bkogvVtoMEZ-u)_y_i`qe~nke&2zvEFIR`03IJo-s}< zwG-+^#tJja1-x6LJmua7hDq8G?ByKc`;d=2Ef}iLipaP7-Ls;kN91IC=Y1OL=}2ie z_E}I`J`RX7O4$+N$JYHXqFYWSmZCs#wdZ7@zx+%}p5TNPXYHw8=j4(wYRz&&E`af|bx#Fk@jLrp)lIEm*zF|JN9BOIMPeLQ%6hNHIwr|h(*0al({N%9X*tAa~d-uF!@(hFX zJ!r}#-D|gwX^Y)^XBCngRo{c~VcS6!)Jr*m&b*4n!*K<*NM2V4Pl0Tu-Z{M>xjvCN z=azkU=C;2IBAas$4lFMV_}qRHS~VIt1>>8z@pr-8L2LcvE6BWVNm!E_g;p>bG)#mk zCM+|x;QLNyqs@)VaZhUeVnqCkhM%4?fg~an^L$H;8%-%8+qo%T;WTyKgbsLRz2@-_ zB#6}|J!#r{T}}HIugFstM)?NPON*uhNXdkFnV7)$+l z(j)S9J$(`+bQ*lxmh@H~%8*gt(FB&+P=KGx1zCOW0F~+oZkS8ta=7$p?E2j2-sjGPpM;h$T@9hoW*bD=B{YhYn4GXHTJ)|3fj8{moaO$r6 zFYxdbTGz`rpZ~<|x!B_(Zr^l3amAY&TTq@>^#o94 z^k=ze?l7(-h)PrcO2DO?6Ybu59msyE-IqT8R9V&Tq+%YpA4RPSKfbF`yI$uzKQ7#D zy?Sr4SR^I!Bz5FuIXhG+p_w@4YNF12*K(Ks>8au+;;Rw1(t;77583|G!hg#yLu-Wh z)y@5TS<|02XA_5NQ+IRfh>q6>g z?#PL~k@Cjkv+Tl_O7Ea35j`|xmb)RU=CxhTOuF==^k!N3e4ayXw0o_`o!QB{a)+|{ zf}mmvf!F(Ax+59GSUX?M7_;Cn6Zv0wX8zmpQWrW?JeyI=1L6;nm!?o!r-X)wiPcuQ zh6_Q&?ECKvi!799l%gRjjixwCG7ITwnlSam@OuN1`8%s$_ zrSA*0k`0CHl-b&gdkK1s@fBb4Y8{+N-P9@3NC_6Ae#r~0uk2fsybn}{^&!IK& zQN>^_Q~tQR92@$}amzgZhftu3A4+6g);6OzI~B0rNlP~Dk8*}Nv)*5GV>+YvtS^mB z$9OzZ{zyQdY0vZdoEZNegZ4)whNJnlx5l$cqVMG-A}7~`fykhQ>|CLwX4)W~SuPPv z8hSxHB^ysvp}9O+3&2|TZMhwGHYKAF+`Mu&52p53f02@n?_F)Pm%z|S<95>CxMHix zgU;@s8z}z6#IMwZk5N!k6RBPX2WQiL|80ppbm3U`MV|gnO4iSn)(N*UO(qCDRD}5C zaY{wff3fCD_oUYE*voNomZZ=KQiK$8c$IKfgJ0ay$(3VB_;t50v*Cu6!2Edo`%LQ_ z^5+4}iBcgZGDkcAbNU)OFfW8@C;Lc`2%PR4!M(pNhOZ+0qQQMHSXUaMQt?ST`@-UB zJZBkNnY%2lV3v%d*P<^+K-V?rB7s*Ac}s(5tYP=$l!qqRp)@ zp}pUy(kBe*as4Gn9p;RKE?ajrI-%MgFk@u%u6H2n=+a|k)?cTae<5MSR~?5lm6toR z9D|&mXUs}KNHjqUd1xfRuwxM|N%dGm^5Et!PU~t4@fW&_uer;5PPA3XU{d({UDs2x zMF&MWkG*oy?@J9GuXeAUT?h$+>FEe@XYxTw06202%qi9LAL^1%vO`d+Cy%_g&p`d` zP-`B(*m2oD+!e<*6W)->V;mypLxZCujFZ*0rOTGc1Mo8KZn9?|M4i6~wA*NrI7)kiUJ>E*A|TwC}#! zVcn3Ji&OwZM(922{&BYMt2$R*4nS#oPM9M#>Zoqd?ISElH%bCrv*UP1RmO(IHa@iM z^2NiW`x~O@4X>c%mDpda)mqjwmUR=uSsjnN*}jv)Yqq!?8_>Z#!_yvK&WV*Cf?*2N zO=e}*iJn`R;r~Ic3D0e$W1zoOY(Q8;xnW^A6GOu`1IHoN^IaAbWD}F1ko8a{!MU&kJYN85-~BGtp?PpH*-4~KQ>*$R=w zjoFO-St!}G*(JGQ#R3R4D(OCv?$y%B4)B>0@fT~^Ye}Te=wX+l`CDWJ{e)3Yb>OXZ z{x;b0fT9ZDO5NS13jSG&CP#wRbZzP$S$K)D5t4Kfck}+ zxuSAxY2J8&x)!{>5ClA8J>xR6(bT5r`I^0K%TdZfTbFUme*WcY%jo_BH6JG6U>UtkJ#4))MmX~#xB=dRYj~>g| zClvvszdSYTRhIXfcY)tX8`zqUvS7Y0#v9_~mJND7y@MSgz-%P8bI@D@fmJ-0kZ_j? z@ZLpMe5%Z>Vo&`4M+0+Ip9_tH8LdBpiGo4#t6RO=;YCJP`IPwvnL|&%&d9z4r2zZ4kzPKh4wrhw2PEY4x0~UE5g- z9^#f`DkBBPJ($wV#3&PqlBU_Vro~9zar-w$QeO(ox-uQ>aywftRcZ^nugLsf)gK~0 z_jhL%pD&$yaYOxI{qdCfHK0rFcNWYBl^L%wa1N6WxPD}+N zKGE^ovCJc!Uu`Rn&VQ5r-Y_D0K-5v;=2 z>)*Diu&Wkp1UFrFh6U{ee}K@l-!Mb9=VEa0*Ez#071|IXVv+JV(D`=E$(qx7U^#tT zO~(Z;M}zk%#eX2YGhb{HhZs;cs^&$fWB}OkrsqNBLC(s{f7p}q-lPei(&}W1HyoEG z_)K^I*KcEx4K$2aXF=X)#_~KJB)(wWWTY$c0c zNypra+HLeeZ{~XIJ`c}=Hznqpw>kynX;E-*0l3q{VG-rs&7&IsSs>MY@uS*N=6Oo= z6r}Uw$=OdN+m(in__Y`C=4E zCnK{gz`JW%4EsYsUqkdOA(DFyGDpq9HJm)V{!4QcHrmM$15s?uC=DdpNP65sP?hRX zySWc=iX_4!1pTfGlGk08L)mV}PBZ(T=VcD8|F!Bg>8;=J@;b-uXu$8W=Z|hbgud;K zi4F3%O1R`wd`r$`iPYD`c&>c&kwf0?O+E`3z1^WklCbm| z-<_hCdk>^effb_T0>I`nI+6|AZE^&=#JhmzL>-a(lq^TOHSiLiEo%-#3U(FP8^@>A z3QP6&_+NkQQFOfDFMlM@Lu-1G4rgliW^s1m3~jza?gbzu>sBz%2Dil}9lOomqG79N zWC>|HX`k{7$P;?$E^F&ldkcYPfEPJWKYkki{r9X@z*4HT5+_DA8;ZJ5H3$j;R2yCg z1$0o`(KrH9Rva<{T{8@0Ch8COOa`t#9b{uTEwGPlMQ`}PnR?~vz$RCmOq z{+#MU8%#BN*6*u+sONcj91&MfXt+o=_bI)e6p{#B5J_La`%a@LbY9wAJuX}*VaS!{ zQBh>r?c3Sk7qe~LWf0g`Rdr5XI~taf@-Y*qZ&<(GHBG)Z%V~&iwU!9wA#s9sw6mRO zKo>}?pjPD^1%ErZu9gr~-0Gi8F?oap8T5zLY)pFKvFRMUoWF}cZcQcpYV-hzVZCF% zBzfrf5G+hdkaA=P?R*>MHW}qP@h5mW>H!`45{pR|wUco{A@(?Xogo(RZY#?Hphd5GRjYNN#^S_ET}a2ZxI|i}!B}c3x;JgvfG8Yn7*kG$WhTRcv2f&x z=ruuTqoB@DFRKNBpm)fP?Bcv@5S@&=c&_m@o%I=ET1)9~h z>a3=Ef^{-4IfcesRO(-~dK{dH zB}ed)?oP1>(nf>)liPf4<|ysr?^wfrJU(y0&tOSjj%zJ%%ruF5s5$_Fx~Q~I1D~R8 zpn<#MwM?oP+oabb@YwI^-o3(wVyh6F=WJSVZ0b1*RybmhAL{$bm`T7r=jT`qLQsrc zk~TpKyI_joQz_1@*JAj3e3pX!_)2sIY$=#>_0S&)y6*it;b=Bt2E>W2#>j zTR0o-c2w}{u7m)-k^k69um2g3uSg{5-HH?K&}@p5q2naW4jIAB?@OFiy`B9R_4O8Z z8y-nBDRdH~+@zNApEPLMVb`oTn9X(+;Q@V^DW|Sf+6HZONE3=}&}VGR_*YI>CCyNE z^G8zI?DFO-l#;QAx$%mz#7&6;7Q$3}%vWfNh?-W+@FwaTO@kvA!i~>p^ZH`|eV8yS z6^@!OMjwvi2NCdmdy(I1w4MR~TrQ@})C%ska-ie76zOHG?PyC6fL53if;VKHRRvb3T)w#zP z#Ox*ux?Rq%3I%zf>+7zGtlsmE z)4%an6UD_C(0CYx+`mSWmlStZb)$gvPoULdZ7!FVgYGL_2A~G7nxB+I8LDb?y4b%1 zCGTDNSMgOEVbXPeINiA{B+lp8DuI5l0#>HBKSajf)tn4HLi~JDvB&u(+-zjEILYzDVvFfOD&fEN)SUM_ZGg1ndw)mlX&h&$Q4r zeNrvJB`7o3nf~Y6o3+i4vK{8P$4|2Pk*QCl;r&Zd*YOp+58OQ89(JB)+8St-0ps&i z`b;ruS$zJO$DT5`gakya@}>XSxl%qnQQfM(PZ8T%`b4qL5q~7cDepE_bRFMD+r7Kq z`=E&?jE%eQ6P$Z#U)P6d@skdWTB>h`tH2mHF{+V$wHFeC~x6R}{iI z3>*9tJY|H7UkhaFtzA?c&W2@{P~LUxYLl6OEgAi}(E0p#@y=`Xb?K22om;4on9`PNqNCWfT?*|^ZQR`9Wgk$hAj?aqn zl$%Zc^*~#@6J4QKzsA1T#TmWb@E-o)nY4K1890jc#4e%Q<(TE&aV^|P8NW1-7FyN| z5(+xSAt~QsciB8|7_Qsc?WN)uy<*_G5@aePm(a=qC!oRqWG5R;%P;k*E~b%dEz)bl z@}$VgFWUqGwO$nlzAJ*gc@rmqb_l^~Xhe+M5k*nO{$aCDLM5Cs8;Fit9=!N^`f*8h z<`#z=Ffp_M4*T1q9%e*)GDatsg;5rAk%ksmz9#Q#qIvmHCf9>oGZK@WePHuN{*}M#)b9q&T29P z!6Rt;NYe5~6*pof&4H-#Nz-zle$cUkK3`sBk>8tt#e;f# z<=J%BKBH}`$y%n$5~v5)UmJbY=cATHv)7p}4ANi85$@me3pxqpQ#HFm*ktaxVP<*x zBh#5;b8FYsgh#paC~gNH7fHa(;&D$|gY&(%i#42NE!Hk0xSy2td^%DzUs|c8%CquAv?7m7garg4}g)<3)og*TMj-i%g{7;+W{U z3o*NZTPX^n0(A%7Fn&ig02MhgxfM*1lNHC^N`7n#%@1h%Q+|9a5A&qBIC+2Hd@nYo ztB#Y4EFv1Xk<7JgCT+(lfDemKQ+ddTDYDdTsr=T88FNcCZav~vbRB#02BuBSJT0nwZ!}wV zmiAbi<@NkL_by)E{*DKBVoaPy<<{5BAlnkF@r`{A-M3*6)NLdmrlXs?`(U<}#D^Ha z&B*N-JD0;OvI&v@`F^-gbc*vRSspohizW}z#{%-o1cVl`w~?Z(epan&9=AV73nQ6E zX_lQ9o{GKhyq7Y>n#p!|IEOpf$W&!2z75~;C~B8_TS-sT&_-Cw#kt!VB88Qq3C$Q5 zB&mAPuP?i%C`m=olS%-Ph1udAc;6sAH3Hd=nEi8>OOJP)s1_W_{}36%?q$5%6AWsO zgpvV+|FogHc(dLN)nTU@{D-76z|>Kg6Ct3~fnFMQ)k4A8?{506u^S<;r~z?-*If0=jNEg-P3OOv&KBKKl>i zz1a+`t$8a8W+L2}zJx|$BsUgnzxeFA8J2btt%8x~aYW5|YKS^hkt1&Or}+~lay3+6 z`7~n+J4Ss&$-DIFSJ&hh0lM>i%65X@g>Smr^8Av|CvQzq3n6~b??G=MX{W|5V9#&w zR#4EFN0r;=D%bFbNw%-j#W9-Q9gbiTbC&R|U!GcD53M1E2!VO?$=^^mj9X?p;2AZB z|GG_rlZR>_fBpqSUz1Tk)^wN%h<@Xj=njMG!?V1@^;&~=G>!4%`oGWIzq9!GnFZAR z6TK_~x;rFKsT5^J0V}f8Q1@JWC(Bsxm_tD+BtE&}=7ObPc#5cbMU3G_=qCuB;W=AG zibP|-V1m=^2|YUh;tS^&$A>?xy^Bu}6Hg)cj~I=hj2h+tXso!C@_o!Hg(}m)>B;K3 zl)~6-MO*NnMQs~{mss(0tNVhLk1qYnHfj_=!bgeIOZ0dwUgefFRq%RYqxCh3v$Wcy z(wT4rNIIh;@gYU#TS@5$^PFU<-C$J~mw4m?^GX9QtyxZhy| zCCBDnA0R5l==7p_@IrgM`&b-AB1t1~mrBo}b2H4mWL^F*smonlDu0OwOnU^)QhKh> zGQL$=U-xyZVGbb3%C+iS@O#3IOBu)X&?{8@Wk+WhVHGEM5lmcs-Rn67*ZHMlKdlgr z6KksxQIho)n_vb#W;CXldY3Gwi^gzl68gqt5t` z`oxS6I_sm9Mi2hcz-5`O1bC@?LMv>hs2}i_oX;EoueqPnHr_YmY=x*Y@#Qne9E`S2 zIwcQs!5v@Si{PjHMo1q@b;u(FJy6~=ko?onjY(2Qd9X@tp`hHGRNwsyBCz92p}WhL z^?8r0tR`Ov823hP>Dua1vsbc@DVO2qZaEJ!hlWC)5&Iol$a3f`0wQvsJynF81iD>h zSF`mpitACYzaDvNNkRJc^fPIu{1>S9%T@(1scd8vyPph{r81(LX7r`ourj`QDy(|G z9U`=1PCL6rD+w;NW0rj(k$Fikd157W3qzUg^T5WQ*dSV1&vCTtH#qKM6w1Q0DKO#UH!VBY_ zo+T^8INLMmXQ%qztmvjz(?Z0U+RdE`24fJz9OP!}tuhVymDrmN;ER`u*27-5oBU2_ z(ZN0&_^L1^y7$t|8_OX(H}6ZfQ%+2gwVrUKZFr?xd-MIWn+g#6BnM^dx!e{fIYYb7 zZ9Z_ajgm_w9p<}lj(Cgd0J1X%Hg4aWMOf>CWjOj0qU_~M8&|R|^@l%dZ@+RhutOk* zAVaDoqPh*4isFWlCyPeVb5v+dwuQ_Jc$VGmg%q`wbBj%aWa59*o_HoIH5DVvn_L1UM(qbb(G~79ALh6PdMhlubc1 za)&F_z`dEMRK-|!)!u5fHN3?Zm}1zepL*KdRhO9m%khkIJS{?203cY8mP0{nZsRKs z7Mk$C2ZKRPVFJP?cCx45JK2?@=?c`S(1e}Qo`7BV=Kv4ZeivY-B56ht-@OAQ!KpYZ zy;AZDOPA!2cLV8CK?XN>xkqn!dYTd32PF`59Z7AxNLdXsp04ig<$_AEn)Sv*E(oN} zebsz&{!z?w81+1@{61`$+?2_yab^X^e^E0xtt@<0mrqSEIrtt~gA(Efa0`lluS!hS z4LLOnI|d`(bLlXaclPkN(#o!=39VeW%|Bv|?>T=Ccv`^+zBei_ixdal#RUbu zp7Fiu%vO^zKaPLE8_+KpF%N_+10`^4JaG2ie?VfHR~>&DQKqqpwQS6`GzzcEr^s+` z-#VWlLF2-+WaX6+CXqP_#>Wykve_>+9s({~-%C3)&0Q?DoILbf?og1)$)}oW{}!oU z`aUaRp2UVXn2b(QDirf`2NyfhcSuOVlJ2K}eKHgW{vG_n3(+$^{l1a${y9kvtdKPj z;@H!Lu%(KEO24D9QJ&*NGv&?kkShEfSm}8b6?(FtKi(;-3zvu;9An8B*xlQI)#&aq zJbZ5UR$Vfr{eK8B_xu)9GH~1EV5wtS;Rx_Yk=k*t!QmOHkVdBtdC7~&nGhMb{jy)2 zn;X%=tG5l`{ywaYedxw1=BZ~{8~TL788Z67BzVYBoIA?EwEuG}L!8PaJY_>Xh{=1K zBH6!p!3&0rYvHXlS(XK0wl@PFf`GK1Q8j8_N?X2Tf38+i@~Uoc2xQLH9(|C@P*wBe zWChp}W4CS@i>cCCgXwq8_Z3=3*@F?}Qkt)Ew=Pzaso)p3o`ZYNrcd<$Rttp1H?D5h z36%N7=`FH3>tm7?h*XRsy}dOs3P~Leg;`G*`s9G;_ceD!Xs<_PA)$s{_A;P@S(TsU z-kB}ed77|1J)#hw<-zhLh&BP>14QRT^qs~x3l!zcef|SEq-5wD@{)hft}NwS(K2dm zK&)+sKneu-ZQk+guWatmVXmJRg+!XbP+AyD-9di(utPUZs=)s7PNq};Vkr6ZI9J8= zMsDG-zBLQ0oi9LKcdH(WZhXLiSC{*yfY<2v6~A7;^NT?r<}$7DUt9CZVR#V3rFTIGT8en78n)~GleiSJcOupwi%HF0vFD(ilxAbS77moSibwN^$Dqxl;? zQI?H&BA@~V|BdTHz({HbTmw-iM0oDg?3{Y#zsj!aUtSMd_u3UktYa&Jh_vPCD!@I) zOjaAL>-2Rf7S<$jc=(fGXRQQn)|$>8Y$Ir(r%Tk^i>Uz9jUMAz1&NH`Z75P~qQBxK zSl-ibhlD}=-<;9NvB)wpeI$AMduOA4sZ~mMUCCjW9|o=^`HZkg>H_m0wvFKeq?5ec zqr5T_^&GMY_SH{0HEj8JYv}qTgP_H66=EOPsit>Vd|PyQy#f|=Drfl;(wi=JIoeEP z#K+xQhto@l^EJSC+x8&+I(X=BOZ_cRQh^^65$=gMU66NNQ}kYeN!snX8frDB({49M>6Du%3e(Ez~=t42>~a;=SJHsBN3jQX#q zO{8uNwXRy@IcVvA2sneIgp(uW4T>66q$4-5QmtT(D8<119!9@VFOhyZW%oxI5Q;t| zV1iNV?m5N|%ifvFJDw!5VZ4OGCPd;i!z2L-;9Nk1SAl=ij`J#qD%$Jq^488v)y${O zfhHEJ)>~2(c4g21&;wUroPU{{`ylUHdXS9$*3p;jLq5O}okbNk4HEfopR7B`Ye6z1 zPWPEnLwMlhC$rvKYaUE<*!h6AE<}4R-ddMg8+ujz+@G~WQ!ujW;aQ>KQ@0h~!UpeU z+O;!Ez>J`B<-hnyoRV-0FvKX_YhVHvSAIJRc_zAu)Pfpc%}^k#48 ziXD*Kh?CSOCi!6_hgq`9w14o>Z!Y!QO0P`$vP=>uH)m;jY0WT;7wq}kZD=X@*1P=Y zkG6vIhdA>o-CS2zH`OQ)&oW`&*RrrRqpUuq#*!c%3dd`nc&>p%pSe}p0q|d?|4gQ1 zI$sHFAYF%dUhReD=kQsBGYVhwAbu!DZPl7H(C%PK)}3{vJ%?MJcdh%q^*BW#yqJy&H6BSqrPf-g9L5Hm z<)Z^nluHC5?GBPvdblfy!0nUo^ox3;=fqXq9Qn4!*t@(xTNYQhS8;c4LVn;2Zc4|W zNWKzPp!sIc^dxQVeS6+dP~2dpo9OXu>>}ua%?69{)Xy~q@e9T287-#Yb~=G~E*o+p zs#>mjBxjfryHZqP9EJE%$KYmByCf80Lw$CUo%qe=KtyI(Uh^5RQ<}L+0__0Po>3tc|9fbpusw< zfPxkr+Q-g1wpV#RW!>*R)Mp! z()eV`*}g;@xb+h|=Cg(gkeqi!v+-X=4dae3*scf#c@MYtxU|Ys#BnEr!UnvV&#GRcUI=T$5 zqYu1iV}jtra?WHXk7=>cub7h1+8`{vaZH3z>-twotZp$Fi-9J_9J76<_d?td>#}d*Qh5Szr2LsM#j!dj2BBXX9`E@LV<7n^_{n6plgS6ES2=@JWk|K% zyAb?oEyEPvIfs?b`)JA)5|6Gg@mHUYvBaAfPMjc`wMmR>#||qV8K{{Zx`7LZMKJ|* zFj%)O!pjTKCE!^6jz`-WE(D%h=yg_8E&_7xFny4(>`!5#Uq?(+YqQE_WZTXteRKsH zD3Q9%{)2nB1M23vgiVI&v%5|R_-vIFYHA2$h@qG6ww~w{N{-RPY9)fph zh%4YPwcj}*ebA{z*)GQ_ewslUk;Ld->0+X-oPAhXeR1#vF+R^BNVISrho;z3GnFvj zN^yO&#*GOqd&ar8AN>|3W9->bi8C4@-HIRi^ z1zdv~*u)p|1mC>)vlp0!)>;e(IGJ3pwFNfr<3qkxUwzO1w*EqGtKl5!fl<4#s)>{s za4Ylu@_~(2iJ-bH`%tg0`IS9_m1F0WYhl%}?adT9hmxU7OUD!S?dBL@~MLNo)+orj-WT2pY^znIV06 zEpyA5iX_F2lCjz7{qnoZ_!Td&q>%VgP`hV#-b5C5?+o_}j*PC>%BIw>WJwBd-75)m z#>Oz7QQ-)IjR^j=c=fXI@6w6|4^x@`X2dtY2g_Eg3$5SS3($*V; zGTS4&R99kfXhHh@pFR~L7Y=6YHGcr3OFyvoSJYC{M$;VIebL=Db$bne}$YIoy-5WG;UK zniBd|DU&Hfhu=0+Z&nU=+}HWeL@b+uGX(D);~t1<-Mb&Oxx!r7 zEos{Q*+qUz-3PDe1{UnvRgy?OF*KxdV>x>${{96W?z!eN8#k?M2I@1RqUTW@ zkt$RPuYiI{s*`fBSfVoA1+I$Pe3cY=;q(y28X5%}ty!gj2pzEx{UOKGGQ=(W6Vr|g zXq}FU7iSPWFqu_@cT!rkqQZE2Zc1h`mOb=p2ciRQHk$I{fWdD(wkT|cP1oQc;Z3x4 zKr3dkbRKaK3#pR7aXo3EmU5dV#Cc7Y!`*lbADe|WKs^C=V2)K8WYB^l|4*m>I^iJS zBDtFLdJP`k?&)c6rp78pzPT2S6wgbO-&=c#@a2>hN$%WK^Dx=a#_F=j5FYFe^4qLd zbl8HoZcio3%407ghQpzZ1tRIU1q6Pge=D;IeuGFYKQGh>%jQuT&L?Yd47_M zzwZ+1Esd?@jiewYzYvDFB<Pd8}{H9SQRg_mTF;fN>V6NJ3~7B&dWYwC_e0sOeXB z=72wMg<~2WDAug87JW1%(dy1T-!hGT(t)-^pTV z6NkZp1z@^M$I}Put2_)aPOmI70R0`~l~#zszOo0Ai5F#;*HmZ_?!d&v_c-=7eUZ4z zj~;ApPab~Pv8yIZI;5j;CYxYKh&O>-1u67ix?iBO0_wDg(`aP8845J$Gt*0Oxe8Ad zGOWX62#5}0lr^#D`2A|_U5NzCF(T;^GR)S=y7NLx|>o3ZJkTBnj6Ql7H@Oe7jRtBUP>X_nn|KG`Zue=>lrMJ7htbt zfI1MqZlw%&S4O$MB})jWLmh6g+2aQ6u0Iweekswnew}MWfuM>YF@Bhc1MD8&E*0a! z>h>JK_}Z2>Jk*YXQeU6xW}Q%6_hSCSNwd66bW0~&3f8Yq_O~yRIRECO4B`3`M(dL& zinM&^It*{D27VvQ5|l8l_fLoiew0T#9@BbZ4`-LWH@+DRh!+4Ey3!cqDI+$|u^44g zCx!ga1@d0oa+Z~RIi=F1WxK)(t}BzbWUh7+Y)&dgP)s#&2=xpLSGyj^Qm%p*NnAS& zN=>|lWo_oN{4X}WstO_oro>{q5+M&!0+E~CWlh~x?kXVtRo#@%XWr{h;IY%TMKuD+ zF>T@}RlXWMlxzat{>gb#ePEKQAU4^Q5 zDo9{wzyqaV$DKqX4A7I&H0<{hcY(=C1RiC5toE@V zQ=Hk-Tj9i3$HrW{Mf!Wp=Qq-YzYc|E>=uSp&VPtu)XSMeCvL^r1@7?MCa~MU>q_D8 zF(|i@Be296c{LmL89ekK6-}oqm40;s~i*esvGJ< zi&1{Ag~SehY|?rX7WV3Q|WtMFFVxvY2aDfn0{B_S;(#Gu)%e^7R)8- zf%4xiqT_Z5@U1!6s!j;;RUh9kI$8g!FLiF!Y)HrAR5fuBvf7pIzX(qbVZ;oyYVhpn zIqt=#z|XAw z-Cc8tGYgVzZSg3zCZ79c1MVvq+EtSme_?QVx9(kZ)G~%gx|f`~J^pi{8H+%)FGJU)<<%7{eMgZame2KzY2%v)q`*Ftb_)z&9*;0iL}5JQ9R56ai_nhuf{V;_-@eq z-8eCmBey+R@w3?Er~XoT!@0&8**LUp;||tRJ)rP@C-7<@OjE&Df44=$r^||v#z%ug z-?X^MIOCIk6S*;eW7^Z+rMsWtf{{e7)CEIPVLT&Hy+pgxlcav}UwA8gM4%`NW*W~cO3N_B zdm8eW!ze*#qoHY)wXadS8gBnBA<(XG@lfx_n)!A z|4|Q5PvX2Ht&>5Qym$UR#`U?iN8F>c;MaCC8j*BDSA6l(*p|&O-h0u+fRJh5Y}Jog zQTm`y?secs7$)$jP+P}2?;&L=Apo--_w7^&HBbipOi$->LPhw>{Gdmcp>u|oMY77K znfV8HTG$58*E`IweY>+CobCXxRX&ha|%EX0@!K7={ z{yhwfdKcQ0eRQTK4s+ZOS6KQ^@Eu^b5QohA)Gnh}^hZi2effzO;J}A>)d0@H8S%+y z0R-HR1m4cw(%gNvUQCM!CmxBxRi(qo*hlY zS09_N?Lhzfi(z7&MwyOIQ@%>x_GG)gKdap~GNFL~YBYPBMWOVPYKZI^!>0sR*51aI z!92DNxBp`SlpsSfE^mTq*{^<^R!2Xd>OUWoU= zDl4arby-HKh1lt|rFeP%;2@3$DRGGfK>6gLuDDE4QaaLN zj%gw6x`@k1%zfFy;XBrG__`;Gt6vo$_EX!BeF4x0MSuH=;1s71WX9dcy>rS*U-#6C z;o=H#$0rs$6`NLk)IftTt@9-#U!FS zflnG4uQ`HmgbBA$$5ZA?HH{@EKz(t`P^5aFf7yTGYkM@E+wj)oLtJ_sd~*9pieu^> zV@@21Yp)ug@d#qMXj_bC7wmEQ2i{I|he76qv&2o1A&Z;2ie|7lxoPP8{w%^6Sh+IP zBOEqPA16RKb#w{zxX(57kQ>b;C#O&CR4einR}U@O-UCMse1N0T4@cJyV@gt-%qtfh zH0H)}`8%u;{^;Y6d;!3|(1)uVj(qm%^C4_p#MC?nO!>00tN8FljJq*8ZZpqS1IRdZ zswpS>dLUzr@`LC#s&>S;4}Z(6db(-g#3IfU!T?~SWj&bwB7o7$rwsy()Po#M{hGjU z8Uc?6zMAUE-}Em~Mph$Et{nAQr(7B8Z5+7C2xdPyMwDrMLF|>6AY4L*n>knpn3)RJ zRj>>TzHaJVvG1f*>kJuzDXDdaJMlJtOHG9}uL3f(SLH{~TG(t4t&ge3fB;$n!+rPo zlhlcsW+2fFH z!W#xxRObQLy-7GQH2xKT>_Xf)6$2NWo?}!`_Bb$ZJ}=ft)=%=#LGzm9Dh@F9=z|1u zVCb30r*&fJB$AwfI5xN=VfHD98WDDmUI>t;T6}SUPa=%bnk)FF-gDhn@`O!}7-KjL z>27$1hLw4`*Ht+2MfL_4S3R{Rr_@L2CRWVilu@Ct8k`DlkXfPDS@1F`3Pi8Hl+cnJ z_zna8gio~e{vdk6YCFtTw4<@9d;ftyB@}dl}PGgF4RDy zpM2~G&DD-aT5_ZdOgUN)>7(~}@hnI2&UIfl3So@M@ejwE;)Q!L2>hV-BVPcx39!gv z!1hnAeUS!oapo_Igo6be_nMBuM^jHbb{~J5XCx1S>G%51WiqNulyD}$a^lba_5m^!n<(bMEVqmmn|M$T!04kEk0T~?*E3H8+Yx>dqqMJI)8qPK z5E~9-_Fn_g&wRcJ2H==WJKpD}Vrld^bg+kkFEQklz+@tA-@t#fy|pAc$Yrbn)E}a% zzOGIAp6db|n^59BrL_I`_ZasSOJC=+#A7@YKgR_u+V zF`G2x@A{KWac>AyXmXH!0l3LsUMWu?;^b_IJN$@Q>5Wv?^qAZJ#xmhH>|Zr`^T*;m zG_CyuZG1YUd=SfZ+^uTgm+9q!1LaS>7k-LIx<{sH-EKmZ%>*1ddO9}UL z>;5!ei6L2b^fL7=9emzPKnsWSn54yrRy1;=mzMkj6d*f!(oPJW^g-8}losOoQB1sm zD<(|bsn0}VyF6e&rTw@U0B)u@py!9cSnk3UYdu)t_{)JX$t->DMro5DSUr#dM8gBt zfBF}ndZ~dO&X)ygnvUw~KFSAnIO=sFvaa+{*tFo*RfiBn5l71c(9=(Bgd<**;4C*F z4NRnzDpzrcwVRu2vQ8W-2f$66c#|_HO`&qi802)(O_9kl>JHyv`qx32PrNE))`D^ECm1Z`cXScW{GaqKIJW$%AaP@yhXf!TPZfe$Raq3>Q=wC*Cm+0*5x`OwKw7+y6m~%<Q9ND&;GroVX5Ann<~NZnOF9ppD>O0BQ;7BDpx&w7#Z>cIdD$2B(fif4&q2cAA6 z4gY8T8sNvh0AR7PS?b}JHnBUKd0>rJeDh%nm#tn8Y>y*`h8SN2ya%2iaMTivg$beHv2`0DG|=II20uRf13}s&GKgUd)4NR12fdfV5b$}a-4Gel zSY1pv^NhI!zGAJPvU{%bpcOIXG1qa`iGb@8PCz(c5*k+NA_-6*xQFU1;fNE@pmUV^ zl^#=Y)IuQl(vkC(qBl8Ol3F8i5r_}>beJ!VC;3M%G%eU%RerrsEt6#K@GrEiGDeBX zot%s}YBTMLGDDS;RneA3)IYu;F3~wz#;? zlUBxbdbkfzCi+Ehgho7VagatkdfIVt40K(0;31}u@*n_CkBbKlHDTz{(3cL8&p!OT z7l2q@EwCQg@P(b0TO9S^xsCgsG-7*?^RT@kXl~Uit$J++PL=#z7AO<7#-K)T9Y8uArCuO)j7Xo`A_I z@{-qR98+Rb$ec3E7-vG)Ff&)|=& zMjVv7r{I)y%_}#0PEB$_(Hz1qz2x&(l!gP=)VeK-w7f?QO?>pS8Q2^YCs$&~3tKNR zo3xLFe$)$qRuF5Bj~e|r2;cWWuO<$V$N9&Gxl zJMH+)(*s{TCV&rl9CRbVjS@L%z-6be3*KJ@iWUZK&w)&UfVM9M(6yWMR1dN5Xl*=@ z?9jN-JDSA}hKW!6^=uL|cy$Bc-@O1cUlAC3G)Y{Y7Rr_0Xwy5q2$PICu)D%=HD-+xWhqkgVsr%`?+$!0Gn z#mWt%Y!z}q*ZL+lZL7$sQ_OtMgYf79lamjB-5*?98a1fY632TFsTShe55(Zd2V->~ zJmlj898JFZ1q&i$IAjx75Y}z}kG;kGy#7bM0AQ1Fqr^cr{kEwm{#^P+*F{Op12MM1s3)<*4Ii?PI;GlNoAdRiZ1qV(}5k~;h^}h)KsKp2C{&-3`;Z$ouxDzxvR=?qLaRZWF zYy)7@H4HrB4I|z#x(x%53R`?cMKSN&Oe}RTO>7r9RGp~WZ^qqyg+JvucQYOf)8us! zgYM(5z1|ai??-H@4FGKs9Po8~BwW*Dz z!yDRU z)&k(2XZ&o&&?bJ$(>Wle(#p8Th?}KanPHT@1O-H|b-);HF8q(*T&L_ZHg!zCOw$&2 zToVyq?4@Hvs!YWM(64hI`vNijfvGgWLz6$eaTIpP*=;!HMH0V?&SYTHqdM>j7&UPm zp+oSZP1bwtNIfJF-o}!n4DJ@*=QONZbLrL1`K|sA|oP)68${qn8i>DWh`pKO| zA}4dfMm}YE$b1IOwwMjW2&R+hiC0Oc39PwAD`O%|4s&s{o6*eNfri1PYnWbnjAvJ zdF_Q$vRxF!9R@h?TBi~~LN;6k3qF7aMhfb@)3zcv0vkS|+*?y-1Sb0A1k?S4J-q}# zJol^S98htjp`O7k6Bw5uW4wm|$Z?lm#6giy8#RDgA142rUl{#3z()h$Kg1%4u@YBe z_TqvEk=hdkKKt-vUI21!Ym>N-eel$9F96TEu=$`=3_B@6ZeaArhwaT{j?+#Z>{i^Q zpod)_O5WUP%B!2QYz|14g zyhZ04^0!(VkT(7o#kD`QQObv&oTw$UF0`x%98JUNHiLO^j`HsKOan0=P^jV>i0{Vb z>qd=t53Pt?^^)^%gM_g+Vwq(m(|xxQc0X-&{Dvgc!6D{+$0QRN=Ne>S@`pPelQQ_= z#z*TUTlwlCpqOmRM zi*GGd0)_FikrG2Fc%)9?2w|Me1wn1YL+AjHtlQwA{HF#v{Bh!GXUChTk40hRHXIP< zV=1jV#$RsAmSkp$6_&>Ih^e3km;DJx_z*k5O?Y;3TBp2FG{6;HsS?>s+Wr7WBd z1aUj;(r`9dny9$?IB#Gp1i9RPDeKl8;=~BpxyEQ3r8h z@ZrEmL$8l`^3{`wLl968IGW!OM^iV{q!*mjs<-*ye#lu z=Qlj)N6asDl69b1IuumkYrU7A6inMMWFP>xXw3NtT z4bIG*J*mZMMDB7PSC|&Axl?|l(tYGU5q9+~r_3^P6zQ|;v6x>#oXap|!BUQf5l&RxnKFxiJpI;2hr3ZM|Sl7le@GyKI*3sI$UUZQ-l^x z5(9@Gn(7R%{GydH@_FqB#xz~X%0;hwuvH^W@_|Kjdmz7lv{DqqO##@2UzUMuVWU;B zVQ_WRDGrR}F|L5+(lmdh1d!MinjDE;HAb%C4LGH@j9d4(P7&BW45X0wWxU-Skr1@{m(|OF5gKyf`3L;{zriy*`S|_Z~TD#B6}@ ze?t2aF92A`(}TY+GWGyAARnwP$Qa^=?`&b}LC3wQ{Lsfkyy{@LA*dd1jsd+AVe{di zv4}9I#wsr2h~bbA>3{163=SFz(VzU}pyu?P*EkW+Mko&KgDhY1Z4c7BO=EpEkNolF zI!v4g`h@o?3|`Yxq{PdIPGAdc08R6eJ7XC%PMKkpt-KO|v1u)5!}t=!^*m(mVvd!q zeGxi3ul}F^VIS)uqjJbcQ_k321H+N=mPalE)5ZlmBD#R!dILX;P%~Y^7OQc1uGxs! z^=SB``5@fGeV$6+h-H>htUA|1oP+bVx$6&fZk{$+wMyO7(O_Zt)OD9=YM@e{^$Q4z>jzV&;^ZkhrRQs2Q-M$uqkmdE2rn_nW{K* zaL7FFIOJpJfn<81P0ctpz{E5T@NvQD9>(#cE@Hg#pava~gDYDXUJlxSO#lkG@&BVy zU|@nYCXA(c2=2JRCsO#DEX2@ye4vlVN-N_b<-h}sxnvL9KF6_v)LUu*X1H;-nC^P1 zwc{`pfhITL4OmbaDgKQew;B(t=v|C^q>l>;+LK{2zwMFT3xO(wkEWaT@bXA8N3wX} zf3<(ni8@giOH!Jix@dXO>`W%TpR3VcHdEtCs%@o`-{K**=o!FMur+bA&yVAT}|eGFG?3qUR7AW=tt#H9;5?CQl0Jz_YZMZfcb5zijB zH;)MyM={}_*nj*B02WP~N%qbMw#To30EinqNzQj%_bj~(VB_=acU%AwR33TSVd{gz ziwdN~$X7gi=4Bim1nYuJ9I(D6fK3j1=%6t%`tIjN%5W57I60`xFzO*yxnWOD+5k_S zO^j5}okUk>kzRl`=aunHGUmYK$1qj!xwzx>zx3}?U5ENH>BY18+5MHc#)DpQ<*Iki zWSjPc%R#(}Oi(%#hTH`>VBltB$|lbt4#ffH1{!b4xE?Uq2%{apC18-0`P_JsA#sM2 zIl2eW=3t+``Nbu3S{ z)GI`OIPj}xI2@106+PqG%MO>g`@nib+&_v7gYUNDpV)u=3xGB!df8aW?rU*R_$e+; zJn;Dwy828|9In3<=qqvN#SI6W9r?KTaN{EpyD$X`^LW@h4)0&cMT>l0NYY|X#>f%Z zFBQssp!E=JLx+v=Oy!IaSet2B$z2X3?Yg{zgvS$)pe_}0aiUxPS~%;r#j)d?{?K`9OAok>&c#% zF?5_B=N@dVlco}LN!pI!YLniIfi2hhUaKU zhnxg@U%U(`UU(S7)O)PvP3JZR)4`_5tf@xB@g2*41pY{F8o1mN7ZPs#y9D8&Z~ZiKnK$`>CrI+ zrnx1LF(TR94nus0n`V_LBSn+bzxqeC(#y!4DR^PJNs5kM_GMiBtyKxzC_zxT&!g9k zl^A@)yq6Q0H-{%X9G!>b$Spq&bZEOFa}RT0+RXCpc;xU{f`-A|;X6!ecLQ-b@sx*t zH+YY~XqQaiue*HXR33Qg>@dkN7KiCnJi+bM1Vp~aYz(SPdUC+m-tstX>Lrgh644UF zH7i`b!gX&HH`CyXYayf&-(lJ($|Ly$4xa-7pH-bWQ}#Tz9WO9lKcj->C*LYDC>i!Rpn=qh42;7~$XIWf z4}!ZjWXdkDVaU~KaYPn}>GP#?CJu63NM&c{!8Y627kDh!I(l$&nAEPj&pus1G z!=^DFMO9xE(lMAY4ymGkO#jg@09Yk$Wc0FyyANz?cp@}HX<&DR!wVrfq6(7_O<}Nc zZ)7YrfQ{Ws>#`#b9v|xY(4Fjj;PM-VuuC&?`d|Mu5Axd88k~H@41-yraOfw1vN;@N zU3m^lYcRfatooVV{YCUZD7cIz(@xf6jSm+$4E9F5Ch7vkDO!N*zJiYx)DkDuGSY#WF#8W0U1x6TO1D%|iUIe%BT!_2Kd&vwARj z4HyO*e(i;8v%v^0d}=U~d=?5|mz+HBG)%|3y_4EuQ{EFH;|py8Le(&uanNb9X2#JG zci*r7#F2yLDhk_ubfzpO~hc zg*%VFeLW3Qa*Eo0<4k7oDhC0zmM;!_IpY3eUvjqQi{vR5c>Nj)b|mipI1qY_NjM#J zn1LFD;^?OY)1DS5c-VJcAagqm*{(}WhcO`P_1q_)y3)DpyO42vsQfU>Ha<+^yWk5L zDD{w)uIJfY6OMzHWy;H(&cWa`r8;qUQwF3N)@KJ>$oj~?yGAFQ0Gbd)>tKldL5 z`sfz`ES@$=x8-{r7$2q`jNPCY19I}94d)MT+Sol2RJ_~Rk<#NuqI!2YYJvw&+R~R_ zF9L|iO>epYNwWOZKsWtRWjw^x0M{Q10?ctlSB)Hb(vgqe$&SBbKjs?2%&qh(zQZ?| z<_jTxmUGLzDZOLe4?X{PYAUykYYGV&-p}(X-ubt_)-puBq}CgIS#u&C#zaUE`%!;X zI)%bvY)Y1s6{m!VWe!+1rp`eSm_4KbZC?n0gNs&z!>!{^zkmcvcAxz40L#V2Q> z&O~3V-)O%$qpcdDMxWQa`09nVUC)0Rw5@l&HSqwLPQ`Z^ zsGe8ky#&LlbIDznrQZmk=)}C79sU9a%JmS;gt;3vZZHkv(h=g?7gknkmTyLd%CO*_ zX={RgvrQK#gK&$N&Vu>I$$dEKGhzHU{LrG_BywFpRSW0QIDi~0E_fINdT%Yi_~0aW zw=OOr9x)SW(o@Qp9MitdKkx|eVu1;+=@FnpZ}|04N3Q1`Y|Srg2M09SDqnqz7q~uU1n*)p9H9IH$7bx4zW8N`f!!eGTMrb921fEW-pBH1XcAZmx7-d5mPPS?75@#Lb zbiS5Aze*|}nvsW8*MKh!^%w(JEiiH-FpVeTz|~}QWqPg8;%Np)h zJTScsXm`0LAH)F=%X~e&M_xos7yO-`aE>WBNb!d|aTGy7&3xA9A%ds@j`>PqFWhd# zfcP~n2$`=^^)Odna?p9Bh67)*v#4rQ!t1)`M7jbKYz|C){J#*mGLv8c`EkHh!LGJ* z0-Iov6DYjro(Mum9s1eWJR zyn4zKI_QK(O#!xQ|w>5<75j-@6DmQIWZ_-5ht^1FD z0np0mI)xA0ea93-|LZE}`-ZzT;f+=9wTp{@(Dj%7Y|;?N~hX&*R| zQ>Vf-${UiM1GG`#cW4EIvygJs2fW}iHg!_srOxIQdk?aJN(I0Y|mt1tx;jg58V=5p?`H|F1bss4crd(;Ye&SBfOuPxT zf+KI@Pmbws@cx(gWCst_I+cwtRZ7Oexr#|kzV8bZKrZu64}a4wZi>Ozivn%<`2odk z_`M;n=C-g;=|A=bKpRdy7R+t={Lkompsg;#{9q>}R}XmVB+gLSdN5x*I9Rb8@!v4B znGQJ=8KF66d^|FEpVn8TMmA>&N?1W>CXz`O6r05D`U>qtYOm*d>-{g7t(T;pb z=u>>%F$zc{ZWy?K<3_$My#QiJ`-n{&YLfIHereLNlPu4R1-5Xe9|a^sn;z z8b;o-&M1+*Wf=k|-|IDuaU9TGpMi$O9-L~Vmga+Hlt;lln7-g67lh>NI;!EzXx~am z^VIWYrw65F_y)3QGdJW7q^Vgqo6GGI5%-s$a6!|YAY85Ihfi)2ux45ULdj=$h=Did z`B*Z)Yx&r;Po}y|*c?I|l3iB5dSv1XA3qXqbbe##V_yKUCfo$NsBMt|Z8r#3JOlji zjW-W${Fk_MLs`x8JgtI!fbQI0QNs8iwWuUS9lTLXF2{^JVVv zDl|wedEj-p|IXjnptxmd5P5DId%(*dP}+J;>3;5)+}6TAnR1=wI-R7L;ea^C!qVUd z8+LI}C!ms%Vdtd(_05t)4h3M0##qA?>)b~?2pmQn@YC>Ax021s>w)DD42P!73ta2O3*9cNk` z(DM_A;wUj==8ho-(Z}cUPq9Dt1;7{iWMdH#+kNU+02v2Y?Wl(xmchFh1yYj7O)Ej< zLn3@a>BH$hi4hmY|4x8h3X!$Gy^ElFL6eTge*r^7N8I23qkMq4NW%wI8o>YN=D)i~ z-D7PJxUKQo!-bH}O}KmncNp-dyS-^dZhu(UjdxcAx`9&~x$t`fn1N$lIa`8)=N?0= zzX<`&bQlY$UKS%};jt+)XK*7L2JM_A+9L?&wT}!d9GKPspk6+wqJg(uP>G@6ad$W{ zG-#oXq03xKU=G-JYo%CH{qa_;^-!6<16M5dQ_tek z2c-KRG~7SgOD)r7EOk2EeQ;SrNgvdIp5mexLE{K0O|lTyPp!JCGVtm_`pKu> zU9J~D@=m`1h=k0)m1#k^`Y3-X9fV3td-~7)D(GTEg(1bW=fhn^T1;^DiU%N5`SObk zV*@(m_LS#NC#BEz(@)*IT3T<<4-CIM)j#1|djNRwoXY*^0CR)WFb)-1;?U$x2y#eD)bz>?$@J;Q5Dt`z1;Q5MxV2zIuf}t^ddu04$PktdlJs z;>QnmfCSQ(i(NB4yekm6<d`ch}jZXCP4J*wD4B;u?_zO;Q98?#+ z*H(PjdyeAmr(MFvdr5jCO^&Lp{R0g*CJb#$+kz)@XapZAQ`+QYEP2ylljn5ksmWw7 zM?v+0??Q!@p@cVkTQ6p|HO24bQ35pG@L5uMc0%MNj{RFh3yiS>!Y5!H6i-YhdSFaz zAh)=$+zT4o1-yigq zYq8qc3R;ZgNnhc*f(1kzZK?$yc>d&7H4@Vc1oGHYt9ZiEw>lo89dS_lg|YAeNJ~MD zJ^VBknfo5>Ix~CrdhQ%uy~c+-L6g(cPch<~U_d~ph&gpnOUyz{ntTjp0djmN94R-k z%znA!J^(v3%T{&(h1H2g5FkEikvDx;WB4G%F){4b8hT)Wr*pAf#vouA+-kyOT=kPa zg2Jm%WlY!GCcMqv@+7HR@DIcTEQR-b6Et(L^F+9d?_!Cet5Y{#;f8Tw-4D?JvqR=3 z$8F>ijsxm3R$%%h0L5BQ>PV)+cN z9apK1%ZIOmh@pi~$ovtABQShaAZ}hXoe#<`CsWxy#dlm_yIRiu8|^%hFgd0p$osog=l!nsN4@||ixDeWKT$_u*?5NG<^wM78Q@J^ z?1TUcOFvLHK6EP>P_GLbTGU6ia7^ zR2&9jrz?p(me*F$^s@yD+5*Q@;RrXvrj`1m#GlW_MkAYSb=)%5Y~ zFdtvPE)df-=Q_aELX$O5apTFWp8T+xW%og??b_wTKWe8oV1Bx;k0F`aqj@9MJEY4XR?;3C*v+)JFpN=*7vMGjZ~UR4*EN0U)n#l9@*-3WgGQ9jOBHf{jB8|6t8 z+}(V=qJf$x-5p;1Ow-9PxZ=HkBKCO?KA=kTxc?&u@vtSYh>?`sj$`kVW?XWTe-*nl zCJeA~O(r4;j;;cM1|p&mO$hbI0TwIKs!!x*D=n~jAYMu`P!NoFrf`Du7`G9 z#dR;0Kh*QM1t-SkoVaa1;fkuC@*zUJai=#Uk7++4@${2-@TsX{S%etuh655-rP9zG zfuej}10JIUbTuXdIIN92D&%8XsVkzq9@*%0sQX<)em^hacRjUVDX@s!2`#a#7`o#T z@3*%=VlPE9;^Zqdb!G}cfcak(6i@+^nA4o=>2 zc9`ERp<{J-bd~zfzU~)Rzx3mr{CQLO!{88}bSp89yZneTf0N^BWv5ZT@)jVccY`w} z@KZ=}Nvpr*gLFsm{W5V!68@QM-1I@y&6yF)!>_dX*VnexqqS8Y!u1D&+YOUbVf%d<4>Taun-@WBOS+OC!WZ#iZSx!0-2IR=Nv#fYc}gWx z26YhAdbiZ!Ui3LkyahuDi2swjTWw1tzx$|U7z=lw;C1NX?qAH$vOewwpkIGjF2~%i zrNnAS0I~6jEtuGj)3M2ilSQbZos|0I3N!AsVNYC0r?zz5Rb9o{_k$9A48Z~H5dGv< z%x{(%>+)aqz4okej!XlNr26LhG`5g(HQ4U6t^sCVL)wBPjGNUqyaj`6xS11v6%NZu z79gB4r?_qOubEw}_QrVdPlLAkpB|is`?>d*0nk{^_&RsS40j!#n8lPcop8pdaZQA9 zq|wj0^W=*U|J5Aj{uBK&NjF6|;|JuYczcdP?)>s$^j26IBcEfQs@B|=9<;8st8QZG z`00M&)8AJ?CtA{mV@KiW+lY+ydzv5j0-$BMT_{^g@c1#TGy>}nT##Lx4|!-L$W9MR zBZ@aAqY&z%8CO_AVU#WY$g)5H7AyWiTj@*hiKe&kb}`Rg5@ukRJ~Q6)s3%eNkT{I# zrF&xOlyMDe11WgYX38n=0asW(YfX--TmKX{s!U9mr_s+j^w@ZSCNtyGSOg-#T+rh~ zJAb+^Jd^v&fHYYm4y>4E6=P3ASa&fHEza6Zj)U@@V_c_A|1`4mMS7v1YQMmLm$Di9 zkT?c56<*;cM^v9id>sdT!c;~H^3@a9Hvt30^`!YKt-wH)Up5SH-A633DP)*yy3{Ay zANvBJ#nNKJuZM63Jw^zdpo4+w;a(gV8=hkf=cd}`Ln27vITz9#20?hyQfD}E+{7Fr z&w-v_LQMi)b1ej2ug5&T zi+LROiGvuL)#9%*8b(eWy3ElxJ>|aCmtYw$rHQm;Er6JFuZQrAHm^2)!{J&Tm^ghw z{k{x3TW#nzSxOWwde@MC6-eIDbmtnwjILfQxe|U;jf`)bBYri>U%kEJd;G*V4_pmsE^8gJ&^rImu` z7nnxB3EXj8?y>eUa7}lUnqA93-BT*TxC3iIb1P3q#6?lBPz4Gwqmd_fax5pzI-eO{ zN}YHu?Q-wd&BcNTY7McBz$0KTo#J|)?->yA$%gA}(y*8UPjN^UXOoXO;Nk#4+i=Ap zKOFfZp&jpDhHn!uofl~%;Vtr2qpWxGbIp*_r-}YSi~Kmen>RN4^@oC$55w9CH_BrA zcCKLRHu(yFit&*z09qX1n8MH(Uc1GjT=6)xHwJ8y{u00}@bQU@T`vWG0rVVkm|Fv( zN1cMo*u)aLP9y+~;nX%-C+dRtToCSRb%D;^>Gd4?J#ml<4WsOB{tEJ*r6l#BoyHW4 z4w^ozVg|Q?5%V&l6_!T%F6W>U)!)V5;fTBItp=t?e>BH`*FR^Txbc>G%$Vm_sg_5M zf}RHqK{d|<<}vs^-Z{HCIMFB-hoY1*;{6DIQTjMQ?k_f7VB?qG61yUowUAce4YH_p zDn9;I`9hRLUdW zd|kK%zT@D9eL$)0;a*Nt47~H6#@YF$jerMpO#cbcVK}1p-nFKj3=~$zT+;K)HiKz# zP`Y}feCs-K-CZ1ZpWw~f)d0co@fdXJhEX=Pama>~!^?DZb)ID;2SGK{by)S8+Vho* zeo6}8xMq6Burm+cV+~~7h|Qtd8^z+-$60}49I_fKUB8e5>bdZD zhqH7_j=(Y&4q~f%6*WQRBLx|>vnK_BwdPhtxcUlwfbnrJ09un}i(u0)V6tOn@oe@m zZ2q+Fpv1KkELNss$S-gt`cMC$_4smOWPZt{wn`KZd3Qt@WqI_l==!OyXq&u>{T+ta zs{#Hs{otgsPIX)Hr8g2xa~Em>LBh?V?vFL5VqAs^!Zi2DxdLfzlP*@j;a-tpo#I`V zeh0f)_wUXfT-OUO=zyvZrzl;k0uYMU5BXgrT2>^^8y zLHG*+;8)uVVoBLCci3(uN8Tm?$fs%1+vF@90Z-f(Uusvp3@MNP2KIZdC!MYxa1h(> z0T=iX`(s}Kv_8IxcMo*L$-yRaathQ2vY1S46#YJam+LnP{CCnz>l@c7G<#eE#uMbV z3QL3Z7jr;6m4zI>_2~C!;M?COYpNdd7p?e!*mnUpFw&ACfMq_3AlU{skhuFMT|1wX+0$QJ;ui*H=FryVMC@3rz%;zi=G2E-A3$L&QAT)(KC z!g}=xjja<=1(oTJ>XHfkIa zX8i+6W6b_FR!jPB_qzu1qK;^s-gMBNrdy{w9{5wXLTfMD8kvz-d2`lp?|t+Oz-e`S z!#(e|OXc)KQf=72i7Ieuloecr^(h?2DevhC>>?)(aBQ6YCoq>->^secdDX5mvZ*1L>I~e+$1CPE`K98?Tt7;oZ_AAEBw;f2_5E; zIi2tR>BZPN?fhyS!r!T_oZEgazSO+Ue?PcZd|%_3@g3r+fv!*Y4y&Ck^7p z@A1V??mH=q#%~P#$QOWVy|nUuM^2=4#8uyNn!CAMA~9I;|NWjd32kr-JHMEj&)9fUrJ8V(D<^lgL+(sH*}`6 z`AXhH&O>-A|2sQB;sxNi;e6$^;xCaiQ8}*D@^{Zjex2_*-Ii|C>a_XpvP9npp6Yc) zjkDwbu)q8E+J|r&<_Y)Qt=$soI`%M+PW{z2^mCtdw*&ts&oOLMJZl(zEU=&A8kFZ4tK-`DDmQr}K}cO058ABfJ&v7;RV(D0n@BX@@_njlT> zr7SJ|FRj5+dK$;?>HLTnfVY;Wud?sjCbWCFzCv#90BO9MCqDXja;C9Q4i#6#3%z#gbH>-br?DKBznG}BccznLP~vewZw5jSk{m~B zpGv%ozd4fsN&3gV06cBDr#K$o(|_jSyCUq$FXPR1bv;i#;m*0K*+b>OqU$xjYI~h3 z{)(6sP(PXe z;#|Bu4__bY-<$d32^8%Y=Zhz!xrg(DUe$h_iPxErQc3tO#qZL2W!zrtX?nqZ;#AEb zzs`T1DgE~|l=)fx$G!l(ywU!t^~8?bwG+PMCid^nk z?9UAN41CrL0ROyo^Q3v>svA@so6Z{=KEX%(MsHL7DD%G-IG&aV+SLAS=b)Om^#)1Q zcgONpUMJs<>)nxbelOPJzmNa7okZ%k6)9UdSzF_BJ z|A~Cw3{3w?TyDVHhqX6e|1U%;_kVn<-W_L61M-B&+u+%;A39^-reB0v-EDz zio=|)m(#ZtZ`8owHT^Ar2k^!iK89**^^cy@v?=Z@gZl0;m;W)J`x5{CXgk5?zCFHQ z&40V#PfGY3C-?TUxDEcK1^B*m{n!_PuS}8eYuL+vbHY~&L=OH!{qY|Hl6KVFjzjU^ zz5j-j+bs#!ZHE_#H2~*87{54ip5_#Z-_bBY4f0OYVqYHfcZ~O|8al_X=D(ZwM!iQW z3CXf`cy~y@!tZ13KD2k(uhjgNT#aR#u5>2sD@7!J$VK>Hn2poF*=~8iJQmaXoz0JX z0eILWj~5H_xsm)Q^#G*H*jHBE1-_F1ki&7QhR)$3=bsK=!@I1S*njeh0YA?k~>0OZ5@m#X9%D z=5Nk_1J&?wEA=?e(fuO2@knrTv!j4&mP{Fq`@`Ljdja_JdVb-`!&mYDPX#Uir46n; z>zQXd7W#hkpQ`if$iF&iC;eA1_+Oca7ixgQ5;t}DKcbVr(<%Pxyo7hX7sjI0clutY za*u&x+#A1|@9N*F<+^E8-fNgm^I`6dzES@=^vYg2)n0NR&S4tmNpvC|9`di&d8)C| z*+3i-anqx}A#b27zn$BsxIf|rz}9|Ux7*-KC-O$lM9qJc1bCIk)`k~}Z@J+1qT$^+pcJme}eC&0L)(BbGJZ{~O^)Vn`bj9`yb`g0tLw8@BIm)2U*X+xAPv1IP8-7S?tbJ8fbWZGfh>Rrntu8&j>QX0 zgQ1&v@soq@xR+khf#3@~uS5HlCv^?>#*oh8BwiR=6MsLW&VM(C9fpcl2J8EOZ4^8A z-=Q_}Ok>C2F0AEXXyxw4S;17_aS+lPgh|cA3&D697^44*JFEY*HPcwK+%I)~>^ren zILHfLr*>b21^;5*Nr%paOseO|L>tZ>SutB@K^rAPPw`XU5x3gnaBn;mTGAFE)S8AU zfN2X*Ve~DB+yk$4khkIRr+3rS%LV9D6Q^lR?o@1BZj$`nozHp!z{+cpUs#!mIyrOl z<4^mRYvv_lH}VT?);6(m!qr$HxxB!v^x|(q=c#%c%Ts(;?5o&xb(+YFV?g>u-RT8^ z57Au=B|AO|+L(d|>J&DIv95)5<4|qK>AWMSiJf>XbUu_y8GCMp%edhs=azaK%&B_d z)Chv-RJV)Mjh9G0>GGHK019*ai|cY#+E{m*HHb~#9n>{V$3ud*4_^hnjwcH@9>d9* zsK!~Y%hCZUvZh1@qtCD*kEW#Xg8fPDvt9r;D^vR=jIxaf3=h?9Lr#49l7r5-&gk(V zuKyI!MWmTMbC&pm76X6%{K^BKCzUlSxfx598~zd!kdq*{mH2kI<~$1iJ3jwcz*Xv{ zvGlynVoRr90+yVsCM@y$#$f(T-EW@cpp1T3Oj~#qIMpb55|VXyQz{{em%`rY{A4*? zb{TsqpquHQ$s3IcGDoKR5?X+YltIeETY%!1(J0L&4VXTa_unvfgR^lwgqOX_%it-= zu9Xv?xbZlouG`}vIVa)^#ecABLAuIsv8o?<5AmLhydGfE=N&%w1wd>6xMWF0=Q+4> zZU19ECz&{4y%Y#0X3pdbSAWn&c&Dwjr9bHO+7oSZ7R3RG^Q8+z$p`I#oq-bWBdZ?H zus3mV*!uWF=$4Np%h4M4`X_BqXO3wxCxvPZhd8+|7B+KyAT784xnFLJE!y+{N1<4wqEzqS2w zF96yHzAAoyoZ^!+G63PH@6%89h-+h%4P)1U-^F%0NQoTPI8cUeYNHe1ZRREiwwVka z4@unew_s>%07uc+0+2bB7%u@S!*V$Ex`*VUYeCO5nDXK4CgbO&mjnEi;6HpgXBm9d z8MSlZS*tJ~2Pi(4jERf?VgX_L?du_NcKKQP<<5t|qy^YW-ElJJl(Ng1H483dj{CSk zIen)2D2a{e1}gfE;rABNo}?;XhBCjg&%HA#cI=hcn;-v?>_DYz!${#(1PCvogH>^vG1lAgQfu&o5Wur zgau5U$tReH)Y``HVyWv=M>}oN?sni19Enfqccndsi&$EC2L7KMCmrnR59IFh z>`K=|ACi?~ah9q;7PdI@r*Om&E-Z}lH?dS~cP$8%!WvVOQ3TC*zd|o#ljG22yK^ZF z%VK6OF{Kr!44b2cB%t+{+akkdd?vXEdqdeu0rcD=ZNZBElChKCVJw186|MFboFf@Q zYne;rkVDE7&*LHH*V3{NqfXJw$T1;?akQ6SoDZoRK2KI}@hQXe?_9*7)9~g>;p6&` zd;!2->8)ekCw~VfhORb6IPRAXqqhx4C=Npp9{(pSm`TiXM$|+DAQlI_ko0Q;LB=iR zXo6_1xfVH?Jwbj=)FJNxBTW+5WH)jV2H9T-8dDQ|!I3-FxFRzbHSqECaNEZqjZM62 zZDLBBYMAbFUKI<&?pCZ(u~ZGPYG2Tp+s>_lykH!13oc`5O>R1l(RQE@A!5hyF_0n| zKhj#Dx${Ui!3{L$G|%7H6nfHlic4qOLka$+pOTAoWAvNIUE#aE93^aP&JTQ)&wUBA zf6M84T6C7OdN?Nz)i7v@@A`%BxD9LWG@U(0-48l^y6Y&!PNjJxl%4nH4`O}yxp^Y`v{2PK@4#(tYbk`=&+y zP259^-L#hY6R;G2O8CWiEC$wt!##mX23;1*QIh}H3gi_qe5 zCunk7Od8%dzK5RdUr2qDKF8ahIuj$}T;F3#^1asM7CV0J?-O9PbpQ0P{22~Dd*haN zUorxhEJTpx1k1>n@0Jnw*VP9;RsK$$ziM^s&w@m0-y~%a*lyZ^2z!JiMd2y z`=Y_MFl`kNp0Q%Rh`Nyq6pasVd4b*pD6P0 zrdOQgOHS7s{fIqoS_plmSza63SJduvb|+!=eZoNXP))!D&gFDN(ZhI(sy6cRkq=VZ z#|OXFM2&L8Kq`ILE5gt&PT@$r5>U57HXfMOj8J+N{Gwr+QV^s$l&?4j>R8!j{D1b| zKs$0B*A=~Ipa1{lx91TMK|?g{a;4Mvu1QL3$|6A!lx5j+D%m~7q#>ORH4UUyY8e}Q zIU%I5a^zQFNGmAGl~aKS#+Q;F=uVVlSuo0LeNlf~2c9?Z85XC-6=R<5>RCjMgR$lmRcjAtu!=v^iot>?^m7aZI}DM%C%g zGr2JbAUMd454uXBQC>u{d7TUkqPsatiazlAwj%R3KB$Q^EBKJox*>*x=`)^K*`}eF z2mW{eAygb`NK`rM^{`d^&0aD%pRz;4ZAzYiEc6C`njh79p@Fb}d~n$Ml|Jd`C|4)q z1`eSco~K^YE(4zZ!tU1{^ryO+TWjbl&uetfRm^aIDaQImh+%E;zBZ+A`E@?RlA}GH zFt9L0Vb0)VdhS}~C&_);>hE;^8)HB61ppU9Yf8Oib)h1tID0uF#9{@64;Mhj-7gzC z;mF5N?f;vLT^JrhT1ddy!T@dE59^P+4p!(zg5HXylbNenIF3`R#23@!L@aJ*$(GTA z%`Muu8bgr*V#y6}6AKq}y8Rpf$Z9-5Tf=+<*u=wEUQ94At9g`OZ7Z4Z7qs94{CO_`+mmx$Fkka->vC$1ps!CD+E?rM#ocY`+DB=JC2YZ=(NR6-3<$FueU9C&jA-rddqwN z*w3#kL|l|pFTiseMz>)_Pkal9v-u#OfK<4`RUqRN4cBDCmAds0xm~aOn`SysI8)ws z-7iG6H1xM8I$`0|b*Jk@jA6$o{tf0Y0(BnJQ(pS@A~5(Bg9zf0t90CRh?l>@U~X;w z5Vjz3;mQ7K|33gYx1aX{5GR%Eqk5buu?(OS2Qju2pg{C|La+Z;pNqkC_y%cI2qUaT ziN)o!#q91K$ey#IS$)n#+L~V+Q~y#b(Jf!e(F$8>K9-2#P5FS`6j=9qH;14 zvT-1CTHj(93N7is*Zq+%0Dd{N&VacMXY+58z{7`&A(QBvjdVO5w*?bEc?{xkY|f{f zF15hHZ!Y;2R^Ak@Q8tLt=v(eWqfTJk3xfhma^Gy^z1=G3_?_z`4diVTc9G?rs&&B? ztQ_NSP&(s=hM46^vc}qD$)EJ4Ly8eHrOyBAW#CjBz*IkAYWA1}R9pUw-sfeKBsK-4 zo3V|uIY|tx!(Ll*B5mBwDdt&Fp(}pGQS&DJBB%m;Kc2@Wr|=9m5utHEXr65gsNjA-0--C$_^vL+l#>IMM0!1%^?m*^~Rs- zdk(Y{;|oQrC3owM@3>1(4+rNyv0d+$|CpF6njpAWx#F}qz9qpQY@&_lh?wQT{3kFj zjW{p_PHH$e(Dl%^eDFZsYE8L?9m&j#1N(s4qX-%twIhXy^V}A_de3vcBzU-==cwU% znd}C26j>T(e zQ!FsT$wyb4Xkv_KE;n%qrcdqQDF^VAjh=bNr5uaz(&BLusAkqvE!0-1_|SI8{Ej!; zf4%!7UjY27Inv}bZEpSz ztBYXzddO`XSZLyb=jq^ygOZFD&zK0J8AQL~rNLkv6qo;QkA=}Rwjty?FIjN|uRktR za7#?kurkY79J+>;c{Vsdfb~)7)4VAV#F7!F{w@|A)zI}*+W*sD^PeXL_jG=ZvyInc zGIjlHLq~#wR;Od|Nz(vYj`(_>ZT!a7{lt?=UFN0j_;x-o9F$QhQM(U(!o>e??tknH zfYux?&Xuhg;{3#6v*W5`k<|jt1aR1r&&5$-MDXy7PK(C#VdI&}e`U~fAecV8NUpz- z&CqrO8egWyfqd0QOuyIP{wBa`_h-1qf!y9Ktu`)j9KXxyvGV(%D=-+Cn}G4_5+D0% z44MRxWJ^x|DJi)fpZFITU|i>F$=f#nz^-_n%ol_Z+HxVBnwofOsi0!;eH@BE=`(NJ z#C@_&n$$RKy=vs#ryNnAo5Is5A53##(lv}?jrTUDgh{u>Y7Bu-bexxSl~orfI-kBYi&KELJ+upl}ZJfeo$7Pd;Q^N2Q3z z0ls6h)r)X*3oV8Epx28XguvVuvR#wvjx z1Ad1g792is!rrKvTM{rpcOG&B({TAae=U|xY}Ejy{H_aa4WMEKpC7i8n`0VJ@Zi)7 z#Kcc*3nAw?g*q2iW~?V5xM9go>=ZfyJ3qbZKxazkP3axewJebvqvuXk=U|<=FUPO9 z;@}o8FbV)e>(_^P1s4a$!d)YITB?Vr@sXT4+K@3fr3Y>Jsl`~>bXy*EJeD~dj(XNW z(Fd^G$^*XraFjgYDgpZ^wx9U|5UWWyV6GuvJGTMA?-+@G2!eQhBi8>{0OD9EUbAir zXk`)c0Dz>?Zg+LG{V- z`Mi`>P7q-J6UTowLTMu~3A}?F7pB@tHhD$wJ`w}Nxha>F3m)r;sG{Jab$p@gD2`)K zY|}Jz&%6leUU0Hwm6k^NNa)xWOvMlbyoEMLyzF~7alr{3A$@up{j1!OoZwe-q}Q)s zYUMH!YwNM0@*J+}rl#Ll6c|LcIa3g%%q?G7)MBV>H$LxRiVc^T_p*CStx!)<7( zAs-z5T>$X_fmd_K?HG_;)(NNn0wHXE3lJjUX!Fo`Dp7G1lNfBZ2}3OKtB_I`;U%l+ zcLv5iDjCQ>)VmWwY!q4|oEwXq^r~&KD#N7koNRTru=2&tA1Cx6BP>o82%}>qDxpQ@ z!+eKUF2Ws`thAETO96hXWgV3}^({_qVDYJ+GM8IpmWIxud?cqcVFf^ZJgQU zO8_ymX_~K?AoY;FdVyfQI8Siv6LoOv3VJ+bAd(_O-5ES}R{f~YD(7MAF<3q>* zGuH(@0Z3XQ9pU1m#o?R3Y;4Y_|3nZ1k*GY_+QbpsHi`&T48@|cX4(r$u$;pu7r5t& z*ENhcQiAU(Zj*lkmdXXJ5^wdGvnxH~n$#;2sx=X%Amo44R}zgc3F&O%&BVp73}A)R zD9-{*o7_0Cx4bJHM8w8+88G$@=O$zVvw596L~2tXVvxrIQNzOVR=EZyU(Y2*q@ncA zu{g~*XpL&)`UkDA2p78Sm#Kg?x2AnB~cG{_TlklG@cD-@Q71i*hMc6YZ=G= zs%7z?X8zb009+`n9kp(|4-PgeTzuRQi0LCNAT~UJ_$PTOfQ}sWiGc_m;n3Ev5kzq= ziy;Y31emEId{w5m@s9Ya2@S}geznBl69*xinVas0gPQ<;uYTKJgl}^#sQD{MC-g)= zxc+P_4Hzfkj86DebKvQLwhb+LxYpeGEw9WnjxiA0gks16p3VnEG~>!t&$xJv%h=r^ zMK-O8Kk*!ctub`5@H+%x!^&9(kA>NQF0d1P0#akZ3o66vU73yB+^a0ZFETWTU|vut zBHqNgiUIcpmb;%Irjf%6=j)le^;`=d_HAC~@La$TY33)cu;Q$Ya~k5>taEgnA7G$L zhvP}CcxgBfP~~*u5A%QY3jnT_-ve$d*0HPW3m$F;Ee!Cuu?L2jaM&tJoIuMB3^4My zfB7$fr0@TfZ}M4#_WG{^l#d+6!mQTED{<8zadRs57)U}JEu9SuUiVGyMQ~#tjwV&e zZGj{y=ZcH?6r1oDm`Y*t^`O*Hc|oF1NtAKMR%ns&kkaso3LLpln)=$#H*zWNvG|JC82`vMTFMbC_5DX*KseOx{Gr%wRHViib7R~lc# z>p#o`hYKb7Sb%sy`%nB@NaW(6mNq*ELkoT4>N7>H=tvvH(l ztSCq1d#rbbF$v7MNUV4p-WA?x?p8_}7EP=|Ft}^4wZhSDoIr|vty5Y-8tqnMQK=h?cE(U?Xs;NA!ZSdoN8)w_F zBeyt9roItSo@%m(Ry4#m9bwsH9MUD%;$gB0cfV{eCh&*!KlcS7FOb$Jdf5ndKk4TV z5AJNr;bIJ|Zny{_2E6((u6U5+f`x&GBs8l93@-kDOk8RwS2n(m$KSh>+hUMJ6L)!b zOuiu`cbGq&BqKTdB%xjyD9gE9AolL^WrH=NA}n1a9= zOTxx82PRV3D`&te4g>MkmCd-t=r`V$WchANSG~vfs(a+lgVweuP2!kyw2alVX*f9p zMt$Zk0e%ahI*osDL#+xOW5o3sIi`a+UDSY`J;o)#DP zLc+&a{Us8_3{pRBhMP?c^e8;O1Vl_)nOd6@LTn0jx8WHsz49j`a<9@S`j;`g05X@> zx&Yj$m${d~;DBeWHgvIu99>gUrd|)E>D)`Q3@HRVFuoil1J@=F3iF}c@;E>e@_;&7 zL!~O$c&AwE7H(Xaz$-S@@Hi5FaQo3O0Jv_rzG&!WPd+d-TMrAcqcpg9!hx@iU3u)| zKsqZnS~7Z}2v@=a)As9))2%vi6t$yu&=ga%yk ztp^Wn6J5}B)b;Ij`RXS<#*$Dxls2bK@%%gj!^?Z;Xq?2!5dv|uWhSC$++cs}};S z3B5cBqgL`{SC8EIps7a;8s)EWae({B!XxfFZhPKOv48vv04|i)rtHZFc87ax>EvGl zL_nK8aBs-L0`dnR;?zpPy1@{D5L(1CeB6M51Jr_)4IVV`xMWO;rlXt^T_uhp;Hp`E zJ%SU{@I*yFo|_ZEX+GT>&7#-96B&hyeHhBS;v+uACj139g*lK2=-O_j!eI^$nVj89 z3rBNW-%JFyt}!Xcq2)_Q{Sr*N>K@t8tQ`Dy4n6aVGbI^TX3wvHT_(d&UULMvLS@(h zpJEiXyfnA;%{jOiun`6ZF4BWmnPs%3(DCcNt&@uygk8@CAfJAvdpvBdYi-=T07+&{ ziBW?b)sl|IQ42Yxm8a)AqN_(e>7p-Oxp@j5&oKFj^|)hhEAJ=vKl=qBRtFyxaW&EZ zM^9AwxXN0bxVqq=ivvPaV>|+i!@W9)K^e(5Ca3; zi?&65`dKVZTPFhM#8F(is zfdgN~4nOLfQ$sNfr&MkkK!+A_QbOnzb;v$LIiMPsF^IK5xnYzYIkX*+PGS`*W94YW z7oC0QK;N+9KE;$U@fAZq#0SVTp4lccT{B_W^om-Bl>iZ~$AquwaTHJS$*))jeGrIQ zj&I(;Ym=6pJq93I=7-Z?1{hC1uC4!Tea8uyj)Q4KL%Q485JydPEOhu9Sp63e;Qqk& zvtI!6g2lS227B^HJV4^v`v$)7^(}xubbw>iH{Ar%NTKbFJ}V4D{nKqMCly zZ8|+@EIu_!ofnI9Y!Ph&7=G+kN5K=mPA9 zP05X*g4r9VOk5uc!>T~$+;k@@wKCxpOkA8EpYV>!_c2K)VhpFRjg}Y=4F|dS8AndX z77%#kGY%b+R+lD6#9IVFa>_qa7O(jLkv4r0Q}eiEuo3&|?Z>|W-~#44<+X%8`5jjt z@mL9ZfKVhg5W^xtkIfE$gSY4ShqU6!Z)gF(bt{ zX6ID$;#9bdBNveFFWN__CHKJOXMv&4#JzZ*6X&P(KmP>) zt11=~);&II-FF{wX*z4@hDCm_2OTXe#*)CB1wl)wn>R4#M2|4WhRqzd zgkXfH+cjy z2j*=Hp8hL@s@ig!OS!_z2-xg;83{~l35iCb&Uk1!Bj*cXou6_~fC4eEEmm$AWrH4L zJ-91!_`BYghmZj<=^DoD?h_PQj`hZesSg;_xGEDD=BkiTlCxh-GrD3%*APgRuN8QI8Svsu}aQs6Rzg-h%D<$o-#Zfg=>rLc9#19j8eoFq?}bcUE9 z_Bdc-y@{|_cE-J3`S-M~ZqLz}0^hECIC?fv-FR32w)qE%e&)H2(_Nc;{s0slK6_9T z;uxc2$!BbZO1tus10R3vSM^d$xsa!weAN<;n16ty3G4RB4(sSDd@4X!$6H1Z;~snjzzlWPWzXTw6}v7fOy? z-Ft{tE($M0E~6Kt1r1&&@t<CmKf6d=3-7_!iT? z?x(_MOLA(nbue`NB>=kcks|5BF1Q>Eax5-Q@1?hCv(E8f04TQg;mG%MBZfn?DZU~< z@Ax}j0I+gmLB;?0;bjEWv777bF9*3!N^foS!><8A#6pe^4|o5=Ka8bg0j-80T8>YH z=1sTY^|lK;^^u~u_#0;2FsaR62awgwrfI$?s!@I#`kR3%W#hgiZ0u_%FUJ4G1-gA8 z=e3}a+W^u}sj7u*emc(qK&R0K|pETEz#=H}i!Yaq)WZ3rjJ7z$1LnB98=$(9ai&?ZZ#*J6(8h8Sc zv*uoep}!#@q(8i?aSRe20#`$s^5&B3FGZX$o-p~n-kuK98K&Y`N?sSDPls4KOCNZ<^2qPulJ?Upg2IHBwi3INxZjX}x2p&l&)& zA!qu4B0bT?b6@sP?|;z?z*;H&rpMarpMKGMTnk7zeAwz?15hsUi7XbUEWlY zhi?(^s{n9-u@4*P$#EtY(7F*}L_@rq+W_4+yUZ}k7TtjoPGg7-P|uqE%fyR7pZxGO zcPMcAveENwGzjUX!Qe8-RMyRJDMV0TnY-a(JmhrEHat@LnR|R!y!X1!E&GPdP#jKk z3#^HXD;R#q5bO6X`6i}3%@N~%Fs{R}6&iCDWYXqzndiRAn0d~}g+!Z3Q!FrEd*>5a zGPUz%T$?bXohJ=w!ba~hi2*{Kn?L&i)F=P0gQh;>sZQybo^#zsu6*^<^IkFUw_F5% zQTsJ70Jx^Hj_O{LeR@b451XqNN|@U>2m1P6I^e;^&ET=ZBc`9&xv;}WuMHgTHn?!b z*M_ABRQbVCz1x?7)YkamvH|eszT3f3?V`6haGXn>1MF-?En}oDwkAx;*J zp)+B)aHsSWuyRju2QbfS7K3Rn8EY&ZRr0g`X?Cpv$PP(-5p1!_Nq+gxBM2ZG>}Z-} zt!skfC5O+Nu=UKT^_x8ArkGv=#6isS<*T0hiO;db0cG^Td@v`mkt5LZD&Jx>F}~y} z)P3PUwf{XY09ZMBgJ9FADL<|*%=#c6PWc(b;!s1(H+t|9Uw;XJpY-HM9}awP-7kUy z*3*oG>MJDOx;YhyLN%Vmm>aezm4iVE>~`t^u4Wp*^bn~yFa~y6kJI*=r{DoRq#X&c z`a~tPX|0R3=gG5}q!8Nj#m(MQwuth3uJaLd9|G>Xy@{Ligk$tSH}i!2yvmNjXkBcZ zKdJ_)cpAkUSV|lkC$UxI#8WNxJ+JxAU0EY2!T0*p^#Y)lb-Y|Xz8nNU^YkpZ@@vAp zaOUz^q59AdyPglSJ&wA;(*~|h888}i!B4Hr9^Cvy$5y`d16AqjrJFI~OX1Lz7W+7C ze$&M{Adc35m9fyDdHg*u0CD}WZuG(Bl+7MjAI3%7xZ#Kne6k_)pLj!13_fiB#1C7w zq8A2EwM^_WZR{8;Yp0IBEpV*3AzF6w*`MjGDGtKMxxdv? zKzXL8uj&cqoNgDT*GbMvO1YgM{#9tlV+0B8`1#ifJsHVT(Q-koy6bdnc6Z{5MGQ8E+NMk^EkHH;T{&r%{>I(w0zF4G{x!h z0q0AC@w7o>RD_YEc-VE%Pk8E|HgiA4(5f2JP+suTWDi>(NYKVuV5AOAHQ7}^1BHh# z8zJzpaRYN4vEDFd@tiBH^MA7c%U%HDk%X%siv??s-vq$OMl5Xa@htO&;V~^9V6YW~ zjl8Qr28*h1-SN@Lh6wNYWtE zES-rjtmO&r{mc42Ve+F^jVT0aCve!sD24u#SPahcU_8@a$ThL!& zRB`V~-*Wc2ynO7)UHx62)Fa`Y3zil2k5rAs8@K}iv5QESG@q}f?}=WqbC1JkHvx} zZr|vM$5RIHqOie7kArOGtU!b!#?2eNp|K`K78exUXbF`Kj5-9lp`#9LK>oi%M^KaP`eXab!dg^IAi* zTr@hBNTHCxO~UhmD1B>Ei$K47Tf_(TClybNRwE#l-2Awsvo zmGpperCvC%xnHvo)jCjL*VGE;K6{*mG?Ifj8t1FUR6ra~gmH*NXTTJzT%)0$Qec;E zYGEv%2MYMiX))rNCyx5cyNQEy*D#LKgAt8>AK(i8*yHbd0f@`EzSLVkon!srqeeeg z0T!y;*igA(gon>K@c1yEHgI6-5!0^%!mOBZ4FENPVKeGYKdEb6_=|tmK#^#Ap{PDE zY3XZM{i}f-SLUfUG@xDW#`X~MQAdrjjgXOsd5&^@EQOiTB$D3Im7w{j2S=^ZH=Z~b zy=0oi#@_VIF|+s+R>8p_AH`wZwSn_)tuF89d~IjM2^T`0vaLPk1gY~Fy26#0J#$UK z%*99m-6`gX@mh&X_pG;5c|H6(UL}ZQaXg3U#(_GJE+gxh&;3mKz|r6vM|SOf9uJ<< z*rTrJLJu6`VOTDB3kQibY894T$l;?V`>F@eW6Ks2u`uEBldx>zUaMn@{f7S6y#U~% z>UaNGe^@2jSmD3=V6pTZV9Jxd`r}stObZftwBsOqA$H6FI|*hOE*fIp7KZad44XeW z(es4>glOy(D?kAN(UL3MUBzl6kD$kC8>ZO!pl5;e;R$#BnnmiSp@{)BgaLz6q0K?` zXnNQcS0T$$IdV4V{15*i-BN1|j&+Vos&}s2ibE9RK8?8uZyIBf3ym!5waYG}8rz7({6LKM#y#ZqyKt#sz7DG{uQtKI?>Y*Gn6^ z^=$wJfJDoD+3W!~j&OamAfLT+0d(KV87oQ*o^}CFHoM0;Nfw7WaSY=;fu~%H0ah!X zfT2Hea-l3~eABdxpZKBKu~+^u3_@ET$^!Um^IV+MZCmHa<9@o8br;hVZK>v%S$Z-` z_lgwwRY)3((63ZQD}U7KpwHVOQG@98qIh1A;1+jtA{IVlNnqGHu+b2|vsFO3(UYEe zwHZsN^^!)N_0o_=^6Dr390vH(43kY5^8=xu{bJ;p22AxmN0@R?eGn!-F%9CB^mBpV z_X3dD5^K~qe_dkYEtcz<6weWko|}0Xg{6(vhQ9+SJPTpLp#fh97^^``n=}!SgIGCX zI|rLIDOdfHUHL7Sp}^3tHv4USnZGiSv=3hzDOt2lW2LRwiFl+uvRZyl)sfnOa?3cV zvJgVMdm%*GlSC%sA=idQy%Rss@s9~5&aC}FZ4Gb_oxK~KGdU2~)d{E{6L6kJF!Mxj zvCTE7%rcfza|sG#FXvP^fQ;Qz9&je<6E+l?t~>IGYtDO~a1cF~V%gO-t2I{v6@Wmr z2?vH2`fCFZJ28c7!^Ri_ayv84ZW61COE#heGGtM068eZJUP_8iM z!HI@C@=v^sE#~h#{>m2sJhbqi18TFvW$zn%tTWzs>|>FD%S}GlNX4;$!jX>!27B)p zf+K>8!FElAnM}hDAVt%7k&nigfas-n*|YG0SWtQ{#5!&=?{EwCQF1L<``A`8ZmTZo_J9fnSBLhCOBY ze3W)KFn1TNu7wZghA)}QOJMW6R{G=^k(*-1wr{YKgRT~&7jekZ&dVrcNO3Bc#Z3tObH(V9!HaJ?vigS@*QL9Yvq zs)fXC{e^(A#c7%kU3cY7m};Qk9#9$Z9N!$J>G`*|CLg4*>AHAJ?wfH7)1`*%0yW>v z2&`gb&YlL9bBlC5v@VB?0K|v3k0S{a|5AJqy@6hCm=|>j_n4j2mF^YJA%c(#YLJS;l&_~ne?s3MFfSVB}dC|jGy{V7z;$%J?nsKNa76YFxF>wX2 z`cenT3_HKzFM`fFo`~_wns77fRNR znllH(?&oqj|HBx!Yn<0j_i&Zb^~@7sj<~2_L~|m}4H}T=cN@vll5IUVcGpi^GU#PH zjkt6yM=uMWx8+BUZ^9mvJ@vv+s$M$0F7Y*1aQi2z3y+}dDfV0XU;6@pm4}-d>lO_? zZXRKGe&=HWksm#5Y$jS%(q9~S$FCp4Ax|8=AOP3Ew7C3!fFa!muN0QqVN#HTwL{522YNdPt06+jqL_t&( zJqp!kDct+ZWGBU#AMz?o*QMoQBLr0UClUs(c%=tJTEW+gK-~kb0h>iKTXyu&tytpJ zN*rg9)uYyN*NG2+9@wWMGd3uBgGjTdgbJl zjp2%wvC}pf4qA@O+=bV19(9FZ7*!K8Dsq!kd~n1chOqH&^ybj;Iy2NzZiUh)U*iiR zu?nor&D|U+E7AOJTArE7GQ`X-@vXj{GfsND4vO`$7>Q=*$@hUmL%3||QY7PwAvbM4 zGmOJ$MEJc&3L2>Rpt-$}IC_l&moeoD14FiSul*Hq-o*7ypWHYIYeV~W?yr6Uz|}te z)DIA=L^lq6w7_ta0OlutX{`UePngo+Uw;d*UILC+fK?79l&8N10EVWG9r_^gCl`>T zv8L?k#Ra7Ch*SB@w7Qwk0U%F4cxKmTZ5YRsdh88F3-k-zDsF6R37C()IvQ`$@QF---s&YyK{Cev-`vl5=< zwq+A;vF6q_M%rDBam~}2x%~ux(&=L||H`aOP&I=Y!i6hQ@m@4=a)l?4>oi>jTa0U*S*ZnH{?B#2A7Sp9d*b}g z%t3FV4rAw{PUVp|XZm88cBjV1Tf1^4Q-s>HNjSD;fSvsrOJ0?+U|5$BPaO;sxejq# zeW(knFtW(T1B?qmWcg8^_Mea^&l0*Qou&49pisA}RP;(_vz3hi2_Q|oI17M&V7ZtT z&uB$i3)e6M6hbnjhuqlO1<0g}?Wk+sP7ggbf2#*Fs!XTlK>RPL$q1CN|In+py|S%= zN_kRwH`2hFtvsCq^g`_ew-a5Gw{ONl8m?&9cX62a-MZ7Zo{57IK#BRq?vx#f&)ATH zBSV1lDWW*%-nrlVAUQ6;T_eT`%VBD7^*}CuHAO3A#*>($!!+mOfhK?sMy?|SJFj5y zf|xmbQf@SUSiM!gvZl*!+v@(fbCAasYZL#S9v*j@`88N0)2f2eHk_OAm959BsZdEG z>~|3(aA+5BNjO5zj~6$sq1GOBWf)U%)uEH*`BB9NwlAgjTx#N>S> z+N+KoY_HQGSCP*x_!BL|#T=3M{Ee%B0n;TrPNEZzl}*R%;C!k+h?$RM$~rujxz^D? zbodHXi`QHUB}qw2riq20PdW4BQ-Bj*O28iE0$nj-ah&(FjcTT zh-3N5VFTx-()+9KD`GyAAt_VHX(=&4pds>wF4&?Q&~5U&8vJ-i2{3uk$M#7a>d42> z7K8WIcsBF|71PqviCk@D-l6LiAN0K8Te;!|xa{QB5@a$Ju|Zad$B4QFL1lE?0RYjj zhUrf6a?5OCGG;R>d;iV`z1|aGhV0SceyfenV(1@vcS_1McAvLqjAO}CqS>(rOFow5 zbQxIpy&Jj-Y=&%>Siv*JA+Tzwd)9>4mMTZfxN*t68C@7#Ec}x(W(wPu9@!S?_3s$c ziM{#>>|s>XgSF&3uS2vx_SY?Q=*g4B&&nO}>pqIq&;I&=f+BS~Ni1xgYNosHW@>A- z-Aook$qh2iTNW!dNC&5bgr3oCC9-P2MevN2A246$+nbBqTl{cgieiS+{}$x)U`liDhVt*%LArzKIJ6sbvO^4A!tx!jbi0&bAZ{>3WKu$_-Y5tyHqBD;A#%87 zo4IbjSPM#ci*5QKrsY zR1WDk4JU<%4_y1`p!<7=36BZFtduY^!iu?q93l->ig0%ZBq*IpON?gJF#bj2Be)J-9irgZ#?WumQ?F z(W^56CLc}B@h&r5S3O{5Z1$Q;lSd>Ht!Jkv*w~3Wnhs<`O&a1uw^JQmv~RW?wSB_) zOWIsV0)NE9n&mi`VIkHqFymw5;?bK|5TUNwwo@w`Mg^%5f?OZt?CtU!?igmU9N1jc zgH}_cx;lV~FSbT!9cx@>x(nxqs@e`6C{p3~ucWZO`{lTRcJHFhHhfv1v_@RR;%7Al z)wR?>ogNtIztSt5&^K(f(i;O@wNx=*gh1wl*bIG!cFKp!F`L7>?B5GK?_1Hvb}>CO z3mC!tfEJ;e>?8KTN=+V`DmS{|JWV>;+B-jzaB^T)LH)HK3#b?ItlLH_bmtcsVO81g zztk{23Z%rB9uQM6SGV{&j7=+ZF?A-|u$U+o6wbBeO%$x&-u)i!eba{FTPOiRMNF!{ zvuc`VV@%tByNK$S(*B~(e5PU-BVNYk2W6BkAs_F81)~i{L?3^oS3M23$Yh62!Fjy< z3I{{tt0{9b+UWLsI@>Y9vP>q?D5!;-nPdC7^cT|w-=rPh)0F=jcr)eN+``IfBttp@ zEc~aunZU1Z)}LX$$@SgnS$oc1>hN!Hz8)(DFi!AUlOh_;QfpaCL&J3d@N_x*lpZsQ zD_4c{Ko%=Hp~*w?55mb~p|ADu3*gw_?WV&D#Fv2{@G=%zQnTnaUC(f&^!`)|w5U)$ zqY4`QZt$0N2$~l_iE?$`MZ@H}3?me%g~3kWP}!XBL0z?Gi2O z7lO2`&glEd*P4s@d!Lk5y|iq^oHl)^wj{FCPUc&ydh#?PlVdiSWFgH~XbP9jHQ3J5 zYnMIOWM;+qVuBYo`zl z@rjPUU27w1cCfMb!d%qfar zR-tOIF6_)~dBUEi@+x`tkJ<`p(HBH}wy|LkN5_7Xpp42o=yWfL5us^|O=dFK-H2jj zjHW97&s5;u&;85q!EuT9K-&bv?cmVNxyvKGwmn|Ql&_W9W(<<->#*oIG1mRzrAp7F zD_Wmrip1EPi{xUXQ(F%IDzG`58ucc?id%yb1g>H>tc}(=gWe#C%_;-*C7R`HQ#5n* zMf!PS-{`ix)I|K@Mno2(Fr>oDAwh!ha}ET05*j5e8t6GgAV)}z;M8v) z3yXE$Fe%3@`Ti%tQcPqCmHVdGx?TBgG`N7`FO3xKe%D zR>*go7F+=p&P=X4SN?0rF7Qk|jWF%y2%MQ`46gsz&s7nvzPWY?-Fm@)CAM_QS~Ktp zH{;!qog9`Y*vJ;3XR-93EXU0&d5+tf!g4T^=)2u~ex93R_4SD10sZD|nMKd3+2>7> z@7UgRK---cU^^D~?^~_ z7VvhOi2$})2=yC(*f<_HMJ3x+V6xdQt_(wCWFW2x3*Q|CN=0eWrQ_#zIetZa>!VtKrC{l=YV1&Mh+S#^E|HK&Hld z0ww#AZyeb`=3GH)6A9|eBSM1#-hIbeOy|9i>_c)Byywb3VcwrYUOZGB3WnfFp^&$T ziRAQ5!KB9v?TW$Mkc0MC@w{a6;Q%x=-ec^2u(i?e%jEpDyFz94$q!t?zbWWp8{DDU z?tezEpSxH=4rm*LJw}g2zqZX`#X%iZZ8M4A5%J7<$AjhQ3ZHqQl$2tz>f$bl$U-;` zsqXZ(LizwHjE+-!ez@JqG&^eL3^e-v-G#N%x!wwNgai-4Rnj#{xb#C@nf_v^h@U#- zF{6S@mQYus1Dw&d+Qb;T^AEYV+#InqxqtlEo4+>W{XUcV@ypZSq4dz~QE+`;Aa5FO zLMdQ|hb#;lC+Btudg@Fsw%?!eu%sFkmJ2h$75m`{Q{j;tj2Do*e+XRlB@l<H5)^a%uzA2J}&5NWSkDn1PImSgk%M8 z1;4-nr$el8@^f;3ai3GwU&M~T2|wf>_Rg2!xqqYI(BhXI?IoAt=@UzlI2WZQbRxA^ z##d7I@Z#Nz^~Kfi*<0I0T-zGuQ|K?3?!Ko?W4V0vV`39|jhTRA7qLBe*8=q0{-kzI zV+k?iKi;!+eicrKuL3|ecrgYBQ&5>=_19;6XWec&d-{L1ScPvTRLhXMSp`KkgU?Jw zA*HlC+`JnDC~-L$FWqA~2pf{M`Vz`Bap2LD>wwG!xeA6=VPrqwh~ExJW-pmePI=@x z$i^}>ZV(JwncE23j(TTwHr?!xChc1W`Ik^`FcuN?rCS$I%mp0Y`;Kwye2bZmi3X09 zt3p=PPgSGf`Xx3RD+p>?9=$)+B%L;Jc}`aQHqBgKyn3QX!n8sB@Qc{r5WcE=v9O-? zi_MZ{X)<6MwErP=ZRFUFLIAq|jeK&ZLp?&6FV26jRxH+hUdDIWAx_NF*FwC6j%en*| z?bh(Q{#$|6b38uUiQ-#4cqhu)va+{h`~EfIKUi(|yPzJYQiC2dT0ZDSu9Of5$pUW;v-YgKLg|4pD$c@9I7WL|k?1tO0Xw?4 zfIu{*I`gR&_r(5SH?Uum?i07tLnz0okhSE9f+@WJGAJ-yJtz5G;ve-*JK&01rArLv zgG&UWpkOd*_PYbx_RGCB6qj@nLBIqyj_wL(nR4Dxn9|-{y!3AIdf%z^`yb8SB=Y?$ znF97K8W)^}AVZ9~U*Q^=;p7Vr53PZRLApc6VS)!eKaEnU#PvCpH-2|&Che~eWQs5O z^8T?1|Gd5C8R<<}HMn_`A!gbRi;Y3c+jAFtNDvP2uslJYeBQ;q5vfXrE)9Oa_asB5 z3K3V|-S_{}m6$INd$mNaN}Jw_8J-7u82va^HogNmft}YE;|-Ev9;@xYQ6CfcDhxV; zLxR26p?szSED;%=iyAq8jf4{)jHIt-{`mBRkEPLaDE%)pUC1}B`yQrc^@HhWV_wpU zV~8=iO#A285^B+YYtR)rBX|vvytzheSJ6x}Aq#GccDS0j3`+-5F*#h#Xyac+OT;%# z6n_=^mW55ue*wRw9}FJqmNN3CHnusl|E|W*5t8T8U<4KgDVLiU z)tj!kITqdvv0_hLLm~I23vKODG?Zs~48f_HK|W2$O!5xmIcoyDapA1wG5aF8ZN_A? zs|{hy@M32XbOB1uI(A>gN z#1jJ91O?+#tcR-uOTH8&D9Dx2)WlGNy*}3OcVG9srLEb{aL(HTjM8)qU^dlYjDB7R z)-AC`Rr^vB33|s@HP9eNo$z;Q7{$pH=+IPJw!Ca|h+nMf|<( zJs#Wy@b4DXu5a9YcvEYN)*aXA-akfA?}9{qT3ko0M;2gkHmZ5sIFMzHd9L z=-DWW<1)387r|jl^M~?i$zP%gJxk#?Q9|rR_^7Q9#Ol-Jgg|rxuRxE$rzaq(d8hB4 zo>5DwYqN?=Hp6$|aQ#|?Pas3lT9J*AWw&R%kDEe!WdOwD)qC8|U*M17h<`8FZZ|c# zLJ&Q=X4s-0T9gH+;X8ghr_jW&MzImsn~4@ddv16Fsb|{p)@K@!sCl;llMNHf#7HAi zZmxql+Kz?p&^MuQ1kpDKv))u*=gr9S)QKJLK`0(7C?q70ZY%t#-p0_#Xm|8;we&wZ zuw#0_ByP6|cSKev1{R%oj+5MzZmz%p8pu5IO$ z#}JzJ<<9K-*O*IX&f8KYu0#B7bnifpF(uc!dWJClCY+olDS;_Wn@NZ!f-VD{eGJ+; zI&ls!&HNe)MJ+fJo22nTABI>geIdpTx&;AVtI}S-tYP3#M?OD%`TxmllVl`^43OyMA^2zz5y$?T0Nd@NIC^UTpMd-Xv|9YIdMC1;6&vR5FUx=O z&@x)T@!)TSkA_7l!oU5hy`)mpk{!V1cA|1pHKLW8>;vtjo1)n){d=PLSzzHbNMT3w ztKadX=@+{h)^!dDZ9ipW@?LBA| z&9HbYXBij3Sl7ObrL#1_q@}CMe@4GkML6OTwHLt@cqQr4HQ8IkJn%NK-1|$&w$E2?Pll=KT((!68X0;G& zVT+f02vaFI!z6v=P3(ac$5hwdXN`nPlL+21F0AR(T-Pd>f#OGQiK?LC<6}+Hwro42 z!#}UC+w~r^O!g=WqxHTkA;orImOy1brMUGh`f$S3-&~ARqI4`Cv@L$ls=D*y2)bcSwKcv~?CgS(IbyOyO&lTEGGm*~Pu*z|exeP7= zLFGmifRS4g{-w^mEFnEJWOI_@@&ywh_`P1knksI`P4Cs$9!YT3PGs?8!zOFI*Do)O zz4VpmrZl&q-;%IJWJj2T{%P3MO;tE%ggaljcaaT0k6+>4si75f(Z4ODn^}$)kJk~6 z3|uC-oBSgpyH8Rlv$b~;8WPm9dqSap0Vso#1DJc-{g4HQM0^XPZh50g{CNPffXi>h z5|8C0Zc$As<$_mt<1K5EBAo{NOVj5Tb#5>_f+5G@Eo{w_)-K0g{69n6mWP*~LAqDX zamb+Ey-v`d+EVlLQKd;bw!%t$Z)WP$n(l*PRq0vbvQ$9s5pG+Rtx!4moBiMLU7|(y z%q6%%LG9y+mwbbx>?gQgHdb^Ba(44cv51O7>8xh>4$U<$ zbSnMgl0+kqJ~4Z$EkNQrmZP%xL7_6N;l9k5U;uB|nOIZ4nz+^Fg{IVY1G$_XfOf&_ z(Ah%wt9A)x`*Qv$m@d4)hmGlWylCSBy2;|aQajX(Txsw~BanC4`YGLsd`)G5pyHf8O&xKV0yktT&_ z&wV!XPW_y{QC@kSR81f2POixi7D3^70jZrXkiO3jXAwcw`sqn>CL0ZJ zu!sC6ooxrCFs1Z~E(`Wx%KttPB3LOV6I^y!i`eM|pMJJP(=r;2#V9=V$u?~I?V>em zdW-(&Wj*1f^G9BQ*{c1+cC!Ow!xb9GAeIhWX|k?u*=7V-&^42er)JB?*M;_zKcxCR z7DohZ?e=8I5}D^C>TqRZS2CkY(04~=wF7B#@zcomLwJ8&CGcw*>|GxDT}EZ6g^lpB zE{QP=J9j{T_)AoaMBmK>Qy47Br~qrs`G-6dv?@Q;+Ku?kt^XA6S_FW0@TSxX4j`ai zd<5Kw@tZjYet4UBEG1wy>jnd5I1cHSPvwA7@$XE9?#m{Jaf`v=Z1`kTh;Xb-+#OaZJ?@!LEyl#M+pZW>iRe}R*YXUyIf5Wa5o}kxjnWtLK5!TzRYBn-aMbd@E4{|ddkL9%FAL+{T-o#X87!?T6x#z`r(p(C(qF~lAxn4z_U_njj`Wzc}*e? z%syJEJ7~NJArN&HQ=|Dd+L+ShBzKtBv1Jh>f^Z7@)&VcyeO z#~dtJ7uKQn@8-pKWF!z!;YX$Pm)(S>82JI1Zex63+Ephz^#6u#^_LC$42+AxRvXR` zC^66CaQR-(g^ye%U^)$0i1(6;WNJ=OYLp|oLIyTYn%9L9AVxf{m1h4C<+ zWK=!%G~^#{EyWNU^s(@e9EZn|cLui-oMW2Ko#*B5`$>$qL9avjFMlCVu$?{AS5t#- z0*kaebqv!FMBRrv8y7MxW<3SQ;<*YVbb6$TA;F_cAc5xQoaH{kpt+qk%{FMfjk@XS zqU!65m^!tCAFHIFb3G$}{Y*afSr+tM-s;`wAgCi&NHm4GTmrE`RDmxvWhFVBSw(&HmP?4`tc*YNf<>|YB7KF(+v((qc#EG|M9OX8qe~5#0hM| zc~R@xOemylO?{-ei^cF+xI-Yj0hWwhogLalGch^qWVZ#3?Ca^ zqN3es_GyiiehnTV>NWPitcT@S9|TA^*XJ`WR+035rUQ!Nz3s%b0smtOs}*aMomb?q z{F_Xm*AnA;_~%70cGZ3ph$hbBY?OfH7=0=)6h!{43_bOt8o?nAEqNnlBBG(cK(Z!+ z2A+SFrRfd+FMaJp8`Emv)|zka?QrPkIS|d|ePT``K+d`w@1d&Wq) zWcKCPn_URaVMBTQR>3s`V>@hX*-wh#x5!Ip3P5j)Iy51_0%kW})# zQ+_gI;{Z7A43aCgtSKmU+HbY6KJU5z%lQ|Vjtjh;UHkT5yD3%wg3knXi@ehh*I(eo z_+dv*3M%%?H}I4nN2NH{;UBaAEL^zsmf|F$NSH;Hc2N z(Gy`eHuKZ*E?YiQ&y4MmTrcu6xM$Ghm1}jj&1bimP*3Gzz%{)6D^rx&|CZL%;$X?Z zWd5}I=72R6|GLU+wY07y760Ax!BJu;d@i{%TOU+1x?+v{>mDfkpkP_@feJV8qPRo& zKWBPak2ZViZ*=Z(IIOz_b>##{cwdyIu6LNX4bYFK{zttY%`br$1g zz<`@x)1sp9_$CF>ed@n7T%MXzV;=S?iI8u4zIHc~d>{AkkQ^G>XA^F*cCX_$nF}a^ z1TO&=!x=T5=c*>V$*@22$`3jYfP(UP_;Iox_$FK;&UY)CqdUe3naAPLZA>U;Ff>9K z*H*TlR}mL+$ZI6`MdVE{_0wN{D=K|8C`#$9rlb`^IqBX`y6AlOD zA5#oBW&+B?>ced81&X_Ib9Y6rGyjqzzrrkBCo2vg6+?$yOEA0wpnbfIEjz@t8 z30$;aUKw%pvLsZ_EgPj=reG(4-pmXZlzK6nd&u03_=#V? zy>3Im=nv7lXzHP`PUHx$0`b52DFaM7M#W;KTnh%EP0Teed^4|4`ZgQ|H|K>5Rz{{8 zlLs;7S}PN!EYKVyboCqDFAXf@ zXl6#+@e*kEEJ@@W`>~R=pSFjG(R^DhDFNYhqLx2!&*s*4>*P{!D(3F8i~9T8e2qI+ zLLsrMU6R5`F~o`E%Xh=Q<%Ub^Gsl4XPt1}-sJ%Bj4=SX0daXT5Z$n1qwEJ1~wWy^g z5Nbj?o+Y9LnqD-t$YBkA^P+*CpQbhCOszh%YILux|Ql{*o1%?EJ$- zmfdW%MA^Ss?qEKu6sUNxDWlHVP@&H)8lsqh=xk}zK9fwe%^m=n(xea ztUZQzvAC2tE?41>P)NI;@JRo4o@EIaO3lP_f^e`*WeogS>E$h6Xc7s`r(5_U``17( zly$!4j8#od3?_!VBtX`Y9b~2ke<73-yp>$5zm=)mV%ohuod8YBI}kM zzuZp@e5&p-S;O1sj$Oz_~?+e#--$^+ZT$(1!xYL8|Y<%m744^#R3`_2?uX{b(`(yd7 zh>tzvJR7v^2_&`J=llnUIn(oKC>>6)rIop5AQK}^qt_t*clf}3&~+KP9?Lg>+5{q} zZUK?18Qj07owYlvuW!bNUr#OqaJdtzsp(P+x9FCHa+_iOS9Nj@xUY%O6old1*J;R~ z^-1H?>)!FL3H}Z4q>KuzOCr@qSw|m`ZReDhJ}vBlE|U_J2S;wBK>F@J-IfF;DT2Qr zCbY}l->(U%fMRA7s95E+kZ|(c4)fsk!q~6ZS&$)81&ZUmC&PZ_YjWg&PJ~KHPM@m&gU(Hrr8fUpD=NsI-L!?{vEZ|WfT+>%h+dh?t)VPBu*5_%{s^-C9Kwl+jwCG# zUMW16JKz?58v-glW93)4xw>=k21OKn?EQJ;67{U(a#$+gmz>B$!ud+S`JgsoE=q3c zR}mTAfc%ypd2a3QEQ?fL-2KcO#jXhUcMzUIbpaRT>(^3^S7AYlKGJ+7??%6lf4Uj* zFlxHf`3`(uy9Qr;Q7@6tCBT^X6xF1b*kz!;B}tImL994ZDOnSiSP#WT%l>$LZMf|% z6j?5*j&>sUgW{S>Ec`28kh|HAnKWSIlin(ZBgCb!*cnAx72mcjHTaH4XPeq5;B91Q zoNX?Zcg!@(I-8)A^R84GyzN#KCSP^`#BYK0Lqp#mFQS2` zS@C`P0gOGV#y1k@WF887zQoKHnxQ9_gFXV49_mhwK+$_U^Om49uJH0D17_m@BaCvl z(Z-_l&}jY(UE`01tEMz5LN5dU?AB#UNes*EX&n8NUrL9sw_FabCCWcaldc@|Gjbd0RWKcC!Q^eW|Nsq3zA|n$wxeq`h#dT9&_#m&(1awe`2p!Ib&(4(7frU zKqai9xn0VfDqkGixol;e31)8yq!dkdSGMzNwkiH@lf|sMC#M+FoS^dbJyxcON~oDV%*v zXSp=;j^8PUI&e##^>1*jfyttS-7<>kR6M_rx&NB&nEfzShQT-U)y?P^N)lK$S!xbL6=XJ27RB!_dQ@V1<8N&J{?}9cSs5sZ=+-{H^v`hS`2+?$L!LA+vs?CY zXTmc}KQUX7Qf;w}>-5$9!^Oh*aNf;01;8k#F&iD@wE*@2_jY(5rjs4^xltYp-Z+B7 zH88VodGF_(MA6)+hS#5jjV8Jw#b5H}2K;1_>(P!^E@JB!r(?WfG_~BkyS69fP|OKxpnjcMmYeU9up=*Z_}j-SYXK+oO`9ZPRVB z_3n!y@mmIN#=+u;;CD5n`s_@ND!PJKP*P4P zGRe9a$}@K1@1?P#lO`ETDlpSS_^45m86O4 zK2!BT?GLOfFy1B&7%`KOrOnMaJpH8$=I~~Vv&J7SX^cOb#HgkWhKlB*X7PMs7#;*WZ{Sy7vzaUH?O6yF}|tqkyk`Nd4QG-O;7fZsJaO zQfURmcm5Ftp!@o4w1q$6_)GY?_{rfO&dCclR(;#H(68;^_>&jLVID%Q+%wGgJ(5AD zPzER(E5LjGfpI^t=*F<)C)b6uAFZ6xHfHg;@G-?H*Y9F;-{ZySi zf-ea6`y+eagmcB{q%xmxaScJR^ub;9HV_A`@3m{UNkgDd{ay9U`_eI=`wY}uB_~#<OVJ?xx&eS=HqY+j5zH~`L>}8^k22@0<|Q? zN)0`Aq59kQ&7jE>f;Kyu+d8gd!*G#0(u`y<)L|R}RCK)rM&3 z{em2&a5l~aCV#jxHer|Ac6=Ie(6GWaDb7V64rePxyxqsZy7p3WupW-vuHM(cODAUdr^3( zEMY}_C)wiM13R2^&{B;K^dQ2Smok8u8AJpOL5g<-vukHd(e>G45J1hmo>99(dP@Nd z5Omk3xfggu+xly+)^kA3&)m#+Wj*sh>}EaF*mj6M2#DhQ9m%2F^w=Cn7zR?K?Xrjm zJ<}to#O#`wocK|iKgYwNr{Q%nSwe*kJUMWJaB{D1h3+9`0z#=`JAZ!svndgczNmUC zw+hObig&&OeByqGMUks(!aM>kh#|i-;i4lp+0t_R+i@A4Q!ESF&2amN(FX3os;K9? z6BjdTD|)Sim53b-;y9x}>?Wd;46Ci+jZj(Jm!^UpJSB>!&TewCMRYOb9U8n`QB*^Y z(K4JVo7Pn}s3Fho;_aw0l?KVvXfEhL(>+iPJ40f*cx>fHSo{zdY7(!iu*%!nAg&&D z2_(9M+%$Ck51;D-50nF*>WlQB0nr0l{GG+yfcYX?K`>}bj^`9*<*^(vz2 zIotAbM39)67MZeoT*zNY-QkvWRTMwpqPbVFvo^MvKnw$}6az!xBD>P&zX?Wyjg0~x z8K2lbJ>P9yj|dmMB7!hDqKe^scU_j8iL#UF3)pqy=AK&s=-<^fXdimR^*l)eY;>mB zKak*<2nq(f8T-nD{1tu$@{q6Q(AHuyptF<_pr#nwn`!r*TMRCx&jkLV&Jb5}5zlrJ zOyI5|kgfmC@gToPBN|iS3A^T}^`#fH>*zk{)-lWn@?FEkR_A_u=>HnTx2%_W(mN^+ z*}1!1n2#LMjW+&#+a3ChB!Ni9#|Sa5KEIr1dIm6Mv3uE2RKxnUz?PwHNiTj3$RsSesN1uV%an_XFXm0XvD2XMm(IETw%)Vtv_+oR89%oG<--}ASj zvk!&htG828dIUPzk}=n6J}LQ5T5Lp#csouEhP;`Q^6Bud!sWJL zpM?>4I^U%+E*i30M3FY91NXEIRQi>>5{o^a(p3fPd-@C)oJi`D}E8S~mRW<^MYux_jCa41>mB6yra zXZ7qT3oLLLT~D>O!}2S-x}uv7&{?-4kt#;)M0IYrk&3$g*_0NGR<;=>9Jk)3J#cP! zGaQA{1Ppuky@iYsop$9foyjYg&AGdL9-Z zm$y=>>y+;3>m%v^$&IQ8Nw;+&YH8X^4#|c z&%#nRYc8c-vsr8~?3P)z{oTpp7qB<%=IlI^?R1Eb;DV2^s?CsMJx4P52GHNVTL?Qu z`SUqHQ-vh8$Nat5SU{*gTI+HV-`hKJX}p!c6?!*lKtS_XfkF=7x^GQGR)2TfIdDiwZ5X~s}VNa^MicfsL8|i z3~9;NUD6|uIu#g-&**hfJ>Pk!OXBIr-kD+r9er~7w0>Z>vZ~VmL4WXz#`2bYV3heK zXBOBzp0@>cq286jM?>wmS7Dg;9rGU7)$?f%+%kji`O7j5O-iUlWhQs(fO98zaQZ#C zoI81o&C7X~>#sa&`11)yhv_AOkKZ>q70=@hZ-q2Xm5L0oKZSGCk_`I~p;dEF&ek4z zKgKxMjs(1?%Ki%54m>3s|Cr{Au9Y^_ed<2zMzmxVZ;fOnPebdL)&7?$V#2kef93J8 zTmdCLi+Ll>o7zNxGMswKh8PCCYJyy^Tn@`@^o#SEAgw}KTK(82zPN_t-G9q|v@_bk zY@%o9!PwK1T+~dPcz1zNir&Hdu7wI}eeAE& z=R9vNvBgT=>8I3$8_8m_A(H$Nxu))cTc@s1ON?OAFXyX8PSB`&Hum&$%@1Y-fT#Dn zP!q8XPyDk*6wkuf;@XLq9w#;%F7`=;X`2_RJF#CNSMvd3L2?-IT+SRDAE(Q043nay zoqTE+PKKt#FMSkzkCCkxy#(35RxF*r=BJYRXIZXb`(5ldvlZUNxh^XGc36pIkK8-; znRgP)dtMYZ#HQlmxehegiApxE{J;Ei1V7x z?%779r~6peCmuhH9%s5T>sgOcY^6IgZEep~eFd}fLq4z1!aq`eS)7UEzXXCdudOvr zw+2S(wv2`7gdeAI#!xmGd7sjaGH}KF55|y`XqO*K)Jd#GAB=<@+e5EZ;_-dX0|gKL)~;MbSTS3?H`yAB{w5gOUd+~inzrJ2!M!koOr<`?)Pzp zli54lqCb_p)*hsg!gsSFH|Z8%?}ngwPrGG&>_@gQywgT}s$_`>{V$DA--}T5s({bq zgyc52(3nz4K(3O6l9&)`W(f~vd96Fx0naNo+tv(1BQ+ZI2l6fvW{}InXjj3J-5`@> zT=PInrKfoTuZ;DoJ!pF|v@@DTg3~XXJvEv6b(8}(Se=9Kh8DkQ&h{PEZE$qFhkM4nH_m$!&ECorPHm?7muxk&q{(j`y@C{H^l)cr3m&CY+6ZqM(U;vh}o_9wEp z?q6dhP5JFsqDArS9u(wPIGeDmV&Ys*%#g`)=+0h-nQCJ_doKY(i*h;Jj`+KiUgRFf z1>asGpG9K#RXY~G4$nV}hIsYQukJZhtJH)iKR)kb`n1zyL9HXx!HK_!aKG>#^mIIe?}a4K3$B0^&wpqTL79Ot728m2xW>bs;N1mNk&cpS3#3&=lk!8=voy!j)qvs zs?kEUxkG36b|h;}KxB+%u8BFC*{Vo`Hd5IjBy(rW)z_1Q$!AZ`eBg!@qv zK_AB&7`%(2f%>vwz)-Q}O-tz=Q+Vfb%6xj7a5g7lI|FVTLGDNv3AE^KNE6_vr;TwS zH502uT95(=@AehN*hCw=eeGMK;!nHk`UXgKt{S@OG-a6W#cx4Nry zX$t1C9`q>t&*ItNKO2!Ddg{Ikl>{jMy-+>hqvnmmEUeN!*Z$07V8%3 zQ#$!p1PtxZHT5NAb!&Po97XqsnE3@`M^TqTFHNQmLCzBtl$e2JHfR8Vh>FT<`S(?Y z0-O>!iN~u`hpBi3j?d?rNSP2xHQSSJSU*>Zx(ABi=9;^hb#rt%C`Ttw)=nLb`lbZg zUAW+nu=*sr&@Q^gp`C!2Q`^@Nrc05B|JHUU!%&dUQ=j2o|E1ac-=tOH_?(M_eymJV z%S}B)_GOGXP2J4GusH)jk(+#`1t63148VU&pC8;K-Sr^Q3jD@za@|XEs10Y~g*u zdlHZ4JuRM0VD=D_gdW;1bmAFsFH|aCbuaM&fZ&n?_#UejAsVFplkF3S6<8I1GYiIx zf9P_%@eo;mkE@>68% z?|||?Ia#clY1RSeBBAvitJz6?ZArqWi}ceIIW5n@S}s#7tF6a{%UA1h*$wKx2+=ja@BL=EIvMMVVLSX>8Hd@qulaNmG!7m zsLp_nwC8XYD_`i@S9JbWOX2nlW<|pDPhBrNdRUA8E-}5`mrnB;^!Q)TzHL06zV)Fn zwDB=7*X6ZRxq`o_hsfvlv9n%ps;zID-U-kM>LH)1b$axw-?PiAN(N3za2!_uUb#bD z*IyQLyiOZmxQN*l{U6o+mhMajW+=nnNBvIs+kz?mxFzC~{TlpucESi!y!n!*g=bbp z8yV9p^rM9j@$K~aep{>YFg^UcWj3V}FIUoxx5FM(HeJzlA+(VSE=>TI#Sc%k-2Kze zRQnE?3Lhu^D#&GC0av>#35qr+IokfIe-KNaN&w2+@#mwJuhV(K{V;a;*x!>-&4$Kr z-t01U!q99TvGy_tl z*U*#zp(#ZaDHeJOy>|svYUo7>1cXpeay`$v@BiSuI(eDT{`NDoQ}#Qvv$LaZFwbi* zLMCp!2?$cVL=bGraz=#@nlc|>d8RxRk-=O1uB|m^z)ST3I^4uaEfuDuW!srL2 zA(I&S%RItR8!4rr0rmjIwcqkVe8TH+_+E|Y_c@OtzGL$f+t=w`0)PrlH|4se|Yfc znipr*J-Apwx&UIg6q|j5} z`|cnA`U^_FgQXv(mN8c`I!hteYvxaHc)e|Te;^|nWEEa{q}t3 z+)fYJJP+gNy?aiTKE(af@Z$>4v2QC0Gb??*T1VD65hLY;+>g-G9#gLu=jg=r-(%iM zwA14!Y7{SIn7i8~S_)Nem%h9<=cHiK!iH6Y7YSaG5vT`ou;*{npFO4_U8$#}N)pGj zb_3OYwU>J6)~&@-Kr}u-$Ht4F!d6ltpEUwy5T;{QW!Y+SThE33`LPRY!FRYl zcU`V<>cH08^1JV}Uve%Wx)I!J`J^E>s(Isumh4P`g5PSlj&J|Myw;Hi2F5&TL>{TO zsy!_+T{rOx(iFUsx`}u#71YNls1C3wi zWs>D{VGj|TsafB3Y}lGO6_yPIp%M_M&;ItxvT!Odz91uy;0*O5->#4NZC3maQvDb* z7iLm%%g4%heq^+;+K&DoBlqMif_R}aSFuZP)j!g!4q07A5Fl25+B8UY*{>yQpTT-^ z@ZJ*^qUfcMy2GVjvu%O=Hj^T>7-E&rk=(PYlfZrIlIfxmc4c?{XdBZB(HnD-)2 ziL}1ibAhl+S+`du-hA#ZYC>FDaEec>Nc^!dkwK;15eSooONmXgD-|Gd$M)$##p2J6O!XxmIa99*%O=}gy~4It#;92{mWk(t#v*>`Y1Nh zIjBfk|A!shy^tnZi|G-+0~C@j<_)OteWO{ZypQvFOrroi+>B8YM*#8Sx(u&cK4Psc%7SkWLMlr|LH zW;uKMO{-Z~<{F3!IG-!5tJwKS?&ym>%n|8jw1oYz;2anfLha|6?jrT|B!;hL3u~Zf zFbr>I-{$uDwfoD0ARgr!uYFcdRB%E}Ee%@Cx}1MZYFQ+Z1l!#ZrP%#(r{ZY&_yYGw zA;6EHqEf#D%SE$$tMnK`C5;}QzOj4rZ_Vs&w(7tDt8(UvHcg8vn&BDYTv29-66c*~ zDt1YYLmL3?a+)M8r&*!^Y#2h?2%W#E+O#JPLcq(#Udz(p;KfgXQ2D)p>tEe!tJ}3! z?*q`Pslo&c$-lzq3L%76^G7ymD|eLX{9 z5W;vh&u8mWK?O|+zFp7cszPu-*-h6py4S5CePLjV`L^vYnQ!NVfMBbPJSKa?CD$O) zp5m4Sq~Gs@D~-i?_yq`8mGta#rp52u-4JJYCbR%pjVH+!#(1CoPO!I)D`O=x<*=N1 zNPO+x4$Ph4!A~qH)K0uZvx8jgEwWP@-b2*`KNT$w{L+#E98fgC zN22j2ffbt(`1237Ya(wpgoW{7n_msy1%6-ltobzxkMs@s1(aUB7qr z5|U}+E%1Y0Ah;EgogG3`$%Kc$S~6fT)48i-d3woG;I@sS2pg9iZCZ(pfKm6jO`AV; zFe~M(jkPzi0N}t)_s5XUuOD<1!MfwO)}wd94!wFJ1OU)b2;KWoURgIZK%YAyEmM^s z{6@{&05#qB5Q&m6_m(78ObbdMe6BmP)>K(1Ii~K(>x+9i7g^5+X#=w~B~SHGs({A! zKPXEL5U?tK0e*H+6~g^vzpANINRHLN+*SbO7_rA zueKh7wU{2kK7|C8Q(B%n2lsoHKI)GID~=?U+Qx*$eB&mLystj(S^&jc{J;zB_)kZB z{?H>%f!UpZA;)+hPoB|f1$K_>Im(oK&!^4pOQZ0~9Z!V!3;9gXol~2UXE$e?HZLYW zCPGvtC;R+^fUNO3yA774;JxL9|NHSG$MBq07wHBkBbM<{v&57F3(A8~uy%{#RD8CQ zexBv;@kcrU&qlBl1&LhrekXfnU2i52MvbiJZ+*Cy6m4s~@V5M0jJU}!D0e4?5GexE z+DPrmM3@(J-$r!umC!ZkMYVKa4*e!~HBU)cZdiDhK5a)_l-Jmf!i*-#McK|S8qwpc z?$hB12FMeQqWZeJRXZtp+C_dK?*$Wm?0)`}C~NI)3G+8{2YM?M_j@!0;#FGw?OsA>&W zzlsCxFX40oRE?9OraWjdBD@)381>4xr}%9?Ao3kO$FS#JZ66uWvM}ykNAskwVJ@Wm z|D|rEuB70$Ojc9*&~?OTbx!NzyG90O&sA?GS8kC~Gr{S|L}iwiVE|L<66J7hWP1oU zvTFA^_;Jpz44K=8X?+{L#?PCq`7+W`j-bWHuU6u^v-d} zhL_Uk&hQ0PUuN2C)ZGL--~;+f#jj1)F;L~P@tHf|^2RvEQW`;l>_D0Ri;|lheE+O> zYS=H$>vKiY7rr>PSD4+qg3(cJV_m%`pc;G4p^EREo>C%U@N)3xCL!w+w}Hs@JRhQo zwF49LI|B)Rs>BhOVo;RZ)iQCpR}2R911e0HWtTY9rg0)DFyX$DNX zbSBVtUFtwGhF%n~v_M!x{;)DX53&Sg1KDQW7_w;7ai2^%p1FID>OIkr_@sU3xzoe4 z>?fWZZ}glFs|p?p$buYuOf|D%a#raq6jrvo3Soiim#nG@$;$2#Kc1o;rD7|JUS-|W zX5J}Yeigu_n}^U~=1qKKeO<1LDrJvd$?LhQ0%t6=g)kql32vm}N!}Cfdihh1iorQm zAj6NC{}@*GIv^vI-?ch0)!KP4vaWGoaABA&(9+JYkyF-o%_Z$48dN1Xglr&h9e+Gr zZ0|JIe;j?wvv_b~*YLpJDuYo;3AmNc?0orXika9%;rS{C1HEz0S7Xu-Y{FW5Ah5K} z-1ck!7Hx9)L+ESpaN!%E$=Yn0Mww}i%`t;?y|*FCSHGmgtou=}0i7r@GRJMi^DNoW zdN{VE_7v1XcWFJY`KvQ5qWD7Q)5Hr=qfe`6Jr=L#!}`1;-uhQ1IdivFadtS$$^3aF zjJZ;{bU;r~aYzn`s9&#?U#da(xx(r=7QySOJrZXkTuv=Jroo8aEY7ION}r4&;HFYZGvF4C1&j{z%K938v9Ajgv!l`uu+L zS?s=tw_8m|<9oI_~o+f?F7M>H%9x%~4nclH?t2*|-6H{loG>fp}->h&!O`NCIB z^@A|4JXGv@T^}LJ?kv+D;Bjb}(GfUiV;jIaQdu>Cp-creDiyTL4orMq*i+AV03AgB zCdoJ*TyFQgn~ z_OA(}pWo3zc2&rp{Smp>@!Q6A0c~1~3@a_|^A$h&Tp9IOG1`57NOJ@DY&*>kUAW;_ z(@bj}=0AE}wIo5ZM`vFah|Dwb#>fp$1<~@c$^aAN*s2LPxo8;<($Tu|-y@?RKg^w) z1dU|z?RH#=qEt0{5xje?1&+gI753Y4J4&~B>f?*dEW)GO$CPGwf1f{~L1yaI@xK$m zT+IItQJ8He!Bpgl6^0Al(qAElGNl~BH?4mxpk3jUR6xrrJ9C%`n2XUa!=@GV)mo}t-P@unwRk|B^B=nS248w+CUE^x3wY8 z(~r;LgRIYr78?`Z*x7|WqeTQ6p!ItDxL_8e`OBe&5LEvP_vzk9TkfmAwtee zDQ~U3P3#;#Vkaw}=7P*7FI*3+$=xx-n#g0!PuU>61wPBsw7*j;y(S3A?+mllf%bYe z=G$LcR#sa@i3cUv%Iq>C%cqJw{xRxJF;EQSH*uA|OQVD9g{PacS+6(JSjUUcQ!_ke z>qu*1v-Z$xPI65h@b80^?eOB%hc8B{EL<&`5~^4)Kqc3-fHkN7qwEx7CN^CRz^-D9@Hg&d7H zk|743#M*Cl2G&0lH1o;v1f|EGU+nJ2>LGQp7_mr0!=8mIA04*1O#d#6gjeEr-1F;#w)^jvsT z$)gF*nk%Rx&9de6a`?4wsVeaypw42eru)_m{==oB}K zDoF~{y4UwT1;`Q#J4V%yLK!I%%sxYEp_0*t(IAQct1Z^!**D_3;_s*AbyVWaNYMuIad`Cp}pVNrP zXW^*Jw~2z3NG#;_#P=M(I0}3_133a`7ESB^LgJ5H@jcu~qoPDV3vG0DczV-krnIoTfRS$NM1NOXv7DMAQE^=5l9@ zl)z&sGKTJTc8gavTH4g>`?Yk7f=ZjY71laLN5+ju%c-WR;4;EGtHZ5t{q-pGDdzBP zkjf_QT5^7OBr}~<`ahR_2|#3&Ka+1Vd<|AmI%@ltS5ztu=5??8aom%bg}zQ|pmJU% zPVfOHSuwg(#cwP!CwLMyy*%7y!Zf}DP7d7Pp`d#n9Tqa2appOBJ|$1Gn7;cec$M3H9a6zNZ{k%$<{cDk4Ej zV-}6O)nR zM{Wn4@^5bmKL=t%@M63bTOx+N!ar;=2c{L$J?Fj`_l_y^X$QoTgdR>2HK(4fRZ`zG zD80L#36|}YoXm|%@NQu7MKbZ#Bc^JBh^8C=Bmr*d6gj#beHVP9P?aiW!Cv<#;D~2T zE<%FCEFv$lUCT^X2Du{l+NDyyAtX%I@-Q+;lv6=)UOv4c_|unpyF(0NT8ydX%~gFY zr5bGq_fj?pQ03FNGd-3VE;u2yXsX1nm$1?06bI%;(}9@QO}F5rtKU)rrG+IvCwEa@ zd4&EKsYx1ZyEwpKPr9d5flH{H!z5sL%2dYCQ65I~%Gf-cmif#;%Z7^zddjbHy%1uY z2pOE)C3Sk^y{TGxA|XSl)Q@7}4j-p7MXJtsh>1J?%GQ+Yau68wotKY1O^uv`?Rjc`#;WUT ztj_Gd)_S0Sij9uobapC44H0tQT5?*q35t6GSYi@Oc~ zG@hVrEFfpXSk1i>P=lxD<=g-p7{VtHf1M|w;nu$Rz+w(o-to(}JLKVfa zEx>OWsa1BtGxC`pu*D4FLpk33Ai>@)bY=SOZJMt|r6K9!JwLV-R+aeubh0TgCv`mW z3YT`ypOJOMnMivaZ6pf@_q4GxTGjF8sgAD_OT`6;!Xf^d8oB9na-B9JDcK!atQB|l z**)`Agxn2u##3Tc(xrzfIRWxd44dIkA3PH9VJgenNCbgbWxTpZVoS=jS41>@_ZnpQ z!bYALf_{4Uy!j_#(}>#sEUa$7GH27+wsuc$`e^7iY8shhqeMXx)n5|iv9IWU@Ih+} zd@coayE*-O(UM{cQE&iH&A;wIXWycfq4@7=-ww|SVw

1WQC~cV|J1X^WE1F}0^9pug!f+vwjPddm8_?pV5`8( z>JIXYBXZOy&i0k}Ep_l?i4vpZ(GJdi!1MhWRc50SF%im8+Yrw zKlNUsQHpZk5l3?A?6l$uUrV1c`%JN~T%+Ldw*634kNuuh3j8&t@&eZ0YnrX*Rj29m zDb`qO`q{4~@x#^(BE3_{cpw>`5Sw_bPq#A)9`st;7OVnxL7j4^nhlns%f zCH`!jp|!5Fo@fYmJ&J=fA&g*fNl$WF!StjPlq8O;M^+S1pSrC~S#CFjV{$l96H7oB z^$#s3;^qDG8cbAbdi60YtH-HB^f^)jI1{znFdfer_~)#86`}aN2S0iAtm?glwoUW| zNLezSh@nftE1!Co==AN>OoHD9zjx$U{guj@bv`&*RXKyAiF|UY-E6~krvGa2)xwT6 znaD)Br!!8_-b-m-)U;gH4l|Hh#RQ%6R;MlCYQLS=^2BO|BhJX>?w zwqrxhaIJNLvM|V-s-n5iv_FYQRVjHYxi@ZR^tv)ns|v)k9=6)MLFF|Qv4UonCSL4m z6@_dKb6&~fzg3!kDj4tHd>AtEC_iIoEYAVoYj@8W_GF>=$w1&JsK&7?o~&B&k-U#A z@`JRK`3jr4l8x<*bJZ36oS`gvbb$}d+_K^{^+mBX+~;cMfSsz|(!iAp-FQ`|5|6rh znHHpw>P`;7P{Nl7!`|O7y%Sv0EBkrlNjnw*a>dH!og2)1oi2UZ)8l=w#0=~nNmvq3 z66f32yY4mrA}F&1EfpjZZ93Vni>|^+plZ|6BGHb@;Pb%bXG(1UERp_R_v@ENOa`DOTLp z&JzhqWNhmyNNN0jpLV(1x(z+-Kk|GF7iG68n4y$g{^0$S@sOW=@rwXl6Uhwd1mDo{mQL~HD){c zZ+-xQ@q=(1(SZkNR%bo!d5SWRmqlxks$59sm(S)D&uGE=&PLS1Wn=_jRd1Xw8ESLw ze60a^YDFl6ST_CPjkiumb4jXQ#|1b4XD2iAg}aoXwz= zUC*b{b{ddrZ|O=pH*r2DTdjkECH4W6nANlHK2eXc%U@2tIIYTT;+(GL#~ou)5PAep zM&L#dPuyk%#d~fQxcR4>&R=dADY41Rz*$#eQy8P*+wnhZ*MB=c!tl1(7k8If#WD9{ zTryY;+6CN}{GZ~bYP<`EFFM3Gt}m95tv63*LByWgWR4j-R2Ckp9OUMM=NE8`Y0Eqc zXzQvWJs*;Q*oTiB&;B(ru3A|Yo5jzLSl0AnFgGR(p%Nech4SE)@)RGZ9qyG->Yi#d z3CQXUAK;8@@72<&~5<0Z4kCyp3s z0B4w+;Ft{THbC-;Urw*sRlP+>%kAAIwu!AqC>zO(5(Kr?K@`h6vvJYaNqSEpo9ytU z=k@m#Qw2EC#SCBz_w=|br63H^Pw}@coOvfH!`tD5FeuoF^mbbVA&0lf)Z4K>EILa&eKYT#jqyBJQ})&lmq$m#1=1IgB50h z5dQf$4mbarB( zPs_=B^#WQuL)zCFDLxySo17rMCrnL__w;JZxnQgvC4bP4ORUQ7N_|V-SJwL+5PJ&6 z_&fO-iCFGX{xs=zFn+IKI`y?4A{iM}>s}StAc7$|_LhIo<-Z+Z+&%#O%8$(QXgY?H z26K%``T%GE;zl@fp>p?E@mitZBA&+^TSbQt?o5ZA1rqPbCaE;nS!b=K^ERVdUi#z%BIbh8CHs zq)}za$9eOp8AIKXys`baOdPFWo!YcX*xoKL@n$)9PJ|GX_3Bnae)p@(nTD8=&oPua z{KlN9YqL975?Er&Lur+6-9F)?beI9T#n25SC#A&SD(r;Y5pF^GLZq!C~ejNyl+Wis8Xex72owLho zHcfgus2Pb9kJG_YJZ=RnBKlszhbn{ zqjK_LDIjnTU7yF9(ep9r2V?dZie}**G{=56n6K?>wCY*Ik%g^o;E=Zr3j4*P@h#B;n(QJiM==H|vlE_{14RM5`A ze@%UgkZy_mO7r_1C2)rfkTp|h;Se}$b)L2Zoo=*PXL263`-|U9W?)m;t*991w^wVs zrZGWid@p=!ums)E7)I(D&*yS_2RHa-rB8Lbrn9K!jR@bEFRPkU@QP`}ep(O~W2)RN z$J$3~?u!m2ybPX3^UM{Hw_lbQ4ilAU(ReioX54ePKwyG*oq&orPyH!c~p!j=1FCC2zjdkKgO}tzZ7k5)5Vb z=1T&X`L9`D09S_rwJTEWXuR`SkaGQmHhq$S>d&Zl=@5ga-{LlCL`TcN?sBe#ObhJL z(c&$GeRqN;M1Ts5l4)B>@)(0mJ!k(ImE{-Yn5=4{Tz?eW8CDK0VoXbD40Mh^ZM&ga zSegFToq)^Y8czo#Th-!Tn<2qT)pn3FIe&>vxZ&5jj8THX)reHuyAtY7N;@U143L@K z?~B^~BZikuS#D2iygx}T(KXr#TMS-dVUb^cGc)%GE|F=Gr^L+g>say6 zhLegZ@Y0V$X%uDNZDQTtDqStb8HlzN%7Cu#;C=Q;=PvVktAB~ws~&h;%|MbIX3gN) z)8uG7kXs^5Wh%*6@VyuVcy~ASeWR(*UiKWJ^;>Et)Lt>~#HeI$>s~*wW1?w*Q6YO% z_26AptK0gQ2Af_Ju%m|Muh+8f48(ia8%}AJ(q8kvb9Y?1 zZ11Y=byY$VBoe)=ZcaW%ZMVr%EN55~WSv-_q;xw{p|j85+}CTb8>L;{&S_?$q5Eik z=f|jZy-aiecYXHBvsjIzL^FpXZ02G_FD)@;u5RQZhWh58g<1}XW2R2&hghp%rE$f< zgJmsh402Dq-oqNV{?Um!0HvR8PJBwGthr)Y{>b@A3bj7IkDzoq^&kV99lvg;rjHa; zkyQ`%lu3mWNmNW%d`{!TpG|*V0Ei3BSeP9a+xc^d$AZU1P0@iO-Daz3J3^YIZI?R? zr5}QFS?CX<&}iO#*v*phX^)H5z%f+CroTX}o|quqvMpp*(!v75=@d72YP9x%G$oK@ zlO zu_UBF4FTnT!17*d9i?Bsn%-VX%M!@FaCPn`0}{JDtfKtfmlJ;IBq1xO%IASFUv#lD zJzj=iUo8xoNx)~#z%Os68vlYD$qH0<^tQMj=f`HJDzQas>>S;V;c0pKZ%x8n>%$8Y z?r?Vd&aKAu&!NMYZZVVz6<;*aSJXj>z9{kX5}Wm@wAh){Qv|TdEw47}$D>e(CABwI z6T&l3K8?1HSRDa-Ldzf>I!5-9ABQ+~gWG>zO*7k>cTku0$zq11D?yJHpA9E+#}ig; zF1kDLhf|*wCjPh_H%bxqb;;7;n;ED}C+%|XZu2U1fHqPUCwEU`j^BA4R<%Q+nD<#1 zyKe5j&ea#|ZMnTGi>FDx8h>#7r~B?y$-!s#5AW+34(syxNf#iNoNpfqAcr!7g{8Po zX;})k+l5$t7C0@r=}{P$(`z%(CI>RdQOdqD5>ojlVS@rBCUcU{j0{6 zI*QgfQz@DqbM=XD*DV9%o7|5vbO-|qdy?sCkYWE}V}@D z(PKdx5S0U$i6}UES4)kbms7%iHNx&F97<#}i;Dv$-A#JJre?oCyI{GtdgF)8JA1FV zsBwODJA|J`$%|&<&%L*xrHPT>I|nIw3&_t$VNC&||a-3LS)kDCa9*M3@WDW@&gPh{b#3IVOXKeF!eRT2=xSo3WV0r$b!k);kl8 zRz^R15sD8So|Y9Ga>Oi4pej=Zo$)E}I*7ZlI`L+tP^R;jC*S*YGZ{|h$ufj^e_XwZ z;?UB&15zQq(|O^omk~$%vXr0hJMyFi&?c0b6(&VH;R(Gw5>^6^3(E}9E{Y*_6USWb z6CV0xuJHD)gXcxd zIM8lvMnn31ebSwuq#kcUM>a6d`9!;OG5>teYX>gJSN9T1v9=^suyw%gDp@I+UsL={ zjJOWKoM{2dVAOb1y4%&1H-E8$H$J2SbSBd+Cyna~oR4$-&9a5|P=>GH$!Z_Hsgn`B zTVr}mPjEurz@ZD{#M@QiQ{(uDvHn>M&`+d2J@<_>#w@H1pq9hSEU3mPi}|&WGlj|p10{_Swa7Y zn~BTc8-W&&bBihR$kq9<`{hEW)SoFzD1p{%3D0VUN~?8%3Ne(zEOc8>l7Ob!xGvg9 zi9-_IvKEe28%=$u_$S)p$TYpsz|_#f7e9&Xc~Pjg0W`y@HQ7wO53<)vu^&R!(7fni z)BNIV^wmDSq=&*3GCjGE_W|{!p1~$l3K(roeBtIs!Ly#Em+gnOsQolM;(fb3=lxQw z`Fsi4$K^@RQJGSENajZ^8xJ-#^45rqVSFz3waipa(U8j#zW#BW;Hg=xX|R2;4bEra z56Xuy-0+gaXUTkihrD3tv&SZXOR@KX{0yNF+JDcUzfAMvmmhX}{wpVX%1%CTFt=iH z*o|QP?(j+yjN|B-to)mZ` zOO~VUr|XZZ<|Tc2+ia7S?}1HxnBtKNmMYI}h3a{wV%MbG5MISCf?f z-?9GHgeYv>-JSVaSiHQvn7ufd0j}08Y1yj~X(8gdJy>4iPX4n@8ad;<>uyQZ*TAO zGf=4ZtZDYnp-DgwxGu;>-W8;wLU&le?9*U zZ}eC+fzV0i$E${*@PK|9A?KfuE+DiVx?XL0^l9#vsTEed+uF6|J8gn|Bmju@Pzt3>7eE#*Ls%6 z5DJVA9*B)a8WuU~xMujA6Tba(E16xlY~=N}VCLnNiEH5NcPuuG#4Lj90JO|F%Cy#f z2`N3|xUqA3v%+=TG~v(|V#f7D5Mb&Webjz*XFxu%s1L!V_s+gP=TyiY-+44|-b|#a zI$m7iwhva#owMRQ!#xAf!q1_61tZsh?#pDCQ zaBtv`w;2cU>YOoYdOXUvz4C!*{tt<>@WiJvyT`yX&HDG-o12q~X=5bOvs+X&9{(Is`{whXHcU?^k>#tu z(Q1o~=ES@DdIVP3-Gk2y-x(guBe2cuwN1YGhQbl*<1j^217(;aBf+-(3EbTq>@yyt zm>C~B(|A*m_BB?ru+fQQSIi7)g@NkvR_Se71Ijw>D@GNwzs;U`Tp*`!8tsUu-Ev!^ zJSKi?5T^IkqQA|1R|9Q@Pz7vit%3|3P>8~XwpG9BBRg&`>TRf{9RUGozQLt6t<&E+ zzw{hY0Zhwm>TPhUxd7FzED+5(S4S^k-vG9QAfEuA;0KY#SJKPrr_Bu`mlRGy4rF}| z&d+!+ez0+0P|wHf$KBHvNF->(t9@IMROu$4FOcX%aOsCO<6N_T3-DLw%fZ3j-Q7}g z_vbI}QUU(YJK`s}Hz|QqpTxOLg-%^xwGN@6`QWY-w|H0m@Jc|_yCJx-eOntw7(j^Q z#y{MWxbVE0PJJPAo390em-hwl`$-7@$`b^N+cxS<4r41GqYfRR(F3W3n(#{vE}O=k zaF`MKW!pn+b&#z%Sf8RaRd)4mkT}vRgc5TP9as$ZE~K-)15HF4?44-z4#urA1-Jjk2o>6ROvt9Q+A{{PJMygl&`rq=99nFRHCrXkE1S>? zGhEU2gRCce^na5GuovE?Isfv_7~0cG2SNSU#9!C!Xs!eBr#uMIIM)uavX5XTA!V#9 za9nuWv}{@`whS747umUH?E}P-2G7mqi!i5GLy^?Bosf#0x4Bp&O^Mvi2!nF-Eng!> z@<^{pO<&NSysSQPkaOp%^+lLjncckLldsNaQ1ap8SM)7G@Bsoq`p=8aRPMPSil7zD z2EeMhyg;~hH-Zbn_a@pw=k}B{QJ!obL(=V2Y}EcQ#(&U9o}wunGI0~Dqm zUeydx(cfv}sm6LF3G6qOM!etX=M~N~4lHgv3VF&G&u#Za2=W>?n=oJWwx(GlNBkO`TWZXcsh)?fV>#^_Ga>)&kDno6oT&OB;@e z@Qru*&C)IY^ZUE4$o`S@h|u%#sIke1b=K!L0-G=s*dlM+lbmGQJl_BE}#nsFs(sFpJflI<^}E9MOnA6ZZ=v{;EXw$#J8F7=v?Ql z0R^3vNHxtqs8}#%@U8*ZSkOfzNn&=rR^X;-AL~z&Y_> ziQXtFNtmS8d!YhH-=B&9P?bk`hed03P4NJX@jK7i?RxJR2TvXQn*7{HaB%}kS4(|j zn0{$*tWuO5H!G{dkS#S3z2aMjBI}1J~n9WhA&&fbh~~82%f(`579wa za2i?8#TKUE=f{m1|BN185|7T#&Wx)|Gj1_}4IQ0Y>szOz@%^&(ffLOU34j7??~(f+upac?rII4mQujtlrf{uS8oVNP4h z)xvE7F=GDXcN1^0tfc=?q+d&KccAsmu|N!HnzT(C1h73kDH(DH#dG?;_5W%ENB0_! zg3r>CZKBWrkdencJ;Izg4QegNh`j7V%t_694!c%&-%*Nk4qA5K|kifTx+$mNE5sPMiIlEAnnzw zD(>@B-xF(x43Ni4){F%jw-tVWmi>^cEUEkPlSUed!NA2#0V6Q^a~f8M*^#Bu4rTg4 zex85WcyBOG3SRy|Faf{cN>cmv)ZNRo9Ac9!yk4}Q{YicYbpKuY*3Ozc`>oHXpG-als^@uC2Wk08sfL5 zN0|(x(Eb2!G^wF!2^ROn!@v_k&@o2es*vhZMW&!lvzU)GK3o3gJ^@lQc6ZBnC(0yR zYS%xDXEHjRIONOgX9cx}C$%cos%0u>)ZU)a_ZFt~h7X(@=>{L=`*)qdV4eV}Wk4@zdN$_b6SB4h+qMhX(xK)n zH{~m$aX#mdi=A)W5a`yi6!g+?tj$V!7v%5z{5TVL06Pk1GUyAygdj6DWe2BBe6EV9W=x zPoq+>b&=QtRI2-VyLJujyEJ6$3+lN)$NWs~_}lN2G@cs-7w z_%mk7A2C?|1<*qgndBFCbK1A}^&&7YES9HvmYfHb;SQ?9x{=8%rVJ`^Onx1o_5fH? z9-RI3s8xf^CjesZp5Hg-g0u3Zo^;l9q@F%KD)JTPPR{sh!*HYXSG3<0*nP*>El~a! zKDTugF8%Qr&R#6@wlDqpvr`_P32^~`$PTQ4A8(?Oq_oo+UEs|&pBG^bWcQ$%{%eb) zQ2jCCZLC~t6N2*AmR}~U8N6sue(MN_2@KAY^`GV`W4+laGce)zPu!tT(!RigouC)M z5D8cIdVA<`P}0fJOCRg4kJ`b@08a7C=UwhE0<8NAcF|@b9gs^%C{G9ESpUN0_TA0i z70%7jnKh^vvW?Z_SR~fg>CA`+nUm+H(r0c_zs6FO>bsFS$#mbArv+uvc+_DA{#0PA zZZj`CmJr1_{$q{-p;2i3$RAa`6=N(JAoT2SxvbIPi=Ep1nSChTo8u7JWxsG?8py7{;qLWOuJC8SvHcl7PeTZGMUXGYV4`fN%%6yqj7B#IahuCb>S*%Ms?!JcaE)yrxaDw81D- zVKo*ylPIJ=S6Bf{ylEGqubQhUNAtw^=+E?$FQ6Z7+s`x?7*&>I5pki=S|~NL(!BtI z+g6!H{n{79Z)PC)w9;vkmxs%O4cfcKun1N=#}2p#EP$$-ck7XA!A3OF+w|job%(xN zYfW_x#uKS)1*x3}`DOWb_TkcNI|TLz&%^A*PllJz<8lB?JZ<(F$sr+(Y5nk+5p4Br!5ON%0(vn?X|D;KG7dlG>e5{Q@+Z?DtHReZu8 z^_;~&I$=ozYB{Y1ygSOfMbqE@ahyBH;3I>RZlYHr>?5{2#C)PGcEwDR$w zDHKOX+7*C*oUXip7fdCXTmZyz6J zBtZ!W)PpSEZ$IXY&RRm!ci}e?wGC}@^Gs}x9`LXF_Za41R5I?Ac=Pmod;0X{A@o#OdU&Qbk^+9YwkXkA4wo?@oJ81?SE^&yrMZim%6*vy7-QgmPY#q^Va>4XyEmC`o z2D7Lcmd%YzhwL%SNi?B(bFV6I_m!qw&|vLBpZ#9I&Vg|4xC8E63l*!1y>4hi+Xjib z%c>pWn8tFR%@L`G7xN|;hDuOseUC=eQC@fPz&nxD7*ihW=I4P@tIni~7XuRP*dT{wRfwOn~BD14n#zftlxTtg;s zE~Xu!KW$_t+op(aNx$2+7!~@Qz)SCNU`0qX<;&9RvCm2CfX}RCe_{f0c(J2c;S!bd zn+##CA`iY?IFojG9b)`)6Xqdx@S2kJvQ4C;#W;ohXC8Y9a5SoDHRZ;>*G}h$r1eT- zCZjQ2clhQ&36smLj*vjWBdy=&7)n&SyVj8Y6D)2IjFO57?AD5B{DGZ_@Jgy5Bx-@} zl%|eu*1oT(Hk0+WtZFs{M6&_3XNc8=gaQ8;wW9(V^u@z9rY@vO{FnH4FMx+FFI2!ZWotmAW&pjwApv@tm^SIE3N)PVpw59gor`d=#Z3P z+Od->h#4Yymm^3ub5!;D*%gWNB&9YoSi*U;oi^wiz1tWV6#pWI&s|2B03FI()Z~Uw zlt7?5cbyRk3=LS9bRu0-J+nUL)mXVdJZ1`zCVL6qg3fQT?4|H$`SpS8{&ab#hk~S)UYbThFBrw2!zUqp~%eQFl{?IDM4b3+` zdaDNq02$8OcS(TYTjE|)V(Vd%NB|N&(k}2v!_=z_2inhscBCPaqgK*wP_*CI>fO6n zx;CH~IDfckL$wR~IuFt>6F{OMcyBC_5_x8t*@|p(FJ75vmaiACNk%)cAG8NdSRtd% zaFLOrUqi{b1ioos$y+QIq5ln=FVNAmhvJKi5PWb}iu!_F`-s|f{1f5bp`Es^Qagg( zPm3Oz(;YCQTM@%x^NrbruQ8@-YdTMksU4+Ht>{jtJnn&^Xt{!|APsfK4+!~}f+VJN znkj!{LTNiEmi|?~*00h;>Q9L;n2wp^fRu4kz9FG!)@QKJ$R4hy21N3mjpe@S3UL1L z`T217R8Q;u$pWm;ihuEa4P0QDdG2GlRkkS??8{Wc!3nXHF+OW@;d#|4iMO2iSyQE^ z2lW^L+11?Rkr2SKaOE|ny-MG-j>#p&@8GsQa*$?;iq;F&EKqFh0yT%+pCEAiHK&pW zt7<1K)h(GcXr^!R?+`X<^v&p`Gd5^=uTr&{*z@Nph&Sn1b;eh=7l0ipWxSjOVOEErrgjTB#Vz#FBswadX}BP*h9SNGF2X~fTN2|%&F^v zgz&_;X%gf0qY_QTFQW@|U1KT-)2`u{`CUE%*pHK4*mpLZAuneh>jD2)xV>uA%1lzK1_`8suYzNt zq7f#wT!b|X-ye!9v|VVp>ij&DxYWzKr6S-r70w2&m{ti-xJ-l<4m7d9262Dqy))&?y(axRsLmjS~ zYRG;Ye)$L@e=K}3hkmx)8w1au^@xCa0-wehK;4_L&Kx!1&)Hg1t-q31VW!y!w?kJ! z5mwVFFr+r0I;g8t9>*P(i;*$u1pzncU+yY|x-<`^@#zBsyf0IYDXWa-I$%!!&XPu| zVk1vL=Y`Tr*QU!-9KFD8xe@MiVnB3{oFA_C`F-&=)Tu+fCz^#KXHc%|(1xpwVxkQt z)*%i^7Pa%Q89UvSU=PN^f}L8&_?5l1krR*IN}xPr4|GZ*tVtN^xDbtCZW=#wL4{f! zxn1#jSQIw-atDDv`n{mB~ zTjjc|DkD=(vE}f<9}Xl!>{hWW9q5^w|M5URyfh7hN&rW#Ci%Zznc+~Ld;O$N6b7xG z_@X05*eppoN-?W1FcSL=P@oBZ0?PHxj2CH4L@=$Noax{s`w&2LTXDiZ7%1{`wE_Gu zP`nG*jmXngR|`IH7hfUQd-|3h@$bE?dIvvr`!}3jEfGaM2~9c?Dz(Jnz&NM@uL9xw zQ0S<144HUTjSLh|+=GY2YRqI3(X0KwV&3!fjHd_^a56Fv+duAk`EwaG@Q7;nzH}wl z5m0WGJdbw86Mi0T8#T9-t%`+Ljb|= zre!b(s|PHlJr3Rhel)-D5`jTlrTINLyfx+mlHbKJG25<$^D#1~L7xGE{_MF)(vjAk z>VLgq{t9gex~wC=zAm}CI?;3JxIOHrW4L;iE6Nc%wH1F7sZZY?p2 zii*jIl9#!j9%Div#Fs{SX*a;>kZX2?yN~dH3omRmhZ~=th;uib`BaX52#~UrjbOo* zDJg>UsHv*pxR%+z2ciWaXKa!9yi_nKAlmqB#pjQMdt2F( z!wZr0cT`ZeBi}K8RyPI@)A+d<o+w#kz)zL z&c!{2>@w-nf$0H#K73lG2oa{|><-y{P_R<8S7f6Z!SBPkd6?eV4`FfBtbTM+PuCjL z0`7w6cOl=`Ep9ARWGd%|F$3Axf3Fo~Qb0X$@7bv2<1qR{`X2A*NAE)Is_VYTNp8&O zg&L9~ft6~KC4Gomd||}f8i1g@*U!!bs$SADFy>4DC77j#^rO!Dr{JL_HM6Qt=}IWg z*sXe%-r7$h&#@!Ij>o=}&zV=lzHeDwE2&?~>e0b}HGi*u3CLE?aAf(=O|G&RFO#GeZ@*%AveE+wf@8hb4wW`-$Y zZ@+?Uoe-WgF-Es04S{G#j=D^Rz6_~qu(#wJg_s3Z$WDqZdfp8L+4z3Qr-lTPysxok zAs`%?DD=PgWrC5Uum>&!eAD87`S;m<$oFDy>=I3>>d7+vh@YD(UuDp^uJj-)ei~N` z6sg%c)SSLIyREa!5CP_qQ*_Uf2iO3pWUUYHRB5+t3koq!25ud;@) z`33KBH?uq-(?H4{#sgY?AN53Z4F(BS*1F*u4|qp=PIoFuPtu4U5mLZL{wNyJD%b&B zA-X)gQ;(tnYhJr`3P7)2Z%2Oy1sldEiNu0+vs$ez%vyfSF7;L)zTfNxqhZLf2V%|& zk|jS}acSD=6K5wPn3|+@ji0DAK zmUM%3kiSzfrW|%+rCaWPI+~v6F z*kF^$^iyJMJ0dL1^+v~x{@2+>?U4NR&?1910~hx$7kmk=FzgorM41~8w*kEx!TPBOF@vW=NQ@ z`F}TK*yg(5}dGhSC+H8v$XQ0u|{pwJ; z&#De_L!x`4^&(??BOHa-XJ9dE!|Ri=rpMB&_LxbX+FVcg>e#5nW_rb>n*&5s;Hco!)9XjV zb)FxgJ?+uA@SK@YJ$Sa0ztoj(ipY!PL-jl5%T><5o9cIFM=FOE+i$)NQC^+pN&0#>1Vi%xVZ)*X|K4t_fc}U z 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 diff --git a/examples/example 16 - Displacement/panda.png b/examples/example 16 - Displacement/panda.png deleted file mode 100644 index 215a4a9331fbe6bb3efe9501b672df8e5d8be76e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69177 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 Date: Sun, 3 Nov 2013 10:46:41 +0000 Subject: [PATCH 65/96] WebGL masking issue fixed WebGL mask objects can now be nested within masked objects --- bin/pixi.dev.js | 49 +++++-- bin/pixi.dev.js.map | 2 +- bin/pixi.js | 8 +- .../index double mask.html | 16 +- .../index nested masks.html | 138 ++++++++++++++++++ examples/example 14 - Masking/index.html | 5 +- examples/example 15 - Filters/indexAll.html | 2 +- src/pixi/renderers/webgl/WebGLGraphics.js | 1 + src/pixi/renderers/webgl/WebGLRenderGroup.js | 48 ++++-- 9 files changed, 233 insertions(+), 36 deletions(-) create mode 100644 examples/example 14 - Masking/index nested masks.html diff --git a/bin/pixi.dev.js b/bin/pixi.dev.js index c51a9d0..3f77ac4 100644 --- a/bin/pixi.dev.js +++ b/bin/pixi.dev.js @@ -4114,6 +4114,7 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) PIXI.deactivatePrimitiveShader(); + // return to default shader... // PIXI.activateShader(PIXI.defaultShader); } @@ -5774,6 +5775,12 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) } } +flip = false; +var maskStack = []; +var maskPosition = 0; + +//var usedMaskStack = []; + PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(filterBlock, projection) { /* @@ -5785,24 +5792,27 @@ PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(filterBlock, projec { if(filterBlock.data instanceof Array) { - //var filter = filterBlock.data[0]; - //console.log(filter) - this.filterManager.pushFilter(filterBlock);//filter); + this.filterManager.pushFilter(filterBlock); // ok so.. } else - { - + { + maskPosition++; + + maskStack.push(filterBlock) + gl.enable(gl.STENCIL_TEST); - + gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); + + gl.stencilFunc(gl.ALWAYS,1,1); + gl.stencilOp(gl.KEEP,gl.KEEP,gl.INCR); + PIXI.WebGLGraphics.renderGraphics(filterBlock.data, projection); - + gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); + gl.stencilFunc(gl.NOTEQUAL,0,maskStack.length); gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); } } @@ -5811,11 +5821,26 @@ PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(filterBlock, projec if(filterBlock.data instanceof Array) { this.filterManager.popFilter(); - // PIXI.popShader(); - // gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); } else { + var maskData = maskStack.pop(filterBlock) + + + if(maskData) + { + gl.colorMask(false, false, false, false); + + gl.stencilFunc(gl.ALWAYS,1,1); + gl.stencilOp(gl.KEEP,gl.KEEP,gl.DECR); + + PIXI.WebGLGraphics.renderGraphics(maskData.data, projection); + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.NOTEQUAL,0,maskStack.length); + gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); + }; + gl.disable(gl.STENCIL_TEST); } } diff --git a/bin/pixi.dev.js.map b/bin/pixi.dev.js.map index 9c4ccbc..9eb4a5a 100644 --- a/bin/pixi.dev.js.map +++ b/bin/pixi.dev.js.map @@ -65,6 +65,6 @@ "src/pixi/Outro.js" ], "names": [], - "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sB;AC5jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACngBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5+BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACpgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACn7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACpKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,c", + "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sB;AC5jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpgCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACpgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACn7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACpKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,c", "sourceRoot": "../" } \ No newline at end of file diff --git a/bin/pixi.js b/bin/pixi.js index 46d5683..de93a8f 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -4,13 +4,13 @@ * Copyright (c) 2012, Mat Groves * http://goodboydigital.com/ * - * Compiled: 2013-11-02 + * Compiled: 2013-11-03 * * Pixi.JS is licensed under the MIT License. * http://www.opensource.org/licenses/mit-license.php */ !function(){function c(){return f.Matrix="undefined"!=typeof Float32Array?Float32Array:Array,f.Matrix}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}var e=this,f=f||{};f.Point=function(a,b){this.x=a||0,this.y=b||0},f.Point.prototype.clone=function(){return new f.Point(this.x,this.y)},f.Point.prototype.constructor=f.Point,f.Rectangle=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Rectangle.prototype.clone=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Rectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},f.Rectangle.prototype.constructor=f.Rectangle,f.Polygon=function(a){if(a instanceof Array||(a=Array.prototype.slice.call(arguments)),"number"==typeof a[0]){for(var b=[],c=0,d=a.length;d>c;c+=2)b.push(new f.Point(a[c],a[c+1]));a=b}this.points=a},f.Polygon.prototype.clone=function(){for(var a=[],b=0;bb!=i>b&&(h-f)*(b-g)/(i-g)+f>a;j&&(c=!c)}return c},f.Polygon.prototype.constructor=f.Polygon,f.Circle=function(a,b,c){this.x=a||0,this.y=b||0,this.radius=c||0},f.Circle.prototype.clone=function(){return new f.Circle(this.x,this.y,this.radius)},f.Circle.prototype.contains=function(a,b){if(this.radius<=0)return!1;var c=this.x-a,d=this.y-b,e=this.radius*this.radius;return c*=c,d*=d,e>=c+d},f.Circle.prototype.constructor=f.Circle,f.Ellipse=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Ellipse.prototype.clone=function(){return new f.Ellipse(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=(a-this.x)/this.width-.5,d=(b-this.y)/this.height-.5;return c*=c,d*=d,.25>c+d},f.Ellipse.getBounds=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.constructor=f.Ellipse,c(),f.mat3={},f.mat3.create=function(){var a=new f.Matrix(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat3.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat4={},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat3.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=b[0],n=b[1],o=b[2],p=b[3],q=b[4],r=b[5],s=b[6],t=b[7],u=b[8];return c[0]=m*d+n*g+o*j,c[1]=m*e+n*h+o*k,c[2]=m*f+n*i+o*l,c[3]=p*d+q*g+r*j,c[4]=p*e+q*h+r*k,c[5]=p*f+q*i+r*l,c[6]=s*d+t*g+u*j,c[7]=s*e+t*h+u*k,c[8]=s*f+t*i+u*l,c},f.mat3.clone=function(a){var b=new f.Matrix(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},f.mat3.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[5];return a[1]=a[3],a[2]=a[6],a[3]=c,a[5]=a[7],a[6]=d,a[7]=e,a}return b[0]=a[0],b[1]=a[3],b[2]=a[6],b[3]=a[1],b[4]=a[4],b[5]=a[7],b[6]=a[2],b[7]=a[5],b[8]=a[8],b},f.mat3.toMat4=function(a,b){return b||(b=f.mat4.create()),b[15]=1,b[14]=0,b[13]=0,b[12]=0,b[11]=0,b[10]=a[8],b[9]=a[7],b[8]=a[6],b[7]=0,b[6]=a[5],b[5]=a[4],b[4]=a[3],b[3]=0,b[2]=a[2],b[1]=a[1],b[0]=a[0],b},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat4.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[3],f=a[6],g=a[7],h=a[11];return a[1]=a[4],a[2]=a[8],a[3]=a[12],a[4]=c,a[6]=a[9],a[7]=a[13],a[8]=d,a[9]=f,a[11]=a[14],a[12]=e,a[13]=g,a[14]=h,a}return b[0]=a[0],b[1]=a[4],b[2]=a[8],b[3]=a[12],b[4]=a[1],b[5]=a[5],b[6]=a[9],b[7]=a[13],b[8]=a[2],b[9]=a[6],b[10]=a[10],b[11]=a[14],b[12]=a[3],b[13]=a[7],b[14]=a[11],b[15]=a[15],b},f.mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=b[0],u=b[1],v=b[2],w=b[3];return c[0]=t*d+u*h+v*l+w*p,c[1]=t*e+u*i+v*m+w*q,c[2]=t*f+u*j+v*n+w*r,c[3]=t*g+u*k+v*o+w*s,t=b[4],u=b[5],v=b[6],w=b[7],c[4]=t*d+u*h+v*l+w*p,c[5]=t*e+u*i+v*m+w*q,c[6]=t*f+u*j+v*n+w*r,c[7]=t*g+u*k+v*o+w*s,t=b[8],u=b[9],v=b[10],w=b[11],c[8]=t*d+u*h+v*l+w*p,c[9]=t*e+u*i+v*m+w*q,c[10]=t*f+u*j+v*n+w*r,c[11]=t*g+u*k+v*o+w*s,t=b[12],u=b[13],v=b[14],w=b[15],c[12]=t*d+u*h+v*l+w*p,c[13]=t*e+u*i+v*m+w*q,c[14]=t*f+u*j+v*n+w*r,c[15]=t*g+u*k+v*o+w*s,c},f.DisplayObject=function(){this.last=this,this.first=this,this.position=new f.Point,this.scale=new f.Point(1,1),this.pivot=new f.Point(0,0),this.rotation=0,this.alpha=1,this.visible=!0,this.hitArea=null,this.buttonMode=!1,this.renderable=!1,this.parent=null,this.stage=null,this.worldAlpha=1,this._interactive=!1,this.worldTransform=f.mat3.create(),this.localTransform=f.mat3.create(),this.color=[],this.dynamic=!0,this._sr=0,this._cr=1,this.filterArea=new f.Rectangle(0,0,1,1)},f.DisplayObject.prototype.constructor=f.DisplayObject,f.DisplayObject.prototype.setInteractive=function(a){this.interactive=a},Object.defineProperty(f.DisplayObject.prototype,"interactive",{get:function(){return this._interactive},set:function(a){this._interactive=a,this.stage&&(this.stage.dirty=!0)}}),Object.defineProperty(f.DisplayObject.prototype,"mask",{get:function(){return this._mask},set:function(a){a?this._mask?(a.start=this._mask.start,a.end=this._mask.end):(this.addFilter(a),a.renderable=!1):(this.removeFilter(this._mask),this._mask.renderable=!0),this._mask=a}}),Object.defineProperty(f.DisplayObject.prototype,"filters",{get:function(){return this._filters},set:function(a){if(a){this._filters&&this.removeFilter(this._filters),this.addFilter(a);for(var b=[],c=0;c=0&&b<=this.children.length))throw new Error(a+" The index "+b+" supplied is out of bounds "+this.children.length);if(void 0!=a.parent&&a.parent.removeChild(a),a.parent=this,this.stage){var c=a;do c.interactive&&(this.stage.dirty=!0),c.stage=this.stage,c=c._iNext;while(c)}var d,e,f=a.first,g=a.last;if(b==this.children.length){e=this.last;for(var h=this,i=this.last;h;)h.last==i&&(h.last=a.last),h=h.parent}else e=0==b?this:this.children[b-1].last;d=e._iNext,d&&(d._iPrev=g,g._iNext=d),f._iPrev=e,e._iNext=f,this.children.splice(b,0,a),this.__renderGroup&&(a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a),this.__renderGroup.addDisplayObjectAndChildren(a))},f.DisplayObjectContainer.prototype.swapChildren=function(){},f.DisplayObjectContainer.prototype.getChildAt=function(a){if(a>=0&&aa;a++)this.children[a].updateTransform()}},f.blendModes={},f.blendModes.NORMAL=0,f.blendModes.SCREEN=1,f.Sprite=function(a){f.DisplayObjectContainer.call(this),this.anchor=new f.Point,this.texture=a,this.blendMode=f.blendModes.NORMAL,this._width=0,this._height=0,a.baseTexture.hasLoaded?this.updateFrame=!0:(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Sprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Sprite.prototype.constructor=f.Sprite,Object.defineProperty(f.Sprite.prototype,"width",{get:function(){return this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(f.Sprite.prototype,"height",{get:function(){return this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),f.Sprite.prototype.setTexture=function(a){this.texture.baseTexture!=a.baseTexture?(this.textureChange=!0,this.texture=a,this.__renderGroup&&this.__renderGroup.updateTexture(this)):this.texture=a,this.updateFrame=!0},f.Sprite.prototype.onTextureUpdate=function(){this._width&&(this.scale.x=this._width/this.texture.frame.width),this._height&&(this.scale.y=this._height/this.texture.frame.height),this.updateFrame=!0},f.Sprite.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache"+this);return new f.Sprite(b)},f.Sprite.fromImage=function(a){var b=f.Texture.fromImage(a);return new f.Sprite(b)},f.MovieClip=function(a){f.Sprite.call(this,a[0]),this.textures=a,this.animationSpeed=1,this.loop=!0,this.onComplete=null,this.currentFrame=0,this.playing=!1},f.MovieClip.prototype=Object.create(f.Sprite.prototype),f.MovieClip.prototype.constructor=f.MovieClip,Object.defineProperty(f.MovieClip.prototype,"totalFrames",{get:function(){return this.textures.length}}),f.MovieClip.prototype.stop=function(){this.playing=!1},f.MovieClip.prototype.play=function(){this.playing=!0},f.MovieClip.prototype.gotoAndStop=function(a){this.playing=!1,this.currentFrame=a;var b=0|this.currentFrame+.5;this.setTexture(this.textures[b%this.textures.length])},f.MovieClip.prototype.gotoAndPlay=function(a){this.currentFrame=a,this.playing=!0},f.MovieClip.prototype.updateTransform=function(){if(f.Sprite.prototype.updateTransform.call(this),this.playing){this.currentFrame+=this.animationSpeed;var a=0|this.currentFrame+.5;this.loop||a=this.textures.length&&(this.gotoAndStop(this.textures.length-1),this.onComplete&&this.onComplete())}},f.FilterBlock=function(){this.visible=!0,this.renderable=!0},f.Text=function(a,b){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),f.Sprite.call(this,f.Texture.fromCanvas(this.canvas)),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.Text.prototype=Object.create(f.Sprite.prototype),f.Text.prototype.constructor=f.Text,f.Text.prototype.setStyle=function(a){a=a||{},a.font=a.font||"bold 20pt Arial",a.fill=a.fill||"black",a.align=a.align||"left",a.stroke=a.stroke||"black",a.strokeThickness=a.strokeThickness||0,a.wordWrap=a.wordWrap||!1,a.wordWrapWidth=a.wordWrapWidth||100,this.style=a,this.dirty=!0},f.Text.prototype.setText=function(a){this.text=a.toString()||" ",this.dirty=!0},f.Text.prototype.updateText=function(){this.context.font=this.style.font;var a=this.text;this.style.wordWrap&&(a=this.wordWrap(this.text));for(var b=a.split(/(?:\r\n|\r|\n)/),c=[],d=0,e=0;ee?f:arguments.callee(a,b,f,d,e):arguments.callee(a,b,c,f,e)},c=function(a,c,d){if(a.measureText(c).width<=d||c.length<1)return c;var e=b(a,c,0,c.length,d);return c.substring(0,e)+"\n"+arguments.callee(a,c.substring(e),d)},d="",e=a.split("\n"),f=0;f=2?parseInt(b[b.length-2],10):f.BitmapText.fonts[this.fontName].size,this.dirty=!0},f.BitmapText.prototype.updateText=function(){for(var a=f.BitmapText.fonts[this.fontName],b=new f.Point,c=null,d=[],e=0,g=[],h=0,i=this.fontSize/a.size,j=0;j=j;j++){var n=0;"right"==this.style.align?n=e-g[j]:"center"==this.style.align&&(n=(e-g[j])/2),m.push(n)}for(j=0;j0;)this.removeChild(this.getChildAt(0));this.updateText(),this.dirty=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.BitmapText.fonts={},f.InteractionManager=function(a){this.stage=a,this.mouse=new f.InteractionData,this.touchs={},this.tempPoint=new f.Point,this.mouseoverEnabled=!0,this.pool=[],this.interactiveItems=[],this.interactionDOMElement=null,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseOut=this.onMouseOut.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.last=0},f.InteractionManager.prototype.constructor=f.InteractionManager,f.InteractionManager.prototype.collectInteractiveSprite=function(a,b){for(var c=a.children,d=c.length,e=d-1;e>=0;e--){var f=c[e];f.interactive?(b.interactiveChildren=!0,this.interactiveItems.push(f),f.children.length>0&&this.collectInteractiveSprite(f,f)):(f.__iParent=null,f.children.length>0&&this.collectInteractiveSprite(f,b))}},f.InteractionManager.prototype.setTarget=function(a){this.target=a,null===this.interactionDOMElement&&this.setTargetDomElement(a.view),document.body.addEventListener("mouseup",this.onMouseUp,!0)},f.InteractionManager.prototype.setTargetDomElement=function(a){null!==this.interactionDOMElement&&(this.interactionDOMElement.style["-ms-content-zooming"]="",this.interactionDOMElement.style["-ms-touch-action"]="",this.interactionDOMElement.removeEventListener("mousemove",this.onMouseMove,!0),this.interactionDOMElement.removeEventListener("mousedown",this.onMouseDown,!0),this.interactionDOMElement.removeEventListener("mouseout",this.onMouseOut,!0),this.interactionDOMElement.removeEventListener("touchstart",this.onTouchStart,!0),this.interactionDOMElement.removeEventListener("touchend",this.onTouchEnd,!0),this.interactionDOMElement.removeEventListener("touchmove",this.onTouchMove,!0)),window.navigator.msPointerEnabled&&(a.style["-ms-content-zooming"]="none",a.style["-ms-touch-action"]="none"),this.interactionDOMElement=a,a.addEventListener("mousemove",this.onMouseMove,!0),a.addEventListener("mousedown",this.onMouseDown,!0),a.addEventListener("mouseout",this.onMouseOut,!0),a.addEventListener("touchstart",this.onTouchStart,!0),a.addEventListener("touchend",this.onTouchEnd,!0),a.addEventListener("touchmove",this.onTouchMove,!0)},f.InteractionManager.prototype.update=function(){if(this.target){var a=Date.now(),b=a-this.last;if(b=30*b/1e3,!(1>b)){if(this.last=a,this.dirty){this.dirty=!1;for(var c=this.interactiveItems.length,d=0;c>d;d++)this.interactiveItems[d].interactiveChildren=!1;this.interactiveItems=[],this.stage.interactive&&this.interactiveItems.push(this.stage),this.collectInteractiveSprite(this.stage,this.stage)}var e=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var d=0;e>d;d++){var f=this.interactiveItems[d];(f.mouseover||f.mouseout||f.buttonMode)&&(f.__hit=this.hitTest(f,this.mouse),this.mouse.target=f,f.__hit?(f.buttonMode&&(this.interactionDOMElement.style.cursor="pointer"),f.__isOver||(f.mouseover&&f.mouseover(this.mouse),f.__isOver=!0)):f.__isOver&&(f.mouseout&&f.mouseout(this.mouse),f.__isOver=!1))}}}},f.InteractionManager.prototype.onMouseMove=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactionDOMElement.getBoundingClientRect();this.mouse.global.x=(a.clientX-b.left)*(this.target.width/b.width),this.mouse.global.y=(a.clientY-b.top)*(this.target.height/b.height);var c=this.interactiveItems.length;this.mouse.global;for(var d=0;c>d;d++){var e=this.interactiveItems[d];e.mousemove&&e.mousemove(this.mouse)}},f.InteractionManager.prototype.onMouseDown=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactiveItems.length;this.mouse.global,this.stage;for(var c=0;b>c;c++){var d=this.interactiveItems[c];if((d.mousedown||d.click)&&(d.__mouseIsDown=!0,d.__hit=this.hitTest(d,this.mouse),d.__hit&&(d.mousedown&&d.mousedown(this.mouse),d.__isDown=!0,!d.interactiveChildren)))break}},f.InteractionManager.prototype.onMouseOut=function(){var a=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var b=0;a>b;b++){var c=this.interactiveItems[b];c.__isOver&&(this.mouse.target=c,c.mouseout&&c.mouseout(this.mouse),c.__isOver=!1)}},f.InteractionManager.prototype.onMouseUp=function(a){this.mouse.originalEvent=a||window.event,this.mouse.global;for(var b=this.interactiveItems.length,c=!1,d=0;b>d;d++){var e=this.interactiveItems[d];(e.mouseup||e.mouseupoutside||e.click)&&(e.__hit=this.hitTest(e,this.mouse),e.__hit&&!c?(e.mouseup&&e.mouseup(this.mouse),e.__isDown&&e.click&&e.click(this.mouse),e.interactiveChildren||(c=!0)):e.__isDown&&e.mouseupoutside&&e.mouseupoutside(this.mouse),e.__isDown=!1)}},f.InteractionManager.prototype.hitTest=function(a,b){var c=b.global;if(a.vcount!==f.visibleCount)return!1;var d=a instanceof f.Sprite,e=a.worldTransform,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=1/(g*k+h*-j),n=k*m*c.x+-h*m*c.y+(l*h-i*k)*m,o=g*m*c.y+-j*m*c.x+(-l*g+i*j)*m;if(b.target=a,a.hitArea&&a.hitArea.contains)return a.hitArea.contains(n,o)?(b.target=a,!0):!1;if(d){var p,q=a.texture.frame.width,r=a.texture.frame.height,s=-q*a.anchor.x;if(n>s&&s+q>n&&(p=-r*a.anchor.y,o>p&&p+r>o))return b.target=a,!0}for(var t=a.children.length,u=0;t>u;u++){var v=a.children[u],w=this.hitTest(v,b);if(w)return b.target=a,!0}return!1},f.InteractionManager.prototype.onTouchMove=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;dd;d++){var h=this.interactiveItems[d];h.touchmove&&h.touchmove(f)}},f.InteractionManager.prototype.onTouchStart=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i];if((j.touchstart||j.tap)&&(j.__hit=this.hitTest(j,g),j.__hit&&(j.touchstart&&j.touchstart(g),j.__isDown=!0,j.__touchData=g,!j.interactiveChildren)))break}}},f.InteractionManager.prototype.onTouchEnd=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i],k=j.__touchData;j.__hit=this.hitTest(j,f),k==f&&(f.originalEvent=a||window.event,(j.touchend||j.tap)&&(j.__hit&&!g?(j.touchend&&j.touchend(f),j.__isDown&&j.tap&&j.tap(f),j.interactiveChildren||(g=!0)):j.__isDown&&j.touchendoutside&&j.touchendoutside(f),j.__isDown=!1),j.__touchData=null)}this.pool.push(f),this.touchs[e.identifier]=null}},f.InteractionData=function(){this.global=new f.Point,this.local=new f.Point,this.target,this.originalEvent},f.InteractionData.prototype.getLocalPosition=function(a){var b=a.worldTransform,c=this.global,d=b[0],e=b[1],g=b[2],h=b[3],i=b[4],j=b[5],k=1/(d*i+e*-h);return new f.Point(i*k*c.x+-e*k*c.y+(j*e-g*i)*k,d*k*c.y+-h*k*c.x+(-j*d+g*h)*k)},f.InteractionData.prototype.constructor=f.InteractionData,f.Stage=function(a){f.DisplayObjectContainer.call(this),this.worldTransform=f.mat3.create(),this.interactive=!0,this.interactionManager=new f.InteractionManager(this),this.dirty=!0,this.__childrenAdded=[],this.__childrenRemoved=[],this.stage=this,this.stage.hitArea=new f.Rectangle(0,0,1e5,1e5),this.setBackgroundColor(a),this.worldVisible=!0},f.Stage.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Stage.prototype.constructor=f.Stage,f.Stage.prototype.setInteractionDelegate=function(a){this.interactionManager.setTargetDomElement(a)},f.Stage.prototype.updateTransform=function(){this.worldAlpha=1,this.vcount=f.visibleCount;for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform();this.dirty&&(this.dirty=!1,this.interactionManager.dirty=!0),this.interactive&&this.interactionManager.update()},f.Stage.prototype.setBackgroundColor=function(a){this.backgroundColor=a||0,this.backgroundColorSplit=d(this.backgroundColor);var b=this.backgroundColor.toString(16);b="000000".substr(0,6-b.length)+b,this.backgroundColorString="#"+b},f.Stage.prototype.getMousePosition=function(){return this.interactionManager.mouse.global};for(var h=0,i=["ms","moz","webkit","o"],j=0;j>>>>>>>>"),console.log("_");var b=0,c=a.first;for(console.log(c);c._iNext;)if(b++,c=c._iNext,console.log(c),b>100){console.log("BREAK");break}},f.EventTarget=function(){var a={};this.addEventListener=this.on=function(b,c){void 0===a[b]&&(a[b]=[]),-1===a[b].indexOf(c)&&a[b].push(c)},this.dispatchEvent=this.emit=function(b){if(a[b.type]&&a[b.type].length)for(var c=0,d=a[b.type].length;d>c;c++)a[b.type][c](b)},this.removeEventListener=this.off=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)}},f.autoDetectRenderer=function(a,b,c,d,e){a||(a=800),b||(b=600);var g=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}();if(g){var h=-1!=navigator.userAgent.toLowerCase().indexOf("msie");g=!h}return g?new f.WebGLRenderer(a,b,c,d,e):new f.CanvasRenderer(a,b,c,d)},f.PolyK={},f.PolyK.Triangulate=function(a){var b=!0,c=a.length>>1;if(3>c)return[];for(var d=[],e=[],g=0;c>g;g++)e.push(g);for(var g=0,h=c;h>3;){var i=e[(g+0)%h],j=e[(g+1)%h],k=e[(g+2)%h],l=a[2*i],m=a[2*i+1],n=a[2*j],o=a[2*j+1],p=a[2*k],q=a[2*k+1],r=!1;if(f.PolyK._convex(l,m,n,o,p,q,b)){r=!0;for(var s=0;h>s;s++){var t=e[s];if(t!=i&&t!=j&&t!=k&&f.PolyK._PointInTriangle(a[2*t],a[2*t+1],l,m,n,o,p,q)){r=!1;break}}}if(r)d.push(i,j,k),e.splice((g+1)%h,1),h--,g=0;else if(g++>3*h){if(!b)return console.log("PIXI Warning: shape too complex to fill"),[];var d=[];e=[];for(var g=0;c>g;g++)e.push(g);g=0,h=c,b=!1}}return d.push(e[0],e[1],e[2]),d},f.PolyK._PointInTriangle=function(a,b,c,d,e,f,g,h){var i=g-c,j=h-d,k=e-c,l=f-d,m=a-c,n=b-d,o=i*i+j*j,p=i*k+j*l,q=i*m+j*n,r=k*k+l*l,s=k*m+l*n,t=1/(o*r-p*p),u=(r*q-p*s)*t,v=(o*s-p*q)*t;return u>=0&&v>=0&&1>u+v},f.PolyK._convex=function(a,b,c,d,e,f,g){return(b-d)*(e-c)+(c-a)*(f-d)>=0==g},f.initDefaultShaders=function(){f.primitiveShader=new f.PrimitiveShader,f.primitiveShader.init(),f.stripShader=new f.StripShader,f.stripShader.init(),f.defaultShader=new f.PixiShader,f.defaultShader.init();var a=f.gl,b=f.defaultShader.program;a.useProgram(b),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.primitiveShader.program),a.disableVertexAttribArray(f.defaultShader.aTextureCoord)},f.deactivatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activateStripShader=function(){var a=f.gl;a.useProgram(f.stripShader.program)},f.deactivateStripShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program)},f.CompileVertexShader=function(a,b){return f._CompileShader(a,b,a.VERTEX_SHADER)},f.CompileFragmentShader=function(a,b){return f._CompileShader(a,b,a.FRAGMENT_SHADER)},f._CompileShader=function(a,b,c){var d=b.join("\n"),e=a.createShader(c);return a.shaderSource(e,d),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)?e:(console.log(a.getShaderInfoLog(e)),null)},f.compileProgram=function(a,b){var c=f.gl,d=f.CompileFragmentShader(c,b),e=f.CompileVertexShader(c,a),g=c.createProgram();return c.attachShader(g,e),c.attachShader(g,d),c.linkProgram(g),c.getProgramParameter(g,c.LINK_STATUS)||console.log("Could not initialise shaders"),g},f.PixiShader=function(){this.program,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;","}"]},f.PixiShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc||f.PixiShader.defaultVertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"); -for(var c in this.uniforms)a[c]=b.getUniformLocation(a,c);this.program=a},f.PixiShader.prototype.syncUniforms=function(){var a=f.gl;for(var b in this.uniforms){var c=this.uniforms[b].type;if("f"==c&&a.uniform1f(this.program[b],this.uniforms[b].value),"f2"==c)a.uniform2f(this.program[b],this.uniforms[b].value.x,this.uniforms[b].value.y);else if("f4"==c)a.uniform4fv(this.program[b],this.uniforms[b].value);else if("mat4"==c)a.uniformMatrix4fv(this.program[b],!1,this.uniforms[b].value);else if("sampler2D"==c){var d=this.uniforms[b].value;a.activeTexture(a.TEXTURE1),a.bindTexture(a.TEXTURE_2D,d.baseTexture._glTexture),a.uniform1i(this.program[b],1)}}},f.PixiShader.defaultVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","varying float vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"],f.StripShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying float vColor;","uniform float alpha;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));","gl_FragColor = gl_FragColor * alpha;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","varying vec2 vTextureCoord;","varying vec2 offsetVector;","varying float vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"]},f.StripShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.PrimitiveShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","gl_FragColor = vColor;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec4 aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform float alpha;","varying vec4 vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","vColor = aColor * alpha;","}"]},f.PrimitiveShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.WebGLGraphics=function(){},f.WebGLGraphics.renderGraphics=function(a,b){var c=f.gl;a._webGL||(a._webGL={points:[],indices:[],lastIndex:0,buffer:c.createBuffer(),indexBuffer:c.createBuffer()}),a.dirty&&(a.dirty=!1,a.clearDirty&&(a.clearDirty=!1,a._webGL.lastIndex=0,a._webGL.points=[],a._webGL.indices=[]),f.WebGLGraphics.updateGraphics(a)),f.activatePrimitiveShader();var d=f.mat3.clone(a.worldTransform);f.mat3.transpose(d),c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA),c.uniformMatrix3fv(f.primitiveShader.translationMatrix,!1,d),c.uniform2f(f.primitiveShader.projectionVector,b.x,-b.y),c.uniform2f(f.primitiveShader.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(f.primitiveShader.alpha,a.worldAlpha),c.bindBuffer(c.ARRAY_BUFFER,a._webGL.buffer),c.vertexAttribPointer(f.primitiveShader.aVertexPosition,2,c.FLOAT,!1,24,0),c.vertexAttribPointer(f.primitiveShader.colorAttribute,4,c.FLOAT,!1,24,8),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),c.drawElements(c.TRIANGLE_STRIP,a._webGL.indices.length,c.UNSIGNED_SHORT,0),f.deactivatePrimitiveShader()},f.WebGLGraphics.updateGraphics=function(a){for(var b=a._webGL.lastIndex;b3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){var e=new f.Point(c[0],c[1]),g=new f.Point(c[c.length-2],c[c.length-1]);if(e.x==g.x&&e.y==g.y){c.pop(),c.pop(),g=new f.Point(c[c.length-2],c[c.length-1]);var h=g.x+.5*(e.x-g.x),i=g.y+.5*(e.y-g.y);c.unshift(h,i),c.push(h,i)}var j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E=b.points,F=b.indices,G=c.length/2,H=c.length,I=E.length/6,J=a.lineWidth/2,K=d(a.lineColor),L=a.lineAlpha,M=K[0]*L,N=K[1]*L,O=K[2]*L;j=c[0],k=c[1],l=c[2],m=c[3],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,E.push(j-p,k-q,M,N,O,L),E.push(j+p,k+q,M,N,O,L);for(var P=1;G-1>P;P++)j=c[2*(P-1)],k=c[2*(P-1)+1],l=c[2*P],m=c[2*P+1],n=c[2*(P+1)],o=c[2*(P+1)+1],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,r=-(m-o),s=l-n,D=Math.sqrt(r*r+s*s),r/=D,s/=D,r*=J,s*=J,v=-q+k-(-q+m),w=-p+l-(-p+j),x=(-p+j)*(-q+m)-(-p+l)*(-q+k),y=-s+o-(-s+m),z=-r+l-(-r+n),A=(-r+n)*(-s+m)-(-r+l)*(-s+o),B=v*z-y*w,0==B&&(B+=1),px=(w*A-z*x)/B,py=(y*x-v*A)/B,C=(px-l)*(px-l)+(py-m)+(py-m),C>19600?(t=p-r,u=q-s,D=Math.sqrt(t*t+u*u),t/=D,u/=D,t*=J,u*=J,E.push(l-t,m-u),E.push(M,N,O,L),E.push(l+t,m+u),E.push(M,N,O,L),E.push(l-t,m-u),E.push(M,N,O,L),H++):(E.push(px,py),E.push(M,N,O,L),E.push(l-(px-l),m-(py-m)),E.push(M,N,O,L));j=c[2*(G-2)],k=c[2*(G-2)+1],l=c[2*(G-1)],m=c[2*(G-1)+1],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,E.push(l-p,m-q),E.push(M,N,O,L),E.push(l+p,m+q),E.push(M,N,O,L),F.push(I);for(var P=0;H>P;P++)F.push(I++);F.push(I-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;a.open?a.data instanceof Array?this.filterManager.pushFilter(a):(c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,255),c.stencilOp(c.KEEP,c.KEEP,c.REPLACE),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,255),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)):a.data instanceof Array?this.filterManager.popFilter():c.disable(c.STENCIL_TEST)},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(){this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;hs?s:E,E=E>t?t:E,E=E>u?u:E,E=E>v?v:E,F=F>w?w:F,F=F>x?x:F,F=F>y?y:F,F=F>z?z:F,C=s>C?s:C,C=t>C?t:C,C=u>C?u:C,C=v>C?v:C,D=w>D?w:D,D=x>D?x:D,D=y>D?y:D,D=z>D?z:D),l=!1,A=A._iNext}while(A!=B);a.filterArea.x=E,a.filterArea.y=F,a.filterArea.width=C-E,a.filterArea.height=D-F},f.FilterTexture=function(a,b){var c=f.gl;this.frameBuffer=c.createFramebuffer(),this.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,this.texture),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.bindFramebuffer(c.FRAMEBUFFER,this.framebuffer),c.bindFramebuffer(c.FRAMEBUFFER,this.frameBuffer),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,this.texture,0),this.resize(a,b)},f.FilterTexture.prototype.resize=function(a,b){this.width=a,this.height=b;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a,b,0,c.RGBA,c.UNSIGNED_BYTE,null)},f.CanvasRenderer=function(a,b,c,d){this.transparent=d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.context=this.view.getContext("2d"),this.refresh=!0,this.view.width=this.width,this.view.height=this.height,this.count=0},f.CanvasRenderer.prototype.constructor=f.CanvasRenderer,f.CanvasRenderer.prototype.render=function(a){f.texturesToUpdate=[],f.texturesToDestroy=[],f.visibleCount++,a.updateTransform(),this.view.style.backgroundColor==a.backgroundColorString||this.transparent||(this.view.style.backgroundColor=a.backgroundColorString),this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.width,this.height),this.renderDisplayObject(a),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0&&(f.Texture.frameUpdates=[])},f.CanvasRenderer.prototype.resize=function(a,b){this.width=a,this.height=b,this.view.width=a,this.view.height=b},f.CanvasRenderer.prototype.renderDisplayObject=function(a){var b,c=this.context;c.globalCompositeOperation="source-over";var d=a.last._iNext;a=a.first;do if(b=a.worldTransform,a.visible)if(a.renderable){if(a instanceof f.Sprite){var e=a.texture.frame;e&&e.width&&e.height&&(c.globalAlpha=a.worldAlpha,c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),c.drawImage(a.texture.baseTexture.source,e.x,e.y,e.width,e.height,a.anchor.x*-e.width,a.anchor.y*-e.height,e.width,e.height))}else if(a instanceof f.Strip)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderStrip(a);else if(a instanceof f.TilingSprite)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderTilingSprite(a);else if(a instanceof f.CustomRenderable)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),a.renderCanvas(this);else if(a instanceof f.Graphics)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),f.CanvasGraphics.renderGraphics(a,c);else if(a instanceof f.FilterBlock&&a.data instanceof f.Graphics){var g=a.data;if(a.open){c.save();var h=g.alpha,i=g.worldTransform;c.setTransform(i[0],i[3],i[1],i[4],i[2],i[5]),g.worldAlpha=.5,c.worldAlpha=0,f.CanvasGraphics.renderGraphicsMask(g,c),c.clip(),g.worldAlpha=h}else c.restore()}a=a._iNext}else a=a._iNext;else a=a.last._iNext;while(a!=d)},f.CanvasRenderer.prototype.renderStripFlat=function(a){var b=this.context,c=a.verticies;a.uvs;var d=c.length/2;this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},f.CanvasRenderer.prototype.renderTilingSprite=function(a){var b=this.context;b.globalAlpha=a.worldAlpha,a.__tilePattern||(a.__tilePattern=b.createPattern(a.texture.baseTexture.source,"repeat")),b.beginPath();var c=a.tilePosition,d=a.tileScale;b.scale(d.x,d.y),b.translate(c.x,c.y),b.fillStyle=a.__tilePattern,b.fillRect(-c.x,-c.y,a.width/d.x,a.height/d.y),b.scale(1/d.x,1/d.y),b.translate(-c.x,-c.y),b.closePath()},f.CanvasRenderer.prototype.renderStrip=function(a){var b=this.context,c=a.verticies,d=a.uvs,e=c.length/2;this.count++;for(var f=1;e-2>f;f++){var g=2*f,h=c[g],i=c[g+2],j=c[g+4],k=c[g+1],l=c[g+3],m=c[g+5],n=d[g]*a.texture.width,o=d[g+2]*a.texture.width,p=d[g+4]*a.texture.width,q=d[g+1]*a.texture.height,r=d[g+3]*a.texture.height,s=d[g+5]*a.texture.height;b.save(),b.beginPath(),b.moveTo(h,k),b.lineTo(i,l),b.lineTo(j,m),b.closePath(),b.clip();var t=n*r+q*p+o*s-r*p-q*o-n*s,u=h*r+q*j+i*s-r*j-q*i-h*s,v=n*i+h*p+o*j-i*p-h*o-n*j,w=n*r*j+q*i*p+h*o*s-h*r*p-q*o*j-n*i*s,x=k*r+q*m+l*s-r*m-q*l-k*s,y=n*l+k*p+o*m-l*p-k*o-n*m,z=n*r*m+q*l*p+k*o*s-k*r*p-q*o*m-n*l*s;b.transform(u/t,x/t,v/t,y/t,w/t,z/t),b.drawImage(a.texture.baseTexture.source,0,0),b.restore()}},f.CanvasGraphics=function(){},f.CanvasGraphics.renderGraphics=function(a,b){for(var c=a.worldAlpha,d=0;d1&&(c=1,console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var d=0;1>d;d++){var e=a.graphicsData[d],g=e.points;if(e.type==f.Graphics.POLY){b.beginPath(),b.moveTo(g[0],g[1]);for(var h=1;hb?b:d,e=b+m>e?b+m:e,g=g>c?b:g,h=c+n>h?c+n:h}else if(k===f.Graphics.CIRC||k===f.Graphics.ELIP){b=a.x,c=a.y;var o=a.radius+l/2;d=d>b-o?b-o:d,e=b+o>e?b+o:e,g=g>c-o?c-o:g,h=c+o>h?c+o:h}else for(var p=0;pb-l?b-l:d,e=b+l>e?b+l:e,g=g>c-l?c-l:g,h=c+l>h?c+l:h}this.bounds=new f.Rectangle(d,g,e-d,h-g)}},f.Graphics.POLY=0,f.Graphics.RECT=1,f.Graphics.CIRC=2,f.Graphics.ELIP=3,f.Strip=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.blendMode=f.blendModes.NORMAL;try{this.uvs=new Float32Array([0,1,1,1,1,0,0,1]),this.verticies=new Float32Array([0,0,0,0,0,0,0,0,0]),this.colors=new Float32Array([1,1,1,1]),this.indices=new Uint16Array([0,1,2,3])}catch(d){this.uvs=[0,1,1,1,1,0,0,1],this.verticies=[0,0,0,0,0,0,0,0,0],this.colors=[1,1,1,1],this.indices=[0,1,2,3]}this.width=b,this.height=c,a.baseTexture.hasLoaded?(this.width=this.texture.frame.width,this.height=this.texture.frame.height,this.updateFrame=!0):(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Strip.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Strip.prototype.constructor=f.Strip,f.Strip.prototype.setTexture=function(a){this.texture=a,this.width=a.frame.width,this.height=a.frame.height,this.updateFrame=!0},f.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Rope=function(a,b){f.Strip.call(this,a),this.points=b;try{this.verticies=new Float32Array(4*b.length),this.uvs=new Float32Array(4*b.length),this.colors=new Float32Array(2*b.length),this.indices=new Uint16Array(2*b.length)}catch(c){this.verticies=verticies,this.uvs=uvs,this.colors=colors,this.indices=indices}this.refresh()},f.Rope.prototype=Object.create(f.Strip.prototype),f.Rope.prototype.constructor=f.Rope,f.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=this.indices,d=this.colors,e=a[0],f=a[0];this.count-=.2,b[0]=0,b[1]=1,b[2]=0,b[3]=1,d[0]=1,d[1]=1,c[0]=0,c[1]=1;for(var g=a.length,h=1;g>h;h++){var f=a[h],i=4*h,j=h/(g-1);h%2?(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1):(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1),i=2*h,d[i]=1,d[i+1]=1,i=2*h,c[i]=i,c[i+1]=i+1,e=f}}},f.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var b,c=this.verticies,d=a[0],e={x:0,y:0},g=a[0];this.count-=.2,c[0]=g.x+e.x,c[1]=g.y+e.y,c[2]=g.x-e.x,c[3]=g.y-e.y;for(var h=a.length,i=1;h>i;i++){var g=a[i],j=4*i;b=i1&&(k=1);var l=Math.sqrt(e.x*e.x+e.y*e.y),m=this.texture.height/2;e.x/=l,e.y/=l,e.x*=m,e.y*=m,c[j]=g.x+e.x,c[j+1]=g.y+e.y,c[j+2]=g.x-e.x,c[j+3]=g.y-e.y,d=g}f.DisplayObjectContainer.prototype.updateTransform.call(this)}},f.Rope.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.width=b,this.height=c,this.tileScale=new f.Point(1,1),this.tilePosition=new f.Point(0,0),this.renderable=!0,this.blendMode=f.blendModes.NORMAL},f.TilingSprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.TilingSprite.prototype.constructor=f.TilingSprite,f.TilingSprite.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Spine=function(a){if(f.DisplayObjectContainer.call(this),this.spineData=f.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new l.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new l.AnimationStateData(this.spineData),this.state=new l.AnimationState(this.stateData),this.slotContainers=[];for(var b=0,c=this.skeleton.drawOrder.length;c>b;b++){var d=this.skeleton.drawOrder[b],e=d.attachment,g=new f.DisplayObjectContainer;if(this.slotContainers.push(g),this.addChild(g),e instanceof l.RegionAttachment){var h=e.rendererObject.name,i=this.createSprite(d,e.rendererObject);d.currentSprite=i,d.currentSpriteName=h,g.addChild(i)}}},f.Spine.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Spine.prototype.constructor=f.Spine,f.Spine.prototype.updateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var b=this.skeleton.drawOrder,c=0,d=b.length;d>c;c++){var e=b[c],g=e.attachment,h=this.slotContainers[c];if(g instanceof l.RegionAttachment){if(g.rendererObject&&(!e.currentSpriteName||e.currentSpriteName!=g.name)){var i=g.rendererObject.name;if(void 0!==e.currentSprite&&(e.currentSprite.visible=!1),e.sprites=e.sprites||{},void 0!==e.sprites[i])e.sprites[i].visible=!0;else{var j=this.createSprite(e,g.rendererObject);h.addChild(j)}e.currentSprite=e.sprites[i],e.currentSpriteName=i}h.visible=!0;var k=e.bone;h.position.x=k.worldX+g.x*k.m00+g.y*k.m01,h.position.y=k.worldY+g.x*k.m10+g.y*k.m11,h.scale.x=k.worldScaleX,h.scale.y=k.worldScaleY,h.rotation=-(e.bone.worldRotation*Math.PI/180)}else h.visible=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.Spine.prototype.createSprite=function(a,b){var c=f.TextureCache[b.name]?b.name:b.name+".png",d=new f.Sprite(f.Texture.fromFrame(c));return d.scale=b.scale,d.rotation=b.rotation,d.anchor.x=d.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[b.name]=d,d};var l={};l.BoneData=function(a,b){this.name=a,this.parent=b},l.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1},l.SlotData=function(a,b){this.name=a,this.boneData=b},l.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null},l.Bone=function(a,b){this.data=a,this.parent=b,this.setToSetupPose()},l.Bone.yDown=!1,l.Bone.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,updateWorldTransform:function(a,b){var c=this.parent;null!=c?(this.worldX=this.x*c.m00+this.y*c.m01+c.worldX,this.worldY=this.x*c.m10+this.y*c.m11+c.worldY,this.worldScaleX=c.worldScaleX*this.scaleX,this.worldScaleY=c.worldScaleY*this.scaleY,this.worldRotation=c.worldRotation+this.rotation):(this.worldX=this.x,this.worldY=this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotation);var d=this.worldRotation*Math.PI/180,e=Math.cos(d),f=Math.sin(d);this.m00=e*this.worldScaleX,this.m10=f*this.worldScaleX,this.m01=-f*this.worldScaleY,this.m11=e*this.worldScaleY,a&&(this.m00=-this.m00,this.m01=-this.m01),b&&(this.m10=-this.m10,this.m11=-this.m11),l.Bone.yDown&&(this.m10=-this.m10,this.m11=-this.m11)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY}},l.Slot=function(a,b,c){this.data=a,this.skeleton=b,this.bone=c,this.setToSetupPose()},l.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,setAttachment:function(a){this.attachment=a,this._attachmentTime=this.skeleton.time},setAttachmentTime:function(a){this._attachmentTime=this.skeleton.time-a},getAttachmentTime:function(){return this.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},l.Skin=function(a){this.name=a,this.attachments={}},l.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},l.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},l.Animation.prototype={apply:function(a,b,c){c&&0!=this.duration&&(b%=this.duration);for(var d=this.timelines,e=0,f=d.length;f>e;e++)d[e].apply(a,b,1)},mix:function(a,b,c,d){c&&0!=this.duration&&(b%=this.duration);for(var e=this.timelines,f=0,g=e.length;g>f;f++)e[f].apply(a,b,d)}},l.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(0==e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},l.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},l.Curves=function(a){this.curves=[],this.curves.length=6*(a-1)},l.Curves.prototype={setLinear:function(a){this.curves[6*a]=0},setStepped:function(a){this.curves[6*a]=-1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=6*a,r=this.curves;r[q]=b*i+m*j+o*h,r[q+1]=c*i+n*j+p*h,r[q+2]=m*k+o*l,r[q+3]=n*k+p*l,r[q+4]=o*l,r[q+5]=p*l},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=6*a,d=this.curves,e=d[c];if(!e)return b;if(-1==e)return 0;for(var f=d[c+1],g=d[c+2],h=d[c+3],i=d[c+4],j=d[c+5],k=e,l=f,m=8;;){if(k>=b){var n=k-e,o=l-f;return o+(l-o)*(b-n)/(k-n)}if(0==m)break;m--,e+=g,f+=h,g+=i,h+=j,k+=e,l+=f}return l+(1-l)*(b-k)/(1-k)}},l.RotateTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=2*a},l.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-2]){for(var f=e.data.rotation+d[d.length-1]-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;return e.rotation+=f*c,void 0}var g=l.binarySearch(d,b,2),h=d[g-1],i=d[g],j=1-(b-i)/(d[g-2]-i);j=this.curves.getCurvePercent(g/2-1,j);for(var f=d[g+1]-h;f>180;)f-=360;for(;-180>f;)f+=360;for(f=e.data.rotation+(h+f*j)-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;e.rotation+=f*c}}},l.TranslateTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=3*a},l.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.x+=(e.data.x+d[d.length-2]-e.x)*c,e.y+=(e.data.y+d[d.length-1]-e.y)*c,void 0;var f=l.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.x+=(e.data.x+g+(d[f+1]-g)*j-e.x)*c,e.y+=(e.data.y+h+(d[f+2]-h)*j-e.y)*c}}},l.ScaleTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=3*a},l.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.scaleX+=(e.data.scaleX-1+d[d.length-2]-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+d[d.length-1]-e.scaleY)*c,void 0;var f=l.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.scaleX+=(e.data.scaleX-1+g+(d[f+1]-g)*j-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+h+(d[f+2]-h)*j-e.scaleY)*c}}},l.ColorTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=5*a},l.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(c,d){c*=5,this.frames[c]=d,this.frames[c+1]=r,this.frames[c+2]=g,this.frames[c+3]=b,this.frames[c+4]=a},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-5]){var f=d.length-1;return e.r=d[f-3],e.g=d[f-2],e.b=d[f-1],e.a=d[f],void 0}var g=l.binarySearch(d,b,5),h=d[g-4],i=d[g-3],j=d[g-2],k=d[g-1],m=d[g],n=1-(b-m)/(d[g-5]-m);n=this.curves.getCurvePercent(g/5-1,n);var o=h+(d[g+1]-h)*n,p=i+(d[g+2]-i)*n,q=j+(d[g+3]-j)*n,r=k+(d[g+4]-k)*n;1>c?(e.r+=(o-e.r)*c,e.g+=(p-e.g)*c,e.b+=(q-e.b)*c,e.a+=(r-e.a)*c):(e.r=o,e.g=p,e.b=q,e.a=r)}}},l.AttachmentTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},l.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b){var c=this.frames;if(!(b=c[c.length-1]?c.length-1:l.binarySearch(c,b,1)-1;var e=this.attachmentNames[d];a.slots[this.slotIndex].setAttachment(e?a.getAttachmentBySlotIndex(this.slotIndex,e):null)}}},l.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.animations=[]},l.SkeletonData.prototype={defaultSkin:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},l.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,c=a.bones.length;c>b;b++){var d=a.bones[b],e=d.parent?this.bones[a.bones.indexOf(d.parent)]:null;this.bones.push(new l.Bone(d,e))}this.slots=[],this.drawOrder=[];for(var b=0,c=a.slots.length;c>b;b++){var f=a.slots[b],g=this.bones[a.bones.indexOf(f.boneData)],h=new l.Slot(f,this,g);this.slots.push(h),this.drawOrder.push(h)}},l.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateWorldTransform:function(){for(var a=this.flipX,b=this.flipY,c=this.bones,d=0,e=c.length;e>d;d++)c[d].updateWorldTransform(a,b)},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose()},setSlotsToSetupPose:function(){for(var a=this.slots,b=0,c=a.length;c>b;b++)a[b].setToSetupPose(b)},getRootBone:function(){return 0==this.bones.length?null:this.bones[0]},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a);if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){this.skin&&a&&a._attachAll(this,this.skin),this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.size;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachment(d,b),null==g))throw"Attachment not found: "+b+", for slot: "+a;return f.setAttachment(g),void 0}}throw"Slot not found: "+a},update:function(a){time+=a}},l.AttachmentType={region:0},l.RegionAttachment=function(){this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},l.RegionAttachment.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,c=-this.width/2*this.scaleX+this.regionOffsetX*a,d=-this.height/2*this.scaleY+this.regionOffsetY*b,e=c+this.regionWidth*a,f=d+this.regionHeight*b,g=this.rotation*Math.PI/180,h=Math.cos(g),i=Math.sin(g),j=c*h+this.x,k=c*i,l=d*h+this.y,m=d*i,n=e*h+this.x,o=e*i,p=f*h+this.y,q=f*i,r=this.offset;r[0]=j-m,r[1]=l+k,r[2]=j-q,r[3]=p+k,r[4]=n-q,r[5]=p+o,r[6]=n-m,r[7]=l+o},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},l.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},l.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=this.animationToMixTime[a.name+":"+b.name];return c?c:this.defaultMix}},l.AnimationState=function(a){this.data=a,this.queue=[]},l.AnimationState.prototype={current:null,previous:null,currentTime:0,previousTime:0,currentLoop:!1,previousLoop:!1,mixTime:0,mixDuration:0,update:function(a){if(this.currentTime+=a,this.previousTime+=a,this.mixTime+=a,this.queue.length>0){var b=this.queue[0];this.currentTime>=b.delay&&(this._setAnimation(b.animation,b.loop),this.queue.shift())}},apply:function(a){if(this.current)if(this.previous){this.previous.apply(a,this.previousTime,this.previousLoop);var b=this.mixTime/this.mixDuration;b>=1&&(b=1,this.previous=null),this.current.mix(a,this.currentTime,this.currentLoop,b)}else this.current.apply(a,this.currentTime,this.currentLoop)},clearAnimation:function(){this.previous=null,this.current=null,this.queue.length=0},_setAnimation:function(a,b){this.previous=null,a&&this.current&&(this.mixDuration=this.data.getMix(this.current,a),this.mixDuration>0&&(this.mixTime=0,this.previous=this.current,this.previousTime=this.currentTime,this.previousLoop=this.currentLoop)),this.current=a,this.currentLoop=b,this.currentTime=0},setAnimationByName:function(a,b){var c=this.data.skeletonData.findAnimation(a);if(!c)throw"Animation not found: "+a;this.setAnimation(c,b)},setAnimation:function(a,b){this.queue.length=0,this._setAnimation(a,b)},addAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;this.addAnimation(d,b,c)},addAnimation:function(a,b,c){var d={};if(d.animation=a,d.loop=b,!c||0>=c){var e=0==this.queue.length?this.current:this.queue[this.queue.length-1].animation;c=null!=e?e.duration-this.data.getMix(e,a)+(c||0):0}d.delay=c,this.queue.push(d)},isComplete:function(){return!this.current||this.currentTime>=this.current.duration}},l.SkeletonJson=function(a){this.attachmentLoader=a},l.SkeletonJson.prototype={scale:1,readSkeletonData:function(a){for(var b=new l.SkeletonData,c=a.bones,d=0,e=c.length;e>d;d++){var f=c[d],g=null;if(f.parent&&(g=b.findBone(f.parent),!g))throw"Parent bone not found: "+f.parent;var h=new l.BoneData(f.name,g);h.length=(f.length||0)*this.scale,h.x=(f.x||0)*this.scale,h.y=(f.y||0)*this.scale,h.rotation=f.rotation||0,h.scaleX=f.scaleX||1,h.scaleY=f.scaleY||1,b.bones.push(h)}for(var i=a.slots,d=0,e=i.length;e>d;d++){var j=i[d],h=b.findBone(j.bone);if(!h)throw"Slot bone not found: "+j.bone;var k=new l.SlotData(j.name,h),m=j.color;m&&(k.r=l.SkeletonJson.toColor(m,0),k.g=l.SkeletonJson.toColor(m,1),k.b=l.SkeletonJson.toColor(m,2),k.a=l.SkeletonJson.toColor(m,3)),k.attachmentName=j.attachment,b.slots.push(k)}var n=a.skins;for(var o in n)if(n.hasOwnProperty(o)){var p=n[o],q=new l.Skin(o);for(var r in p)if(p.hasOwnProperty(r)){var s=b.findSlotIndex(r),t=p[r];for(var u in t)if(t.hasOwnProperty(u)){var v=this.readAttachment(q,u,t[u]);null!=v&&q.addAttachment(s,u,v)}}b.skins.push(q),"default"==q.name&&(b.defaultSkin=q)}var w=a.animations;for(var x in w)w.hasOwnProperty(x)&&this.readAnimation(x,w[x],b);return b},readAttachment:function(a,b,c){b=c.name||b;var d=l.AttachmentType[c.type||"region"];if(d==l.AttachmentType.region){var e=new l.RegionAttachment;return e.x=(c.x||0)*this.scale,e.y=(c.y||0)*this.scale,e.scaleX=c.scaleX||1,e.scaleY=c.scaleY||1,e.rotation=c.rotation||0,e.width=(c.width||32)*this.scale,e.height=(c.height||32)*this.scale,e.updateOffset(),e.rendererObject={},e.rendererObject.name=b,e.rendererObject.scale={},e.rendererObject.scale.x=e.scaleX,e.rendererObject.scale.y=e.scaleY,e.rendererObject.rotation=-e.rotation*Math.PI/180,e -}throw"Unknown attachment type: "+d},readAnimation:function(a,b,c){var d=[],e=0,f=b.bones;for(var g in f)if(f.hasOwnProperty(g)){var h=c.findBoneIndex(g);if(-1==h)throw"Bone not found: "+g;var i=f[g];for(var j in i)if(i.hasOwnProperty(j)){var k=i[j];if("rotate"==j){var m=new l.RotateTimeline(k.length);m.boneIndex=h;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o];m.setFrame(n,q.time,q.angle),l.SkeletonJson.readCurve(m,n,q),n++}d.push(m),e=Math.max(e,m.frames[2*m.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var m,r=1;"scale"==j?m=new l.ScaleTimeline(k.length):(m=new l.TranslateTimeline(k.length),r=this.scale),m.boneIndex=h;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;m.setFrame(n,q.time,s,t),l.SkeletonJson.readCurve(m,n,q),n++}d.push(m),e=Math.max(e,m.frames[3*m.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var m=new l.ColorTimeline(k.length);m.slotIndex=x;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=l.SkeletonJson.toColor(y,0),A=l.SkeletonJson.toColor(y,1),B=l.SkeletonJson.toColor(y,2),C=l.SkeletonJson.toColor(y,3);m.setFrame(n,q.time,z,A,B,C),l.SkeletonJson.readCurve(m,n,q),n++}d.push(m),e=Math.max(e,m.frames[5*m.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var m=new l.AttachmentTimeline(k.length);m.slotIndex=x;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o];m.setFrame(n++,q.time,q.name)}d.push(m),e=Math.max(e,m.frames[m.getFrameCount()-1])}}}c.animations.push(new l.Animation(a,d,e))}},l.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},l.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},l.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new l.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new l.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new l.AtlasPage,e.name=f,e.format=l.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=l.Atlas.TextureFilter[d[0]],e.magFilter=l.Atlas.TextureFilter[d[1]];var m=c.readValue();e.uWrap=l.Atlas.TextureWrap.clampToEdge,e.vWrap=l.Atlas.TextureWrap.clampToEdge,"x"==m?e.uWrap=l.Atlas.TextureWrap.repeat:"y"==m?e.vWrap=l.Atlas.TextureWrap.repeat:"xy"==m&&(e.uWrap=e.vWrap=l.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},l.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},l.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},l.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},l.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},l.AtlasPage=function(){},l.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},l.AtlasRegion=function(){},l.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},l.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},l.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},l.AtlasAttachmentLoader=function(a){this.atlas=a},l.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case l.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new l.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},l.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;h3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){var e=new f.Point(c[0],c[1]),g=new f.Point(c[c.length-2],c[c.length-1]);if(e.x==g.x&&e.y==g.y){c.pop(),c.pop(),g=new f.Point(c[c.length-2],c[c.length-1]);var h=g.x+.5*(e.x-g.x),i=g.y+.5*(e.y-g.y);c.unshift(h,i),c.push(h,i)}var j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E=b.points,F=b.indices,G=c.length/2,H=c.length,I=E.length/6,J=a.lineWidth/2,K=d(a.lineColor),L=a.lineAlpha,M=K[0]*L,N=K[1]*L,O=K[2]*L;j=c[0],k=c[1],l=c[2],m=c[3],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,E.push(j-p,k-q,M,N,O,L),E.push(j+p,k+q,M,N,O,L);for(var P=1;G-1>P;P++)j=c[2*(P-1)],k=c[2*(P-1)+1],l=c[2*P],m=c[2*P+1],n=c[2*(P+1)],o=c[2*(P+1)+1],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,r=-(m-o),s=l-n,D=Math.sqrt(r*r+s*s),r/=D,s/=D,r*=J,s*=J,v=-q+k-(-q+m),w=-p+l-(-p+j),x=(-p+j)*(-q+m)-(-p+l)*(-q+k),y=-s+o-(-s+m),z=-r+l-(-r+n),A=(-r+n)*(-s+m)-(-r+l)*(-s+o),B=v*z-y*w,0==B&&(B+=1),px=(w*A-z*x)/B,py=(y*x-v*A)/B,C=(px-l)*(px-l)+(py-m)+(py-m),C>19600?(t=p-r,u=q-s,D=Math.sqrt(t*t+u*u),t/=D,u/=D,t*=J,u*=J,E.push(l-t,m-u),E.push(M,N,O,L),E.push(l+t,m+u),E.push(M,N,O,L),E.push(l-t,m-u),E.push(M,N,O,L),H++):(E.push(px,py),E.push(M,N,O,L),E.push(l-(px-l),m-(py-m)),E.push(M,N,O,L));j=c[2*(G-2)],k=c[2*(G-2)+1],l=c[2*(G-1)],m=c[2*(G-1)+1],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,E.push(l-p,m-q),E.push(M,N,O,L),E.push(l+p,m+q),E.push(M,N,O,L),F.push(I);for(var P=0;H>P;P++)F.push(I++);F.push(I-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},flip=!1;var l=[],m=0;f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;if(a.open)a.data instanceof Array?this.filterManager.pushFilter(a):(m++,l.push(a),c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.INCR),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP));else if(a.data instanceof Array)this.filterManager.popFilter();else{var d=l.pop(a);d&&(c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.DECR),f.WebGLGraphics.renderGraphics(d.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)),c.disable(c.STENCIL_TEST)}},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(){this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;hs?s:E,E=E>t?t:E,E=E>u?u:E,E=E>v?v:E,F=F>w?w:F,F=F>x?x:F,F=F>y?y:F,F=F>z?z:F,C=s>C?s:C,C=t>C?t:C,C=u>C?u:C,C=v>C?v:C,D=w>D?w:D,D=x>D?x:D,D=y>D?y:D,D=z>D?z:D),l=!1,A=A._iNext}while(A!=B);a.filterArea.x=E,a.filterArea.y=F,a.filterArea.width=C-E,a.filterArea.height=D-F},f.FilterTexture=function(a,b){var c=f.gl;this.frameBuffer=c.createFramebuffer(),this.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,this.texture),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.bindFramebuffer(c.FRAMEBUFFER,this.framebuffer),c.bindFramebuffer(c.FRAMEBUFFER,this.frameBuffer),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,this.texture,0),this.resize(a,b)},f.FilterTexture.prototype.resize=function(a,b){this.width=a,this.height=b;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a,b,0,c.RGBA,c.UNSIGNED_BYTE,null)},f.CanvasRenderer=function(a,b,c,d){this.transparent=d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.context=this.view.getContext("2d"),this.refresh=!0,this.view.width=this.width,this.view.height=this.height,this.count=0},f.CanvasRenderer.prototype.constructor=f.CanvasRenderer,f.CanvasRenderer.prototype.render=function(a){f.texturesToUpdate=[],f.texturesToDestroy=[],f.visibleCount++,a.updateTransform(),this.view.style.backgroundColor==a.backgroundColorString||this.transparent||(this.view.style.backgroundColor=a.backgroundColorString),this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.width,this.height),this.renderDisplayObject(a),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0&&(f.Texture.frameUpdates=[])},f.CanvasRenderer.prototype.resize=function(a,b){this.width=a,this.height=b,this.view.width=a,this.view.height=b},f.CanvasRenderer.prototype.renderDisplayObject=function(a){var b,c=this.context;c.globalCompositeOperation="source-over";var d=a.last._iNext;a=a.first;do if(b=a.worldTransform,a.visible)if(a.renderable){if(a instanceof f.Sprite){var e=a.texture.frame;e&&e.width&&e.height&&(c.globalAlpha=a.worldAlpha,c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),c.drawImage(a.texture.baseTexture.source,e.x,e.y,e.width,e.height,a.anchor.x*-e.width,a.anchor.y*-e.height,e.width,e.height))}else if(a instanceof f.Strip)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderStrip(a);else if(a instanceof f.TilingSprite)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderTilingSprite(a);else if(a instanceof f.CustomRenderable)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),a.renderCanvas(this);else if(a instanceof f.Graphics)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),f.CanvasGraphics.renderGraphics(a,c);else if(a instanceof f.FilterBlock&&a.data instanceof f.Graphics){var g=a.data;if(a.open){c.save();var h=g.alpha,i=g.worldTransform;c.setTransform(i[0],i[3],i[1],i[4],i[2],i[5]),g.worldAlpha=.5,c.worldAlpha=0,f.CanvasGraphics.renderGraphicsMask(g,c),c.clip(),g.worldAlpha=h}else c.restore()}a=a._iNext}else a=a._iNext;else a=a.last._iNext;while(a!=d)},f.CanvasRenderer.prototype.renderStripFlat=function(a){var b=this.context,c=a.verticies;a.uvs;var d=c.length/2;this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},f.CanvasRenderer.prototype.renderTilingSprite=function(a){var b=this.context;b.globalAlpha=a.worldAlpha,a.__tilePattern||(a.__tilePattern=b.createPattern(a.texture.baseTexture.source,"repeat")),b.beginPath();var c=a.tilePosition,d=a.tileScale;b.scale(d.x,d.y),b.translate(c.x,c.y),b.fillStyle=a.__tilePattern,b.fillRect(-c.x,-c.y,a.width/d.x,a.height/d.y),b.scale(1/d.x,1/d.y),b.translate(-c.x,-c.y),b.closePath()},f.CanvasRenderer.prototype.renderStrip=function(a){var b=this.context,c=a.verticies,d=a.uvs,e=c.length/2;this.count++;for(var f=1;e-2>f;f++){var g=2*f,h=c[g],i=c[g+2],j=c[g+4],k=c[g+1],l=c[g+3],m=c[g+5],n=d[g]*a.texture.width,o=d[g+2]*a.texture.width,p=d[g+4]*a.texture.width,q=d[g+1]*a.texture.height,r=d[g+3]*a.texture.height,s=d[g+5]*a.texture.height;b.save(),b.beginPath(),b.moveTo(h,k),b.lineTo(i,l),b.lineTo(j,m),b.closePath(),b.clip();var t=n*r+q*p+o*s-r*p-q*o-n*s,u=h*r+q*j+i*s-r*j-q*i-h*s,v=n*i+h*p+o*j-i*p-h*o-n*j,w=n*r*j+q*i*p+h*o*s-h*r*p-q*o*j-n*i*s,x=k*r+q*m+l*s-r*m-q*l-k*s,y=n*l+k*p+o*m-l*p-k*o-n*m,z=n*r*m+q*l*p+k*o*s-k*r*p-q*o*m-n*l*s;b.transform(u/t,x/t,v/t,y/t,w/t,z/t),b.drawImage(a.texture.baseTexture.source,0,0),b.restore()}},f.CanvasGraphics=function(){},f.CanvasGraphics.renderGraphics=function(a,b){for(var c=a.worldAlpha,d=0;d1&&(c=1,console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var d=0;1>d;d++){var e=a.graphicsData[d],g=e.points;if(e.type==f.Graphics.POLY){b.beginPath(),b.moveTo(g[0],g[1]);for(var h=1;hb?b:d,e=b+m>e?b+m:e,g=g>c?b:g,h=c+n>h?c+n:h}else if(k===f.Graphics.CIRC||k===f.Graphics.ELIP){b=a.x,c=a.y;var o=a.radius+l/2;d=d>b-o?b-o:d,e=b+o>e?b+o:e,g=g>c-o?c-o:g,h=c+o>h?c+o:h}else for(var p=0;pb-l?b-l:d,e=b+l>e?b+l:e,g=g>c-l?c-l:g,h=c+l>h?c+l:h}this.bounds=new f.Rectangle(d,g,e-d,h-g)}},f.Graphics.POLY=0,f.Graphics.RECT=1,f.Graphics.CIRC=2,f.Graphics.ELIP=3,f.Strip=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.blendMode=f.blendModes.NORMAL;try{this.uvs=new Float32Array([0,1,1,1,1,0,0,1]),this.verticies=new Float32Array([0,0,0,0,0,0,0,0,0]),this.colors=new Float32Array([1,1,1,1]),this.indices=new Uint16Array([0,1,2,3])}catch(d){this.uvs=[0,1,1,1,1,0,0,1],this.verticies=[0,0,0,0,0,0,0,0,0],this.colors=[1,1,1,1],this.indices=[0,1,2,3]}this.width=b,this.height=c,a.baseTexture.hasLoaded?(this.width=this.texture.frame.width,this.height=this.texture.frame.height,this.updateFrame=!0):(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Strip.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Strip.prototype.constructor=f.Strip,f.Strip.prototype.setTexture=function(a){this.texture=a,this.width=a.frame.width,this.height=a.frame.height,this.updateFrame=!0},f.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Rope=function(a,b){f.Strip.call(this,a),this.points=b;try{this.verticies=new Float32Array(4*b.length),this.uvs=new Float32Array(4*b.length),this.colors=new Float32Array(2*b.length),this.indices=new Uint16Array(2*b.length)}catch(c){this.verticies=verticies,this.uvs=uvs,this.colors=colors,this.indices=indices}this.refresh()},f.Rope.prototype=Object.create(f.Strip.prototype),f.Rope.prototype.constructor=f.Rope,f.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=this.indices,d=this.colors,e=a[0],f=a[0];this.count-=.2,b[0]=0,b[1]=1,b[2]=0,b[3]=1,d[0]=1,d[1]=1,c[0]=0,c[1]=1;for(var g=a.length,h=1;g>h;h++){var f=a[h],i=4*h,j=h/(g-1);h%2?(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1):(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1),i=2*h,d[i]=1,d[i+1]=1,i=2*h,c[i]=i,c[i+1]=i+1,e=f}}},f.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var b,c=this.verticies,d=a[0],e={x:0,y:0},g=a[0];this.count-=.2,c[0]=g.x+e.x,c[1]=g.y+e.y,c[2]=g.x-e.x,c[3]=g.y-e.y;for(var h=a.length,i=1;h>i;i++){var g=a[i],j=4*i;b=i1&&(k=1);var l=Math.sqrt(e.x*e.x+e.y*e.y),m=this.texture.height/2;e.x/=l,e.y/=l,e.x*=m,e.y*=m,c[j]=g.x+e.x,c[j+1]=g.y+e.y,c[j+2]=g.x-e.x,c[j+3]=g.y-e.y,d=g}f.DisplayObjectContainer.prototype.updateTransform.call(this)}},f.Rope.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.width=b,this.height=c,this.tileScale=new f.Point(1,1),this.tilePosition=new f.Point(0,0),this.renderable=!0,this.blendMode=f.blendModes.NORMAL},f.TilingSprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.TilingSprite.prototype.constructor=f.TilingSprite,f.TilingSprite.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Spine=function(a){if(f.DisplayObjectContainer.call(this),this.spineData=f.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new n.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new n.AnimationStateData(this.spineData),this.state=new n.AnimationState(this.stateData),this.slotContainers=[];for(var b=0,c=this.skeleton.drawOrder.length;c>b;b++){var d=this.skeleton.drawOrder[b],e=d.attachment,g=new f.DisplayObjectContainer;if(this.slotContainers.push(g),this.addChild(g),e instanceof n.RegionAttachment){var h=e.rendererObject.name,i=this.createSprite(d,e.rendererObject);d.currentSprite=i,d.currentSpriteName=h,g.addChild(i)}}},f.Spine.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Spine.prototype.constructor=f.Spine,f.Spine.prototype.updateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var b=this.skeleton.drawOrder,c=0,d=b.length;d>c;c++){var e=b[c],g=e.attachment,h=this.slotContainers[c];if(g instanceof n.RegionAttachment){if(g.rendererObject&&(!e.currentSpriteName||e.currentSpriteName!=g.name)){var i=g.rendererObject.name;if(void 0!==e.currentSprite&&(e.currentSprite.visible=!1),e.sprites=e.sprites||{},void 0!==e.sprites[i])e.sprites[i].visible=!0;else{var j=this.createSprite(e,g.rendererObject);h.addChild(j)}e.currentSprite=e.sprites[i],e.currentSpriteName=i}h.visible=!0;var k=e.bone;h.position.x=k.worldX+g.x*k.m00+g.y*k.m01,h.position.y=k.worldY+g.x*k.m10+g.y*k.m11,h.scale.x=k.worldScaleX,h.scale.y=k.worldScaleY,h.rotation=-(e.bone.worldRotation*Math.PI/180)}else h.visible=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.Spine.prototype.createSprite=function(a,b){var c=f.TextureCache[b.name]?b.name:b.name+".png",d=new f.Sprite(f.Texture.fromFrame(c));return d.scale=b.scale,d.rotation=b.rotation,d.anchor.x=d.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[b.name]=d,d};var n={};n.BoneData=function(a,b){this.name=a,this.parent=b},n.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1},n.SlotData=function(a,b){this.name=a,this.boneData=b},n.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null},n.Bone=function(a,b){this.data=a,this.parent=b,this.setToSetupPose()},n.Bone.yDown=!1,n.Bone.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,updateWorldTransform:function(a,b){var c=this.parent;null!=c?(this.worldX=this.x*c.m00+this.y*c.m01+c.worldX,this.worldY=this.x*c.m10+this.y*c.m11+c.worldY,this.worldScaleX=c.worldScaleX*this.scaleX,this.worldScaleY=c.worldScaleY*this.scaleY,this.worldRotation=c.worldRotation+this.rotation):(this.worldX=this.x,this.worldY=this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotation);var d=this.worldRotation*Math.PI/180,e=Math.cos(d),f=Math.sin(d);this.m00=e*this.worldScaleX,this.m10=f*this.worldScaleX,this.m01=-f*this.worldScaleY,this.m11=e*this.worldScaleY,a&&(this.m00=-this.m00,this.m01=-this.m01),b&&(this.m10=-this.m10,this.m11=-this.m11),n.Bone.yDown&&(this.m10=-this.m10,this.m11=-this.m11)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY}},n.Slot=function(a,b,c){this.data=a,this.skeleton=b,this.bone=c,this.setToSetupPose()},n.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,setAttachment:function(a){this.attachment=a,this._attachmentTime=this.skeleton.time},setAttachmentTime:function(a){this._attachmentTime=this.skeleton.time-a},getAttachmentTime:function(){return this.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},n.Skin=function(a){this.name=a,this.attachments={}},n.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},n.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},n.Animation.prototype={apply:function(a,b,c){c&&0!=this.duration&&(b%=this.duration);for(var d=this.timelines,e=0,f=d.length;f>e;e++)d[e].apply(a,b,1)},mix:function(a,b,c,d){c&&0!=this.duration&&(b%=this.duration);for(var e=this.timelines,f=0,g=e.length;g>f;f++)e[f].apply(a,b,d)}},n.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(0==e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},n.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},n.Curves=function(a){this.curves=[],this.curves.length=6*(a-1)},n.Curves.prototype={setLinear:function(a){this.curves[6*a]=0},setStepped:function(a){this.curves[6*a]=-1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=6*a,r=this.curves;r[q]=b*i+m*j+o*h,r[q+1]=c*i+n*j+p*h,r[q+2]=m*k+o*l,r[q+3]=n*k+p*l,r[q+4]=o*l,r[q+5]=p*l},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=6*a,d=this.curves,e=d[c];if(!e)return b;if(-1==e)return 0;for(var f=d[c+1],g=d[c+2],h=d[c+3],i=d[c+4],j=d[c+5],k=e,l=f,m=8;;){if(k>=b){var n=k-e,o=l-f;return o+(l-o)*(b-n)/(k-n)}if(0==m)break;m--,e+=g,f+=h,g+=i,h+=j,k+=e,l+=f}return l+(1-l)*(b-k)/(1-k)}},n.RotateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=2*a},n.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-2]){for(var f=e.data.rotation+d[d.length-1]-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;return e.rotation+=f*c,void 0}var g=n.binarySearch(d,b,2),h=d[g-1],i=d[g],j=1-(b-i)/(d[g-2]-i);j=this.curves.getCurvePercent(g/2-1,j);for(var f=d[g+1]-h;f>180;)f-=360;for(;-180>f;)f+=360;for(f=e.data.rotation+(h+f*j)-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;e.rotation+=f*c}}},n.TranslateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.x+=(e.data.x+d[d.length-2]-e.x)*c,e.y+=(e.data.y+d[d.length-1]-e.y)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.x+=(e.data.x+g+(d[f+1]-g)*j-e.x)*c,e.y+=(e.data.y+h+(d[f+2]-h)*j-e.y)*c}}},n.ScaleTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.scaleX+=(e.data.scaleX-1+d[d.length-2]-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+d[d.length-1]-e.scaleY)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.scaleX+=(e.data.scaleX-1+g+(d[f+1]-g)*j-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+h+(d[f+2]-h)*j-e.scaleY)*c}}},n.ColorTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=5*a},n.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(c,d){c*=5,this.frames[c]=d,this.frames[c+1]=r,this.frames[c+2]=g,this.frames[c+3]=b,this.frames[c+4]=a},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-5]){var f=d.length-1;return e.r=d[f-3],e.g=d[f-2],e.b=d[f-1],e.a=d[f],void 0}var g=n.binarySearch(d,b,5),h=d[g-4],i=d[g-3],j=d[g-2],k=d[g-1],l=d[g],m=1-(b-l)/(d[g-5]-l);m=this.curves.getCurvePercent(g/5-1,m);var o=h+(d[g+1]-h)*m,p=i+(d[g+2]-i)*m,q=j+(d[g+3]-j)*m,r=k+(d[g+4]-k)*m;1>c?(e.r+=(o-e.r)*c,e.g+=(p-e.g)*c,e.b+=(q-e.b)*c,e.a+=(r-e.a)*c):(e.r=o,e.g=p,e.b=q,e.a=r)}}},n.AttachmentTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},n.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b){var c=this.frames;if(!(b=c[c.length-1]?c.length-1:n.binarySearch(c,b,1)-1;var e=this.attachmentNames[d];a.slots[this.slotIndex].setAttachment(e?a.getAttachmentBySlotIndex(this.slotIndex,e):null)}}},n.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.animations=[]},n.SkeletonData.prototype={defaultSkin:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},n.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,c=a.bones.length;c>b;b++){var d=a.bones[b],e=d.parent?this.bones[a.bones.indexOf(d.parent)]:null;this.bones.push(new n.Bone(d,e))}this.slots=[],this.drawOrder=[];for(var b=0,c=a.slots.length;c>b;b++){var f=a.slots[b],g=this.bones[a.bones.indexOf(f.boneData)],h=new n.Slot(f,this,g);this.slots.push(h),this.drawOrder.push(h)}},n.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateWorldTransform:function(){for(var a=this.flipX,b=this.flipY,c=this.bones,d=0,e=c.length;e>d;d++)c[d].updateWorldTransform(a,b)},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose()},setSlotsToSetupPose:function(){for(var a=this.slots,b=0,c=a.length;c>b;b++)a[b].setToSetupPose(b)},getRootBone:function(){return 0==this.bones.length?null:this.bones[0]},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a);if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){this.skin&&a&&a._attachAll(this,this.skin),this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.size;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachment(d,b),null==g))throw"Attachment not found: "+b+", for slot: "+a;return f.setAttachment(g),void 0}}throw"Slot not found: "+a},update:function(a){time+=a}},n.AttachmentType={region:0},n.RegionAttachment=function(){this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},n.RegionAttachment.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,c=-this.width/2*this.scaleX+this.regionOffsetX*a,d=-this.height/2*this.scaleY+this.regionOffsetY*b,e=c+this.regionWidth*a,f=d+this.regionHeight*b,g=this.rotation*Math.PI/180,h=Math.cos(g),i=Math.sin(g),j=c*h+this.x,k=c*i,l=d*h+this.y,m=d*i,n=e*h+this.x,o=e*i,p=f*h+this.y,q=f*i,r=this.offset;r[0]=j-m,r[1]=l+k,r[2]=j-q,r[3]=p+k,r[4]=n-q,r[5]=p+o,r[6]=n-m,r[7]=l+o},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},n.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},n.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=this.animationToMixTime[a.name+":"+b.name];return c?c:this.defaultMix}},n.AnimationState=function(a){this.data=a,this.queue=[]},n.AnimationState.prototype={current:null,previous:null,currentTime:0,previousTime:0,currentLoop:!1,previousLoop:!1,mixTime:0,mixDuration:0,update:function(a){if(this.currentTime+=a,this.previousTime+=a,this.mixTime+=a,this.queue.length>0){var b=this.queue[0];this.currentTime>=b.delay&&(this._setAnimation(b.animation,b.loop),this.queue.shift())}},apply:function(a){if(this.current)if(this.previous){this.previous.apply(a,this.previousTime,this.previousLoop);var b=this.mixTime/this.mixDuration;b>=1&&(b=1,this.previous=null),this.current.mix(a,this.currentTime,this.currentLoop,b)}else this.current.apply(a,this.currentTime,this.currentLoop)},clearAnimation:function(){this.previous=null,this.current=null,this.queue.length=0},_setAnimation:function(a,b){this.previous=null,a&&this.current&&(this.mixDuration=this.data.getMix(this.current,a),this.mixDuration>0&&(this.mixTime=0,this.previous=this.current,this.previousTime=this.currentTime,this.previousLoop=this.currentLoop)),this.current=a,this.currentLoop=b,this.currentTime=0},setAnimationByName:function(a,b){var c=this.data.skeletonData.findAnimation(a);if(!c)throw"Animation not found: "+a;this.setAnimation(c,b)},setAnimation:function(a,b){this.queue.length=0,this._setAnimation(a,b)},addAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;this.addAnimation(d,b,c)},addAnimation:function(a,b,c){var d={};if(d.animation=a,d.loop=b,!c||0>=c){var e=0==this.queue.length?this.current:this.queue[this.queue.length-1].animation;c=null!=e?e.duration-this.data.getMix(e,a)+(c||0):0}d.delay=c,this.queue.push(d)},isComplete:function(){return!this.current||this.currentTime>=this.current.duration}},n.SkeletonJson=function(a){this.attachmentLoader=a},n.SkeletonJson.prototype={scale:1,readSkeletonData:function(a){for(var b=new n.SkeletonData,c=a.bones,d=0,e=c.length;e>d;d++){var f=c[d],g=null;if(f.parent&&(g=b.findBone(f.parent),!g))throw"Parent bone not found: "+f.parent;var h=new n.BoneData(f.name,g);h.length=(f.length||0)*this.scale,h.x=(f.x||0)*this.scale,h.y=(f.y||0)*this.scale,h.rotation=f.rotation||0,h.scaleX=f.scaleX||1,h.scaleY=f.scaleY||1,b.bones.push(h)}for(var i=a.slots,d=0,e=i.length;e>d;d++){var j=i[d],h=b.findBone(j.bone);if(!h)throw"Slot bone not found: "+j.bone;var k=new n.SlotData(j.name,h),l=j.color;l&&(k.r=n.SkeletonJson.toColor(l,0),k.g=n.SkeletonJson.toColor(l,1),k.b=n.SkeletonJson.toColor(l,2),k.a=n.SkeletonJson.toColor(l,3)),k.attachmentName=j.attachment,b.slots.push(k)}var m=a.skins;for(var o in m)if(m.hasOwnProperty(o)){var p=m[o],q=new n.Skin(o);for(var r in p)if(p.hasOwnProperty(r)){var s=b.findSlotIndex(r),t=p[r];for(var u in t)if(t.hasOwnProperty(u)){var v=this.readAttachment(q,u,t[u]);null!=v&&q.addAttachment(s,u,v)}}b.skins.push(q),"default"==q.name&&(b.defaultSkin=q)}var w=a.animations;for(var x in w)w.hasOwnProperty(x)&&this.readAnimation(x,w[x],b);return b},readAttachment:function(a,b,c){b=c.name||b;var d=n.AttachmentType[c.type||"region"];if(d==n.AttachmentType.region){var e=new n.RegionAttachment;return e.x=(c.x||0)*this.scale,e.y=(c.y||0)*this.scale,e.scaleX=c.scaleX||1,e.scaleY=c.scaleY||1,e.rotation=c.rotation||0,e.width=(c.width||32)*this.scale,e.height=(c.height||32)*this.scale,e.updateOffset(),e.rendererObject={},e.rendererObject.name=b,e.rendererObject.scale={},e.rendererObject.scale.x=e.scaleX,e.rendererObject.scale.y=e.scaleY,e.rendererObject.rotation=-e.rotation*Math.PI/180,e +}throw"Unknown attachment type: "+d},readAnimation:function(a,b,c){var d=[],e=0,f=b.bones;for(var g in f)if(f.hasOwnProperty(g)){var h=c.findBoneIndex(g);if(-1==h)throw"Bone not found: "+g;var i=f[g];for(var j in i)if(i.hasOwnProperty(j)){var k=i[j];if("rotate"==j){var l=new n.RotateTimeline(k.length);l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m,q.time,q.angle),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[2*l.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var l,r=1;"scale"==j?l=new n.ScaleTimeline(k.length):(l=new n.TranslateTimeline(k.length),r=this.scale),l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;l.setFrame(m,q.time,s,t),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[3*l.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var l=new n.ColorTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=n.SkeletonJson.toColor(y,0),A=n.SkeletonJson.toColor(y,1),B=n.SkeletonJson.toColor(y,2),C=n.SkeletonJson.toColor(y,3);l.setFrame(m,q.time,z,A,B,C),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[5*l.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var l=new n.AttachmentTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m++,q.time,q.name)}d.push(l),e=Math.max(e,l.frames[l.getFrameCount()-1])}}}c.animations.push(new n.Animation(a,d,e))}},n.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},n.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},n.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new n.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new n.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new n.AtlasPage,e.name=f,e.format=n.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=n.Atlas.TextureFilter[d[0]],e.magFilter=n.Atlas.TextureFilter[d[1]];var l=c.readValue();e.uWrap=n.Atlas.TextureWrap.clampToEdge,e.vWrap=n.Atlas.TextureWrap.clampToEdge,"x"==l?e.uWrap=n.Atlas.TextureWrap.repeat:"y"==l?e.vWrap=n.Atlas.TextureWrap.repeat:"xy"==l&&(e.uWrap=e.vWrap=n.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},n.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},n.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},n.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},n.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},n.AtlasPage=function(){},n.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},n.AtlasRegion=function(){},n.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},n.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},n.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},n.AtlasAttachmentLoader=function(a){this.atlas=a},n.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case n.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new n.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},n.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;h + + + pixi.js example 14 - Masking + + + + + + + + + diff --git a/examples/example 14 - Masking/index.html b/examples/example 14 - Masking/index.html index 02eaa67..230cbe8 100644 --- a/examples/example 14 - Masking/index.html +++ b/examples/example 14 - Masking/index.html @@ -133,7 +133,7 @@ count += 0.1; thing.clear(); - thing.lineStyle(5, 0x16f1ff, 1); + thing.beginFill(0x8bc5ff, 0.4); thing.moveTo(-120 + Math.sin(count) * 20, -100 + Math.cos(count)* 20); thing.lineTo(120 + Math.cos(count) * 20, -100 + Math.sin(count)* 20); @@ -142,6 +142,9 @@ thing.lineTo(-120 + Math.sin(count) * 20, -100 + Math.cos(count)* 20); thing.rotation = count * 0.1; + //var mask1 = new PIXI.Graphics(); + + renderer.render(stage); requestAnimFrame( animate ); } diff --git a/examples/example 15 - Filters/indexAll.html b/examples/example 15 - Filters/indexAll.html index 9beeef7..1f12d67 100644 --- a/examples/example 15 - Filters/indexAll.html +++ b/examples/example 15 - Filters/indexAll.html @@ -32,7 +32,7 @@ var gui = new dat.GUI({ //height : 5 * 32 - 1, - width : 350 + //width : 350 }); var blurFilter = new PIXI.BlurFilter(); diff --git a/src/pixi/renderers/webgl/WebGLGraphics.js b/src/pixi/renderers/webgl/WebGLGraphics.js index b69dbc9..8e94fe7 100644 --- a/src/pixi/renderers/webgl/WebGLGraphics.js +++ b/src/pixi/renderers/webgl/WebGLGraphics.js @@ -80,6 +80,7 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) PIXI.deactivatePrimitiveShader(); + // return to default shader... // PIXI.activateShader(PIXI.defaultShader); } diff --git a/src/pixi/renderers/webgl/WebGLRenderGroup.js b/src/pixi/renderers/webgl/WebGLRenderGroup.js index 8c828df..b0d8d6c 100644 --- a/src/pixi/renderers/webgl/WebGLRenderGroup.js +++ b/src/pixi/renderers/webgl/WebGLRenderGroup.js @@ -284,6 +284,12 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) } } +flip = false; +var maskStack = []; +var maskPosition = 0; + +//var usedMaskStack = []; + PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(filterBlock, projection) { /* @@ -295,24 +301,27 @@ PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(filterBlock, projec { if(filterBlock.data instanceof Array) { - //var filter = filterBlock.data[0]; - //console.log(filter) - this.filterManager.pushFilter(filterBlock);//filter); + this.filterManager.pushFilter(filterBlock); // ok so.. } else - { - + { + maskPosition++; + + maskStack.push(filterBlock) + gl.enable(gl.STENCIL_TEST); - + gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); + + gl.stencilFunc(gl.ALWAYS,1,1); + gl.stencilOp(gl.KEEP,gl.KEEP,gl.INCR); + PIXI.WebGLGraphics.renderGraphics(filterBlock.data, projection); - + gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); + gl.stencilFunc(gl.NOTEQUAL,0,maskStack.length); gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); } } @@ -321,11 +330,26 @@ PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(filterBlock, projec if(filterBlock.data instanceof Array) { this.filterManager.popFilter(); - // PIXI.popShader(); - // gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); } else { + var maskData = maskStack.pop(filterBlock) + + + if(maskData) + { + gl.colorMask(false, false, false, false); + + gl.stencilFunc(gl.ALWAYS,1,1); + gl.stencilOp(gl.KEEP,gl.KEEP,gl.DECR); + + PIXI.WebGLGraphics.renderGraphics(maskData.data, projection); + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.NOTEQUAL,0,maskStack.length); + gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); + }; + gl.disable(gl.STENCIL_TEST); } } From 087aab16be38c36d7e35c868b26de5ddd57ca4b0 Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Sun, 3 Nov 2013 12:38:31 +0000 Subject: [PATCH 66/96] Line width now more accurate --- bin/pixi.dev.js | 10 ++++++++++ bin/pixi.dev.js.map | 2 +- bin/pixi.js | 2 +- src/pixi/renderers/webgl/WebGLGraphics.js | 9 +++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/bin/pixi.dev.js b/bin/pixi.dev.js index 3f77ac4..5f330ad 100644 --- a/bin/pixi.dev.js +++ b/bin/pixi.dev.js @@ -4321,6 +4321,14 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) var points = graphicsData.points; if(points.length == 0)return; + // if the line width is an odd number add 0.5 to align to a whole pixel + if(graphicsData.lineWidth%2) + { + for (var i = 0; i < points.length; i++) { + points[i] += 0.5; + }; + } + // get first and last point.. figure out the middle! var firstPoint = new PIXI.Point( points[0], points[1] ); var lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); @@ -4492,6 +4500,7 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) indices.push(indexStart++); }; + console.log(verts) indices.push(indexStart-1); } @@ -11651,6 +11660,7 @@ Object.defineProperty(PIXI.BlurXFilter.prototype, 'blur', { } }); +/** /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ diff --git a/bin/pixi.dev.js.map b/bin/pixi.dev.js.map index 9eb4a5a..e3ed3a5 100644 --- a/bin/pixi.dev.js.map +++ b/bin/pixi.dev.js.map @@ -65,6 +65,6 @@ "src/pixi/Outro.js" ], "names": [], - "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sB;AC5jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpgCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACpgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACn7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACpKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,c", + "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sB;AC5jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7gBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpgCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACpgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACn7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACpKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,c", "sourceRoot": "../" } \ No newline at end of file diff --git a/bin/pixi.js b/bin/pixi.js index de93a8f..d0b9eb6 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -10,7 +10,7 @@ * http://www.opensource.org/licenses/mit-license.php */ !function(){function c(){return f.Matrix="undefined"!=typeof Float32Array?Float32Array:Array,f.Matrix}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}var e=this,f=f||{};f.Point=function(a,b){this.x=a||0,this.y=b||0},f.Point.prototype.clone=function(){return new f.Point(this.x,this.y)},f.Point.prototype.constructor=f.Point,f.Rectangle=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Rectangle.prototype.clone=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Rectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},f.Rectangle.prototype.constructor=f.Rectangle,f.Polygon=function(a){if(a instanceof Array||(a=Array.prototype.slice.call(arguments)),"number"==typeof a[0]){for(var b=[],c=0,d=a.length;d>c;c+=2)b.push(new f.Point(a[c],a[c+1]));a=b}this.points=a},f.Polygon.prototype.clone=function(){for(var a=[],b=0;bb!=i>b&&(h-f)*(b-g)/(i-g)+f>a;j&&(c=!c)}return c},f.Polygon.prototype.constructor=f.Polygon,f.Circle=function(a,b,c){this.x=a||0,this.y=b||0,this.radius=c||0},f.Circle.prototype.clone=function(){return new f.Circle(this.x,this.y,this.radius)},f.Circle.prototype.contains=function(a,b){if(this.radius<=0)return!1;var c=this.x-a,d=this.y-b,e=this.radius*this.radius;return c*=c,d*=d,e>=c+d},f.Circle.prototype.constructor=f.Circle,f.Ellipse=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Ellipse.prototype.clone=function(){return new f.Ellipse(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=(a-this.x)/this.width-.5,d=(b-this.y)/this.height-.5;return c*=c,d*=d,.25>c+d},f.Ellipse.getBounds=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.constructor=f.Ellipse,c(),f.mat3={},f.mat3.create=function(){var a=new f.Matrix(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat3.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat4={},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat3.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=b[0],n=b[1],o=b[2],p=b[3],q=b[4],r=b[5],s=b[6],t=b[7],u=b[8];return c[0]=m*d+n*g+o*j,c[1]=m*e+n*h+o*k,c[2]=m*f+n*i+o*l,c[3]=p*d+q*g+r*j,c[4]=p*e+q*h+r*k,c[5]=p*f+q*i+r*l,c[6]=s*d+t*g+u*j,c[7]=s*e+t*h+u*k,c[8]=s*f+t*i+u*l,c},f.mat3.clone=function(a){var b=new f.Matrix(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},f.mat3.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[5];return a[1]=a[3],a[2]=a[6],a[3]=c,a[5]=a[7],a[6]=d,a[7]=e,a}return b[0]=a[0],b[1]=a[3],b[2]=a[6],b[3]=a[1],b[4]=a[4],b[5]=a[7],b[6]=a[2],b[7]=a[5],b[8]=a[8],b},f.mat3.toMat4=function(a,b){return b||(b=f.mat4.create()),b[15]=1,b[14]=0,b[13]=0,b[12]=0,b[11]=0,b[10]=a[8],b[9]=a[7],b[8]=a[6],b[7]=0,b[6]=a[5],b[5]=a[4],b[4]=a[3],b[3]=0,b[2]=a[2],b[1]=a[1],b[0]=a[0],b},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat4.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[3],f=a[6],g=a[7],h=a[11];return a[1]=a[4],a[2]=a[8],a[3]=a[12],a[4]=c,a[6]=a[9],a[7]=a[13],a[8]=d,a[9]=f,a[11]=a[14],a[12]=e,a[13]=g,a[14]=h,a}return b[0]=a[0],b[1]=a[4],b[2]=a[8],b[3]=a[12],b[4]=a[1],b[5]=a[5],b[6]=a[9],b[7]=a[13],b[8]=a[2],b[9]=a[6],b[10]=a[10],b[11]=a[14],b[12]=a[3],b[13]=a[7],b[14]=a[11],b[15]=a[15],b},f.mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=b[0],u=b[1],v=b[2],w=b[3];return c[0]=t*d+u*h+v*l+w*p,c[1]=t*e+u*i+v*m+w*q,c[2]=t*f+u*j+v*n+w*r,c[3]=t*g+u*k+v*o+w*s,t=b[4],u=b[5],v=b[6],w=b[7],c[4]=t*d+u*h+v*l+w*p,c[5]=t*e+u*i+v*m+w*q,c[6]=t*f+u*j+v*n+w*r,c[7]=t*g+u*k+v*o+w*s,t=b[8],u=b[9],v=b[10],w=b[11],c[8]=t*d+u*h+v*l+w*p,c[9]=t*e+u*i+v*m+w*q,c[10]=t*f+u*j+v*n+w*r,c[11]=t*g+u*k+v*o+w*s,t=b[12],u=b[13],v=b[14],w=b[15],c[12]=t*d+u*h+v*l+w*p,c[13]=t*e+u*i+v*m+w*q,c[14]=t*f+u*j+v*n+w*r,c[15]=t*g+u*k+v*o+w*s,c},f.DisplayObject=function(){this.last=this,this.first=this,this.position=new f.Point,this.scale=new f.Point(1,1),this.pivot=new f.Point(0,0),this.rotation=0,this.alpha=1,this.visible=!0,this.hitArea=null,this.buttonMode=!1,this.renderable=!1,this.parent=null,this.stage=null,this.worldAlpha=1,this._interactive=!1,this.worldTransform=f.mat3.create(),this.localTransform=f.mat3.create(),this.color=[],this.dynamic=!0,this._sr=0,this._cr=1,this.filterArea=new f.Rectangle(0,0,1,1)},f.DisplayObject.prototype.constructor=f.DisplayObject,f.DisplayObject.prototype.setInteractive=function(a){this.interactive=a},Object.defineProperty(f.DisplayObject.prototype,"interactive",{get:function(){return this._interactive},set:function(a){this._interactive=a,this.stage&&(this.stage.dirty=!0)}}),Object.defineProperty(f.DisplayObject.prototype,"mask",{get:function(){return this._mask},set:function(a){a?this._mask?(a.start=this._mask.start,a.end=this._mask.end):(this.addFilter(a),a.renderable=!1):(this.removeFilter(this._mask),this._mask.renderable=!0),this._mask=a}}),Object.defineProperty(f.DisplayObject.prototype,"filters",{get:function(){return this._filters},set:function(a){if(a){this._filters&&this.removeFilter(this._filters),this.addFilter(a);for(var b=[],c=0;c=0&&b<=this.children.length))throw new Error(a+" The index "+b+" supplied is out of bounds "+this.children.length);if(void 0!=a.parent&&a.parent.removeChild(a),a.parent=this,this.stage){var c=a;do c.interactive&&(this.stage.dirty=!0),c.stage=this.stage,c=c._iNext;while(c)}var d,e,f=a.first,g=a.last;if(b==this.children.length){e=this.last;for(var h=this,i=this.last;h;)h.last==i&&(h.last=a.last),h=h.parent}else e=0==b?this:this.children[b-1].last;d=e._iNext,d&&(d._iPrev=g,g._iNext=d),f._iPrev=e,e._iNext=f,this.children.splice(b,0,a),this.__renderGroup&&(a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a),this.__renderGroup.addDisplayObjectAndChildren(a))},f.DisplayObjectContainer.prototype.swapChildren=function(){},f.DisplayObjectContainer.prototype.getChildAt=function(a){if(a>=0&&aa;a++)this.children[a].updateTransform()}},f.blendModes={},f.blendModes.NORMAL=0,f.blendModes.SCREEN=1,f.Sprite=function(a){f.DisplayObjectContainer.call(this),this.anchor=new f.Point,this.texture=a,this.blendMode=f.blendModes.NORMAL,this._width=0,this._height=0,a.baseTexture.hasLoaded?this.updateFrame=!0:(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Sprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Sprite.prototype.constructor=f.Sprite,Object.defineProperty(f.Sprite.prototype,"width",{get:function(){return this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(f.Sprite.prototype,"height",{get:function(){return this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),f.Sprite.prototype.setTexture=function(a){this.texture.baseTexture!=a.baseTexture?(this.textureChange=!0,this.texture=a,this.__renderGroup&&this.__renderGroup.updateTexture(this)):this.texture=a,this.updateFrame=!0},f.Sprite.prototype.onTextureUpdate=function(){this._width&&(this.scale.x=this._width/this.texture.frame.width),this._height&&(this.scale.y=this._height/this.texture.frame.height),this.updateFrame=!0},f.Sprite.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache"+this);return new f.Sprite(b)},f.Sprite.fromImage=function(a){var b=f.Texture.fromImage(a);return new f.Sprite(b)},f.MovieClip=function(a){f.Sprite.call(this,a[0]),this.textures=a,this.animationSpeed=1,this.loop=!0,this.onComplete=null,this.currentFrame=0,this.playing=!1},f.MovieClip.prototype=Object.create(f.Sprite.prototype),f.MovieClip.prototype.constructor=f.MovieClip,Object.defineProperty(f.MovieClip.prototype,"totalFrames",{get:function(){return this.textures.length}}),f.MovieClip.prototype.stop=function(){this.playing=!1},f.MovieClip.prototype.play=function(){this.playing=!0},f.MovieClip.prototype.gotoAndStop=function(a){this.playing=!1,this.currentFrame=a;var b=0|this.currentFrame+.5;this.setTexture(this.textures[b%this.textures.length])},f.MovieClip.prototype.gotoAndPlay=function(a){this.currentFrame=a,this.playing=!0},f.MovieClip.prototype.updateTransform=function(){if(f.Sprite.prototype.updateTransform.call(this),this.playing){this.currentFrame+=this.animationSpeed;var a=0|this.currentFrame+.5;this.loop||a=this.textures.length&&(this.gotoAndStop(this.textures.length-1),this.onComplete&&this.onComplete())}},f.FilterBlock=function(){this.visible=!0,this.renderable=!0},f.Text=function(a,b){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),f.Sprite.call(this,f.Texture.fromCanvas(this.canvas)),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.Text.prototype=Object.create(f.Sprite.prototype),f.Text.prototype.constructor=f.Text,f.Text.prototype.setStyle=function(a){a=a||{},a.font=a.font||"bold 20pt Arial",a.fill=a.fill||"black",a.align=a.align||"left",a.stroke=a.stroke||"black",a.strokeThickness=a.strokeThickness||0,a.wordWrap=a.wordWrap||!1,a.wordWrapWidth=a.wordWrapWidth||100,this.style=a,this.dirty=!0},f.Text.prototype.setText=function(a){this.text=a.toString()||" ",this.dirty=!0},f.Text.prototype.updateText=function(){this.context.font=this.style.font;var a=this.text;this.style.wordWrap&&(a=this.wordWrap(this.text));for(var b=a.split(/(?:\r\n|\r|\n)/),c=[],d=0,e=0;ee?f:arguments.callee(a,b,f,d,e):arguments.callee(a,b,c,f,e)},c=function(a,c,d){if(a.measureText(c).width<=d||c.length<1)return c;var e=b(a,c,0,c.length,d);return c.substring(0,e)+"\n"+arguments.callee(a,c.substring(e),d)},d="",e=a.split("\n"),f=0;f=2?parseInt(b[b.length-2],10):f.BitmapText.fonts[this.fontName].size,this.dirty=!0},f.BitmapText.prototype.updateText=function(){for(var a=f.BitmapText.fonts[this.fontName],b=new f.Point,c=null,d=[],e=0,g=[],h=0,i=this.fontSize/a.size,j=0;j=j;j++){var n=0;"right"==this.style.align?n=e-g[j]:"center"==this.style.align&&(n=(e-g[j])/2),m.push(n)}for(j=0;j0;)this.removeChild(this.getChildAt(0));this.updateText(),this.dirty=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.BitmapText.fonts={},f.InteractionManager=function(a){this.stage=a,this.mouse=new f.InteractionData,this.touchs={},this.tempPoint=new f.Point,this.mouseoverEnabled=!0,this.pool=[],this.interactiveItems=[],this.interactionDOMElement=null,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseOut=this.onMouseOut.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.last=0},f.InteractionManager.prototype.constructor=f.InteractionManager,f.InteractionManager.prototype.collectInteractiveSprite=function(a,b){for(var c=a.children,d=c.length,e=d-1;e>=0;e--){var f=c[e];f.interactive?(b.interactiveChildren=!0,this.interactiveItems.push(f),f.children.length>0&&this.collectInteractiveSprite(f,f)):(f.__iParent=null,f.children.length>0&&this.collectInteractiveSprite(f,b))}},f.InteractionManager.prototype.setTarget=function(a){this.target=a,null===this.interactionDOMElement&&this.setTargetDomElement(a.view),document.body.addEventListener("mouseup",this.onMouseUp,!0)},f.InteractionManager.prototype.setTargetDomElement=function(a){null!==this.interactionDOMElement&&(this.interactionDOMElement.style["-ms-content-zooming"]="",this.interactionDOMElement.style["-ms-touch-action"]="",this.interactionDOMElement.removeEventListener("mousemove",this.onMouseMove,!0),this.interactionDOMElement.removeEventListener("mousedown",this.onMouseDown,!0),this.interactionDOMElement.removeEventListener("mouseout",this.onMouseOut,!0),this.interactionDOMElement.removeEventListener("touchstart",this.onTouchStart,!0),this.interactionDOMElement.removeEventListener("touchend",this.onTouchEnd,!0),this.interactionDOMElement.removeEventListener("touchmove",this.onTouchMove,!0)),window.navigator.msPointerEnabled&&(a.style["-ms-content-zooming"]="none",a.style["-ms-touch-action"]="none"),this.interactionDOMElement=a,a.addEventListener("mousemove",this.onMouseMove,!0),a.addEventListener("mousedown",this.onMouseDown,!0),a.addEventListener("mouseout",this.onMouseOut,!0),a.addEventListener("touchstart",this.onTouchStart,!0),a.addEventListener("touchend",this.onTouchEnd,!0),a.addEventListener("touchmove",this.onTouchMove,!0)},f.InteractionManager.prototype.update=function(){if(this.target){var a=Date.now(),b=a-this.last;if(b=30*b/1e3,!(1>b)){if(this.last=a,this.dirty){this.dirty=!1;for(var c=this.interactiveItems.length,d=0;c>d;d++)this.interactiveItems[d].interactiveChildren=!1;this.interactiveItems=[],this.stage.interactive&&this.interactiveItems.push(this.stage),this.collectInteractiveSprite(this.stage,this.stage)}var e=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var d=0;e>d;d++){var f=this.interactiveItems[d];(f.mouseover||f.mouseout||f.buttonMode)&&(f.__hit=this.hitTest(f,this.mouse),this.mouse.target=f,f.__hit?(f.buttonMode&&(this.interactionDOMElement.style.cursor="pointer"),f.__isOver||(f.mouseover&&f.mouseover(this.mouse),f.__isOver=!0)):f.__isOver&&(f.mouseout&&f.mouseout(this.mouse),f.__isOver=!1))}}}},f.InteractionManager.prototype.onMouseMove=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactionDOMElement.getBoundingClientRect();this.mouse.global.x=(a.clientX-b.left)*(this.target.width/b.width),this.mouse.global.y=(a.clientY-b.top)*(this.target.height/b.height);var c=this.interactiveItems.length;this.mouse.global;for(var d=0;c>d;d++){var e=this.interactiveItems[d];e.mousemove&&e.mousemove(this.mouse)}},f.InteractionManager.prototype.onMouseDown=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactiveItems.length;this.mouse.global,this.stage;for(var c=0;b>c;c++){var d=this.interactiveItems[c];if((d.mousedown||d.click)&&(d.__mouseIsDown=!0,d.__hit=this.hitTest(d,this.mouse),d.__hit&&(d.mousedown&&d.mousedown(this.mouse),d.__isDown=!0,!d.interactiveChildren)))break}},f.InteractionManager.prototype.onMouseOut=function(){var a=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var b=0;a>b;b++){var c=this.interactiveItems[b];c.__isOver&&(this.mouse.target=c,c.mouseout&&c.mouseout(this.mouse),c.__isOver=!1)}},f.InteractionManager.prototype.onMouseUp=function(a){this.mouse.originalEvent=a||window.event,this.mouse.global;for(var b=this.interactiveItems.length,c=!1,d=0;b>d;d++){var e=this.interactiveItems[d];(e.mouseup||e.mouseupoutside||e.click)&&(e.__hit=this.hitTest(e,this.mouse),e.__hit&&!c?(e.mouseup&&e.mouseup(this.mouse),e.__isDown&&e.click&&e.click(this.mouse),e.interactiveChildren||(c=!0)):e.__isDown&&e.mouseupoutside&&e.mouseupoutside(this.mouse),e.__isDown=!1)}},f.InteractionManager.prototype.hitTest=function(a,b){var c=b.global;if(a.vcount!==f.visibleCount)return!1;var d=a instanceof f.Sprite,e=a.worldTransform,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=1/(g*k+h*-j),n=k*m*c.x+-h*m*c.y+(l*h-i*k)*m,o=g*m*c.y+-j*m*c.x+(-l*g+i*j)*m;if(b.target=a,a.hitArea&&a.hitArea.contains)return a.hitArea.contains(n,o)?(b.target=a,!0):!1;if(d){var p,q=a.texture.frame.width,r=a.texture.frame.height,s=-q*a.anchor.x;if(n>s&&s+q>n&&(p=-r*a.anchor.y,o>p&&p+r>o))return b.target=a,!0}for(var t=a.children.length,u=0;t>u;u++){var v=a.children[u],w=this.hitTest(v,b);if(w)return b.target=a,!0}return!1},f.InteractionManager.prototype.onTouchMove=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;dd;d++){var h=this.interactiveItems[d];h.touchmove&&h.touchmove(f)}},f.InteractionManager.prototype.onTouchStart=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i];if((j.touchstart||j.tap)&&(j.__hit=this.hitTest(j,g),j.__hit&&(j.touchstart&&j.touchstart(g),j.__isDown=!0,j.__touchData=g,!j.interactiveChildren)))break}}},f.InteractionManager.prototype.onTouchEnd=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i],k=j.__touchData;j.__hit=this.hitTest(j,f),k==f&&(f.originalEvent=a||window.event,(j.touchend||j.tap)&&(j.__hit&&!g?(j.touchend&&j.touchend(f),j.__isDown&&j.tap&&j.tap(f),j.interactiveChildren||(g=!0)):j.__isDown&&j.touchendoutside&&j.touchendoutside(f),j.__isDown=!1),j.__touchData=null)}this.pool.push(f),this.touchs[e.identifier]=null}},f.InteractionData=function(){this.global=new f.Point,this.local=new f.Point,this.target,this.originalEvent},f.InteractionData.prototype.getLocalPosition=function(a){var b=a.worldTransform,c=this.global,d=b[0],e=b[1],g=b[2],h=b[3],i=b[4],j=b[5],k=1/(d*i+e*-h);return new f.Point(i*k*c.x+-e*k*c.y+(j*e-g*i)*k,d*k*c.y+-h*k*c.x+(-j*d+g*h)*k)},f.InteractionData.prototype.constructor=f.InteractionData,f.Stage=function(a){f.DisplayObjectContainer.call(this),this.worldTransform=f.mat3.create(),this.interactive=!0,this.interactionManager=new f.InteractionManager(this),this.dirty=!0,this.__childrenAdded=[],this.__childrenRemoved=[],this.stage=this,this.stage.hitArea=new f.Rectangle(0,0,1e5,1e5),this.setBackgroundColor(a),this.worldVisible=!0},f.Stage.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Stage.prototype.constructor=f.Stage,f.Stage.prototype.setInteractionDelegate=function(a){this.interactionManager.setTargetDomElement(a)},f.Stage.prototype.updateTransform=function(){this.worldAlpha=1,this.vcount=f.visibleCount;for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform();this.dirty&&(this.dirty=!1,this.interactionManager.dirty=!0),this.interactive&&this.interactionManager.update()},f.Stage.prototype.setBackgroundColor=function(a){this.backgroundColor=a||0,this.backgroundColorSplit=d(this.backgroundColor);var b=this.backgroundColor.toString(16);b="000000".substr(0,6-b.length)+b,this.backgroundColorString="#"+b},f.Stage.prototype.getMousePosition=function(){return this.interactionManager.mouse.global};for(var h=0,i=["ms","moz","webkit","o"],j=0;j>>>>>>>>"),console.log("_");var b=0,c=a.first;for(console.log(c);c._iNext;)if(b++,c=c._iNext,console.log(c),b>100){console.log("BREAK");break}},f.EventTarget=function(){var a={};this.addEventListener=this.on=function(b,c){void 0===a[b]&&(a[b]=[]),-1===a[b].indexOf(c)&&a[b].push(c)},this.dispatchEvent=this.emit=function(b){if(a[b.type]&&a[b.type].length)for(var c=0,d=a[b.type].length;d>c;c++)a[b.type][c](b)},this.removeEventListener=this.off=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)}},f.autoDetectRenderer=function(a,b,c,d,e){a||(a=800),b||(b=600);var g=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}();if(g){var h=-1!=navigator.userAgent.toLowerCase().indexOf("msie");g=!h}return g?new f.WebGLRenderer(a,b,c,d,e):new f.CanvasRenderer(a,b,c,d)},f.PolyK={},f.PolyK.Triangulate=function(a){var b=!0,c=a.length>>1;if(3>c)return[];for(var d=[],e=[],g=0;c>g;g++)e.push(g);for(var g=0,h=c;h>3;){var i=e[(g+0)%h],j=e[(g+1)%h],k=e[(g+2)%h],l=a[2*i],m=a[2*i+1],n=a[2*j],o=a[2*j+1],p=a[2*k],q=a[2*k+1],r=!1;if(f.PolyK._convex(l,m,n,o,p,q,b)){r=!0;for(var s=0;h>s;s++){var t=e[s];if(t!=i&&t!=j&&t!=k&&f.PolyK._PointInTriangle(a[2*t],a[2*t+1],l,m,n,o,p,q)){r=!1;break}}}if(r)d.push(i,j,k),e.splice((g+1)%h,1),h--,g=0;else if(g++>3*h){if(!b)return console.log("PIXI Warning: shape too complex to fill"),[];var d=[];e=[];for(var g=0;c>g;g++)e.push(g);g=0,h=c,b=!1}}return d.push(e[0],e[1],e[2]),d},f.PolyK._PointInTriangle=function(a,b,c,d,e,f,g,h){var i=g-c,j=h-d,k=e-c,l=f-d,m=a-c,n=b-d,o=i*i+j*j,p=i*k+j*l,q=i*m+j*n,r=k*k+l*l,s=k*m+l*n,t=1/(o*r-p*p),u=(r*q-p*s)*t,v=(o*s-p*q)*t;return u>=0&&v>=0&&1>u+v},f.PolyK._convex=function(a,b,c,d,e,f,g){return(b-d)*(e-c)+(c-a)*(f-d)>=0==g},f.initDefaultShaders=function(){f.primitiveShader=new f.PrimitiveShader,f.primitiveShader.init(),f.stripShader=new f.StripShader,f.stripShader.init(),f.defaultShader=new f.PixiShader,f.defaultShader.init();var a=f.gl,b=f.defaultShader.program;a.useProgram(b),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.primitiveShader.program),a.disableVertexAttribArray(f.defaultShader.aTextureCoord)},f.deactivatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activateStripShader=function(){var a=f.gl;a.useProgram(f.stripShader.program)},f.deactivateStripShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program)},f.CompileVertexShader=function(a,b){return f._CompileShader(a,b,a.VERTEX_SHADER)},f.CompileFragmentShader=function(a,b){return f._CompileShader(a,b,a.FRAGMENT_SHADER)},f._CompileShader=function(a,b,c){var d=b.join("\n"),e=a.createShader(c);return a.shaderSource(e,d),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)?e:(console.log(a.getShaderInfoLog(e)),null)},f.compileProgram=function(a,b){var c=f.gl,d=f.CompileFragmentShader(c,b),e=f.CompileVertexShader(c,a),g=c.createProgram();return c.attachShader(g,e),c.attachShader(g,d),c.linkProgram(g),c.getProgramParameter(g,c.LINK_STATUS)||console.log("Could not initialise shaders"),g},f.PixiShader=function(){this.program,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;","}"]},f.PixiShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc||f.PixiShader.defaultVertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"); -for(var c in this.uniforms)a[c]=b.getUniformLocation(a,c);this.program=a},f.PixiShader.prototype.syncUniforms=function(){var a=f.gl;for(var b in this.uniforms){var c=this.uniforms[b].type;if("f"==c&&a.uniform1f(this.program[b],this.uniforms[b].value),"f2"==c)a.uniform2f(this.program[b],this.uniforms[b].value.x,this.uniforms[b].value.y);else if("f4"==c)a.uniform4fv(this.program[b],this.uniforms[b].value);else if("mat4"==c)a.uniformMatrix4fv(this.program[b],!1,this.uniforms[b].value);else if("sampler2D"==c){var d=this.uniforms[b].value;a.activeTexture(a.TEXTURE1),a.bindTexture(a.TEXTURE_2D,d.baseTexture._glTexture),a.uniform1i(this.program[b],1)}}},f.PixiShader.defaultVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","varying float vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"],f.StripShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying float vColor;","uniform float alpha;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));","gl_FragColor = gl_FragColor * alpha;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","varying vec2 vTextureCoord;","varying vec2 offsetVector;","varying float vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"]},f.StripShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.PrimitiveShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","gl_FragColor = vColor;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec4 aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform float alpha;","varying vec4 vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","vColor = aColor * alpha;","}"]},f.PrimitiveShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.WebGLGraphics=function(){},f.WebGLGraphics.renderGraphics=function(a,b){var c=f.gl;a._webGL||(a._webGL={points:[],indices:[],lastIndex:0,buffer:c.createBuffer(),indexBuffer:c.createBuffer()}),a.dirty&&(a.dirty=!1,a.clearDirty&&(a.clearDirty=!1,a._webGL.lastIndex=0,a._webGL.points=[],a._webGL.indices=[]),f.WebGLGraphics.updateGraphics(a)),f.activatePrimitiveShader();var d=f.mat3.clone(a.worldTransform);f.mat3.transpose(d),c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA),c.uniformMatrix3fv(f.primitiveShader.translationMatrix,!1,d),c.uniform2f(f.primitiveShader.projectionVector,b.x,-b.y),c.uniform2f(f.primitiveShader.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(f.primitiveShader.alpha,a.worldAlpha),c.bindBuffer(c.ARRAY_BUFFER,a._webGL.buffer),c.vertexAttribPointer(f.primitiveShader.aVertexPosition,2,c.FLOAT,!1,24,0),c.vertexAttribPointer(f.primitiveShader.colorAttribute,4,c.FLOAT,!1,24,8),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),c.drawElements(c.TRIANGLE_STRIP,a._webGL.indices.length,c.UNSIGNED_SHORT,0),f.deactivatePrimitiveShader()},f.WebGLGraphics.updateGraphics=function(a){for(var b=a._webGL.lastIndex;b3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){var e=new f.Point(c[0],c[1]),g=new f.Point(c[c.length-2],c[c.length-1]);if(e.x==g.x&&e.y==g.y){c.pop(),c.pop(),g=new f.Point(c[c.length-2],c[c.length-1]);var h=g.x+.5*(e.x-g.x),i=g.y+.5*(e.y-g.y);c.unshift(h,i),c.push(h,i)}var j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E=b.points,F=b.indices,G=c.length/2,H=c.length,I=E.length/6,J=a.lineWidth/2,K=d(a.lineColor),L=a.lineAlpha,M=K[0]*L,N=K[1]*L,O=K[2]*L;j=c[0],k=c[1],l=c[2],m=c[3],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,E.push(j-p,k-q,M,N,O,L),E.push(j+p,k+q,M,N,O,L);for(var P=1;G-1>P;P++)j=c[2*(P-1)],k=c[2*(P-1)+1],l=c[2*P],m=c[2*P+1],n=c[2*(P+1)],o=c[2*(P+1)+1],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,r=-(m-o),s=l-n,D=Math.sqrt(r*r+s*s),r/=D,s/=D,r*=J,s*=J,v=-q+k-(-q+m),w=-p+l-(-p+j),x=(-p+j)*(-q+m)-(-p+l)*(-q+k),y=-s+o-(-s+m),z=-r+l-(-r+n),A=(-r+n)*(-s+m)-(-r+l)*(-s+o),B=v*z-y*w,0==B&&(B+=1),px=(w*A-z*x)/B,py=(y*x-v*A)/B,C=(px-l)*(px-l)+(py-m)+(py-m),C>19600?(t=p-r,u=q-s,D=Math.sqrt(t*t+u*u),t/=D,u/=D,t*=J,u*=J,E.push(l-t,m-u),E.push(M,N,O,L),E.push(l+t,m+u),E.push(M,N,O,L),E.push(l-t,m-u),E.push(M,N,O,L),H++):(E.push(px,py),E.push(M,N,O,L),E.push(l-(px-l),m-(py-m)),E.push(M,N,O,L));j=c[2*(G-2)],k=c[2*(G-2)+1],l=c[2*(G-1)],m=c[2*(G-1)+1],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,E.push(l-p,m-q),E.push(M,N,O,L),E.push(l+p,m+q),E.push(M,N,O,L),F.push(I);for(var P=0;H>P;P++)F.push(I++);F.push(I-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},flip=!1;var l=[],m=0;f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;if(a.open)a.data instanceof Array?this.filterManager.pushFilter(a):(m++,l.push(a),c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.INCR),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP));else if(a.data instanceof Array)this.filterManager.popFilter();else{var d=l.pop(a);d&&(c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.DECR),f.WebGLGraphics.renderGraphics(d.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)),c.disable(c.STENCIL_TEST)}},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(){this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;h3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){if(a.lineWidth%2)for(var e=0;ee;e++)k=c[2*(e-1)],l=c[2*(e-1)+1],m=c[2*e],n=c[2*e+1],o=c[2*(e+1)],p=c[2*(e+1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,s=-(n-p),t=m-o,E=Math.sqrt(s*s+t*t),s/=E,t/=E,s*=K,t*=K,w=-r+l-(-r+n),x=-q+m-(-q+k),y=(-q+k)*(-r+n)-(-q+m)*(-r+l),z=-t+p-(-t+n),A=-s+m-(-s+o),B=(-s+o)*(-t+n)-(-s+m)*(-t+p),C=w*A-z*x,0==C&&(C+=1),px=(x*B-A*y)/C,py=(z*y-w*B)/C,D=(px-m)*(px-m)+(py-n)+(py-n),D>19600?(u=q-s,v=r-t,E=Math.sqrt(u*u+v*v),u/=E,v/=E,u*=K,v*=K,F.push(m-u,n-v),F.push(N,O,P,M),F.push(m+u,n+v),F.push(N,O,P,M),F.push(m-u,n-v),F.push(N,O,P,M),I++):(F.push(px,py),F.push(N,O,P,M),F.push(m-(px-m),n-(py-n)),F.push(N,O,P,M));k=c[2*(H-2)],l=c[2*(H-2)+1],m=c[2*(H-1)],n=c[2*(H-1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,F.push(m-q,n-r),F.push(N,O,P,M),F.push(m+q,n+r),F.push(N,O,P,M),G.push(J);for(var e=0;I>e;e++)G.push(J++);console.log(F),G.push(J-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},flip=!1;var l=[],m=0;f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;if(a.open)a.data instanceof Array?this.filterManager.pushFilter(a):(m++,l.push(a),c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.INCR),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP));else if(a.data instanceof Array)this.filterManager.popFilter();else{var d=l.pop(a);d&&(c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.DECR),f.WebGLGraphics.renderGraphics(d.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)),c.disable(c.STENCIL_TEST)}},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(){this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;hs?s:E,E=E>t?t:E,E=E>u?u:E,E=E>v?v:E,F=F>w?w:F,F=F>x?x:F,F=F>y?y:F,F=F>z?z:F,C=s>C?s:C,C=t>C?t:C,C=u>C?u:C,C=v>C?v:C,D=w>D?w:D,D=x>D?x:D,D=y>D?y:D,D=z>D?z:D),l=!1,A=A._iNext}while(A!=B);a.filterArea.x=E,a.filterArea.y=F,a.filterArea.width=C-E,a.filterArea.height=D-F},f.FilterTexture=function(a,b){var c=f.gl;this.frameBuffer=c.createFramebuffer(),this.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,this.texture),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.bindFramebuffer(c.FRAMEBUFFER,this.framebuffer),c.bindFramebuffer(c.FRAMEBUFFER,this.frameBuffer),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,this.texture,0),this.resize(a,b)},f.FilterTexture.prototype.resize=function(a,b){this.width=a,this.height=b;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a,b,0,c.RGBA,c.UNSIGNED_BYTE,null)},f.CanvasRenderer=function(a,b,c,d){this.transparent=d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.context=this.view.getContext("2d"),this.refresh=!0,this.view.width=this.width,this.view.height=this.height,this.count=0},f.CanvasRenderer.prototype.constructor=f.CanvasRenderer,f.CanvasRenderer.prototype.render=function(a){f.texturesToUpdate=[],f.texturesToDestroy=[],f.visibleCount++,a.updateTransform(),this.view.style.backgroundColor==a.backgroundColorString||this.transparent||(this.view.style.backgroundColor=a.backgroundColorString),this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.width,this.height),this.renderDisplayObject(a),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0&&(f.Texture.frameUpdates=[])},f.CanvasRenderer.prototype.resize=function(a,b){this.width=a,this.height=b,this.view.width=a,this.view.height=b},f.CanvasRenderer.prototype.renderDisplayObject=function(a){var b,c=this.context;c.globalCompositeOperation="source-over";var d=a.last._iNext;a=a.first;do if(b=a.worldTransform,a.visible)if(a.renderable){if(a instanceof f.Sprite){var e=a.texture.frame;e&&e.width&&e.height&&(c.globalAlpha=a.worldAlpha,c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),c.drawImage(a.texture.baseTexture.source,e.x,e.y,e.width,e.height,a.anchor.x*-e.width,a.anchor.y*-e.height,e.width,e.height))}else if(a instanceof f.Strip)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderStrip(a);else if(a instanceof f.TilingSprite)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderTilingSprite(a);else if(a instanceof f.CustomRenderable)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),a.renderCanvas(this);else if(a instanceof f.Graphics)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),f.CanvasGraphics.renderGraphics(a,c);else if(a instanceof f.FilterBlock&&a.data instanceof f.Graphics){var g=a.data;if(a.open){c.save();var h=g.alpha,i=g.worldTransform;c.setTransform(i[0],i[3],i[1],i[4],i[2],i[5]),g.worldAlpha=.5,c.worldAlpha=0,f.CanvasGraphics.renderGraphicsMask(g,c),c.clip(),g.worldAlpha=h}else c.restore()}a=a._iNext}else a=a._iNext;else a=a.last._iNext;while(a!=d)},f.CanvasRenderer.prototype.renderStripFlat=function(a){var b=this.context,c=a.verticies;a.uvs;var d=c.length/2;this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},f.CanvasRenderer.prototype.renderTilingSprite=function(a){var b=this.context;b.globalAlpha=a.worldAlpha,a.__tilePattern||(a.__tilePattern=b.createPattern(a.texture.baseTexture.source,"repeat")),b.beginPath();var c=a.tilePosition,d=a.tileScale;b.scale(d.x,d.y),b.translate(c.x,c.y),b.fillStyle=a.__tilePattern,b.fillRect(-c.x,-c.y,a.width/d.x,a.height/d.y),b.scale(1/d.x,1/d.y),b.translate(-c.x,-c.y),b.closePath()},f.CanvasRenderer.prototype.renderStrip=function(a){var b=this.context,c=a.verticies,d=a.uvs,e=c.length/2;this.count++;for(var f=1;e-2>f;f++){var g=2*f,h=c[g],i=c[g+2],j=c[g+4],k=c[g+1],l=c[g+3],m=c[g+5],n=d[g]*a.texture.width,o=d[g+2]*a.texture.width,p=d[g+4]*a.texture.width,q=d[g+1]*a.texture.height,r=d[g+3]*a.texture.height,s=d[g+5]*a.texture.height;b.save(),b.beginPath(),b.moveTo(h,k),b.lineTo(i,l),b.lineTo(j,m),b.closePath(),b.clip();var t=n*r+q*p+o*s-r*p-q*o-n*s,u=h*r+q*j+i*s-r*j-q*i-h*s,v=n*i+h*p+o*j-i*p-h*o-n*j,w=n*r*j+q*i*p+h*o*s-h*r*p-q*o*j-n*i*s,x=k*r+q*m+l*s-r*m-q*l-k*s,y=n*l+k*p+o*m-l*p-k*o-n*m,z=n*r*m+q*l*p+k*o*s-k*r*p-q*o*m-n*l*s;b.transform(u/t,x/t,v/t,y/t,w/t,z/t),b.drawImage(a.texture.baseTexture.source,0,0),b.restore()}},f.CanvasGraphics=function(){},f.CanvasGraphics.renderGraphics=function(a,b){for(var c=a.worldAlpha,d=0;d1&&(c=1,console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var d=0;1>d;d++){var e=a.graphicsData[d],g=e.points;if(e.type==f.Graphics.POLY){b.beginPath(),b.moveTo(g[0],g[1]);for(var h=1;hb?b:d,e=b+m>e?b+m:e,g=g>c?b:g,h=c+n>h?c+n:h}else if(k===f.Graphics.CIRC||k===f.Graphics.ELIP){b=a.x,c=a.y;var o=a.radius+l/2;d=d>b-o?b-o:d,e=b+o>e?b+o:e,g=g>c-o?c-o:g,h=c+o>h?c+o:h}else for(var p=0;pb-l?b-l:d,e=b+l>e?b+l:e,g=g>c-l?c-l:g,h=c+l>h?c+l:h}this.bounds=new f.Rectangle(d,g,e-d,h-g)}},f.Graphics.POLY=0,f.Graphics.RECT=1,f.Graphics.CIRC=2,f.Graphics.ELIP=3,f.Strip=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.blendMode=f.blendModes.NORMAL;try{this.uvs=new Float32Array([0,1,1,1,1,0,0,1]),this.verticies=new Float32Array([0,0,0,0,0,0,0,0,0]),this.colors=new Float32Array([1,1,1,1]),this.indices=new Uint16Array([0,1,2,3])}catch(d){this.uvs=[0,1,1,1,1,0,0,1],this.verticies=[0,0,0,0,0,0,0,0,0],this.colors=[1,1,1,1],this.indices=[0,1,2,3]}this.width=b,this.height=c,a.baseTexture.hasLoaded?(this.width=this.texture.frame.width,this.height=this.texture.frame.height,this.updateFrame=!0):(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Strip.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Strip.prototype.constructor=f.Strip,f.Strip.prototype.setTexture=function(a){this.texture=a,this.width=a.frame.width,this.height=a.frame.height,this.updateFrame=!0},f.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Rope=function(a,b){f.Strip.call(this,a),this.points=b;try{this.verticies=new Float32Array(4*b.length),this.uvs=new Float32Array(4*b.length),this.colors=new Float32Array(2*b.length),this.indices=new Uint16Array(2*b.length)}catch(c){this.verticies=verticies,this.uvs=uvs,this.colors=colors,this.indices=indices}this.refresh()},f.Rope.prototype=Object.create(f.Strip.prototype),f.Rope.prototype.constructor=f.Rope,f.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=this.indices,d=this.colors,e=a[0],f=a[0];this.count-=.2,b[0]=0,b[1]=1,b[2]=0,b[3]=1,d[0]=1,d[1]=1,c[0]=0,c[1]=1;for(var g=a.length,h=1;g>h;h++){var f=a[h],i=4*h,j=h/(g-1);h%2?(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1):(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1),i=2*h,d[i]=1,d[i+1]=1,i=2*h,c[i]=i,c[i+1]=i+1,e=f}}},f.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var b,c=this.verticies,d=a[0],e={x:0,y:0},g=a[0];this.count-=.2,c[0]=g.x+e.x,c[1]=g.y+e.y,c[2]=g.x-e.x,c[3]=g.y-e.y;for(var h=a.length,i=1;h>i;i++){var g=a[i],j=4*i;b=i1&&(k=1);var l=Math.sqrt(e.x*e.x+e.y*e.y),m=this.texture.height/2;e.x/=l,e.y/=l,e.x*=m,e.y*=m,c[j]=g.x+e.x,c[j+1]=g.y+e.y,c[j+2]=g.x-e.x,c[j+3]=g.y-e.y,d=g}f.DisplayObjectContainer.prototype.updateTransform.call(this)}},f.Rope.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.width=b,this.height=c,this.tileScale=new f.Point(1,1),this.tilePosition=new f.Point(0,0),this.renderable=!0,this.blendMode=f.blendModes.NORMAL},f.TilingSprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.TilingSprite.prototype.constructor=f.TilingSprite,f.TilingSprite.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Spine=function(a){if(f.DisplayObjectContainer.call(this),this.spineData=f.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new n.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new n.AnimationStateData(this.spineData),this.state=new n.AnimationState(this.stateData),this.slotContainers=[];for(var b=0,c=this.skeleton.drawOrder.length;c>b;b++){var d=this.skeleton.drawOrder[b],e=d.attachment,g=new f.DisplayObjectContainer;if(this.slotContainers.push(g),this.addChild(g),e instanceof n.RegionAttachment){var h=e.rendererObject.name,i=this.createSprite(d,e.rendererObject);d.currentSprite=i,d.currentSpriteName=h,g.addChild(i)}}},f.Spine.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Spine.prototype.constructor=f.Spine,f.Spine.prototype.updateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var b=this.skeleton.drawOrder,c=0,d=b.length;d>c;c++){var e=b[c],g=e.attachment,h=this.slotContainers[c];if(g instanceof n.RegionAttachment){if(g.rendererObject&&(!e.currentSpriteName||e.currentSpriteName!=g.name)){var i=g.rendererObject.name;if(void 0!==e.currentSprite&&(e.currentSprite.visible=!1),e.sprites=e.sprites||{},void 0!==e.sprites[i])e.sprites[i].visible=!0;else{var j=this.createSprite(e,g.rendererObject);h.addChild(j)}e.currentSprite=e.sprites[i],e.currentSpriteName=i}h.visible=!0;var k=e.bone;h.position.x=k.worldX+g.x*k.m00+g.y*k.m01,h.position.y=k.worldY+g.x*k.m10+g.y*k.m11,h.scale.x=k.worldScaleX,h.scale.y=k.worldScaleY,h.rotation=-(e.bone.worldRotation*Math.PI/180)}else h.visible=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.Spine.prototype.createSprite=function(a,b){var c=f.TextureCache[b.name]?b.name:b.name+".png",d=new f.Sprite(f.Texture.fromFrame(c));return d.scale=b.scale,d.rotation=b.rotation,d.anchor.x=d.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[b.name]=d,d};var n={};n.BoneData=function(a,b){this.name=a,this.parent=b},n.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1},n.SlotData=function(a,b){this.name=a,this.boneData=b},n.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null},n.Bone=function(a,b){this.data=a,this.parent=b,this.setToSetupPose()},n.Bone.yDown=!1,n.Bone.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,updateWorldTransform:function(a,b){var c=this.parent;null!=c?(this.worldX=this.x*c.m00+this.y*c.m01+c.worldX,this.worldY=this.x*c.m10+this.y*c.m11+c.worldY,this.worldScaleX=c.worldScaleX*this.scaleX,this.worldScaleY=c.worldScaleY*this.scaleY,this.worldRotation=c.worldRotation+this.rotation):(this.worldX=this.x,this.worldY=this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotation);var d=this.worldRotation*Math.PI/180,e=Math.cos(d),f=Math.sin(d);this.m00=e*this.worldScaleX,this.m10=f*this.worldScaleX,this.m01=-f*this.worldScaleY,this.m11=e*this.worldScaleY,a&&(this.m00=-this.m00,this.m01=-this.m01),b&&(this.m10=-this.m10,this.m11=-this.m11),n.Bone.yDown&&(this.m10=-this.m10,this.m11=-this.m11)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY}},n.Slot=function(a,b,c){this.data=a,this.skeleton=b,this.bone=c,this.setToSetupPose()},n.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,setAttachment:function(a){this.attachment=a,this._attachmentTime=this.skeleton.time},setAttachmentTime:function(a){this._attachmentTime=this.skeleton.time-a},getAttachmentTime:function(){return this.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},n.Skin=function(a){this.name=a,this.attachments={}},n.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},n.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},n.Animation.prototype={apply:function(a,b,c){c&&0!=this.duration&&(b%=this.duration);for(var d=this.timelines,e=0,f=d.length;f>e;e++)d[e].apply(a,b,1)},mix:function(a,b,c,d){c&&0!=this.duration&&(b%=this.duration);for(var e=this.timelines,f=0,g=e.length;g>f;f++)e[f].apply(a,b,d)}},n.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(0==e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},n.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},n.Curves=function(a){this.curves=[],this.curves.length=6*(a-1)},n.Curves.prototype={setLinear:function(a){this.curves[6*a]=0},setStepped:function(a){this.curves[6*a]=-1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=6*a,r=this.curves;r[q]=b*i+m*j+o*h,r[q+1]=c*i+n*j+p*h,r[q+2]=m*k+o*l,r[q+3]=n*k+p*l,r[q+4]=o*l,r[q+5]=p*l},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=6*a,d=this.curves,e=d[c];if(!e)return b;if(-1==e)return 0;for(var f=d[c+1],g=d[c+2],h=d[c+3],i=d[c+4],j=d[c+5],k=e,l=f,m=8;;){if(k>=b){var n=k-e,o=l-f;return o+(l-o)*(b-n)/(k-n)}if(0==m)break;m--,e+=g,f+=h,g+=i,h+=j,k+=e,l+=f}return l+(1-l)*(b-k)/(1-k)}},n.RotateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=2*a},n.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-2]){for(var f=e.data.rotation+d[d.length-1]-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;return e.rotation+=f*c,void 0}var g=n.binarySearch(d,b,2),h=d[g-1],i=d[g],j=1-(b-i)/(d[g-2]-i);j=this.curves.getCurvePercent(g/2-1,j);for(var f=d[g+1]-h;f>180;)f-=360;for(;-180>f;)f+=360;for(f=e.data.rotation+(h+f*j)-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;e.rotation+=f*c}}},n.TranslateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.x+=(e.data.x+d[d.length-2]-e.x)*c,e.y+=(e.data.y+d[d.length-1]-e.y)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.x+=(e.data.x+g+(d[f+1]-g)*j-e.x)*c,e.y+=(e.data.y+h+(d[f+2]-h)*j-e.y)*c}}},n.ScaleTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.scaleX+=(e.data.scaleX-1+d[d.length-2]-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+d[d.length-1]-e.scaleY)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.scaleX+=(e.data.scaleX-1+g+(d[f+1]-g)*j-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+h+(d[f+2]-h)*j-e.scaleY)*c}}},n.ColorTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=5*a},n.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(c,d){c*=5,this.frames[c]=d,this.frames[c+1]=r,this.frames[c+2]=g,this.frames[c+3]=b,this.frames[c+4]=a},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-5]){var f=d.length-1;return e.r=d[f-3],e.g=d[f-2],e.b=d[f-1],e.a=d[f],void 0}var g=n.binarySearch(d,b,5),h=d[g-4],i=d[g-3],j=d[g-2],k=d[g-1],l=d[g],m=1-(b-l)/(d[g-5]-l);m=this.curves.getCurvePercent(g/5-1,m);var o=h+(d[g+1]-h)*m,p=i+(d[g+2]-i)*m,q=j+(d[g+3]-j)*m,r=k+(d[g+4]-k)*m;1>c?(e.r+=(o-e.r)*c,e.g+=(p-e.g)*c,e.b+=(q-e.b)*c,e.a+=(r-e.a)*c):(e.r=o,e.g=p,e.b=q,e.a=r)}}},n.AttachmentTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},n.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b){var c=this.frames;if(!(b=c[c.length-1]?c.length-1:n.binarySearch(c,b,1)-1;var e=this.attachmentNames[d];a.slots[this.slotIndex].setAttachment(e?a.getAttachmentBySlotIndex(this.slotIndex,e):null)}}},n.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.animations=[]},n.SkeletonData.prototype={defaultSkin:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},n.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,c=a.bones.length;c>b;b++){var d=a.bones[b],e=d.parent?this.bones[a.bones.indexOf(d.parent)]:null;this.bones.push(new n.Bone(d,e))}this.slots=[],this.drawOrder=[];for(var b=0,c=a.slots.length;c>b;b++){var f=a.slots[b],g=this.bones[a.bones.indexOf(f.boneData)],h=new n.Slot(f,this,g);this.slots.push(h),this.drawOrder.push(h)}},n.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateWorldTransform:function(){for(var a=this.flipX,b=this.flipY,c=this.bones,d=0,e=c.length;e>d;d++)c[d].updateWorldTransform(a,b)},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose()},setSlotsToSetupPose:function(){for(var a=this.slots,b=0,c=a.length;c>b;b++)a[b].setToSetupPose(b)},getRootBone:function(){return 0==this.bones.length?null:this.bones[0]},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a);if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){this.skin&&a&&a._attachAll(this,this.skin),this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.size;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachment(d,b),null==g))throw"Attachment not found: "+b+", for slot: "+a;return f.setAttachment(g),void 0}}throw"Slot not found: "+a},update:function(a){time+=a}},n.AttachmentType={region:0},n.RegionAttachment=function(){this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},n.RegionAttachment.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,c=-this.width/2*this.scaleX+this.regionOffsetX*a,d=-this.height/2*this.scaleY+this.regionOffsetY*b,e=c+this.regionWidth*a,f=d+this.regionHeight*b,g=this.rotation*Math.PI/180,h=Math.cos(g),i=Math.sin(g),j=c*h+this.x,k=c*i,l=d*h+this.y,m=d*i,n=e*h+this.x,o=e*i,p=f*h+this.y,q=f*i,r=this.offset;r[0]=j-m,r[1]=l+k,r[2]=j-q,r[3]=p+k,r[4]=n-q,r[5]=p+o,r[6]=n-m,r[7]=l+o},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},n.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},n.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=this.animationToMixTime[a.name+":"+b.name];return c?c:this.defaultMix}},n.AnimationState=function(a){this.data=a,this.queue=[]},n.AnimationState.prototype={current:null,previous:null,currentTime:0,previousTime:0,currentLoop:!1,previousLoop:!1,mixTime:0,mixDuration:0,update:function(a){if(this.currentTime+=a,this.previousTime+=a,this.mixTime+=a,this.queue.length>0){var b=this.queue[0];this.currentTime>=b.delay&&(this._setAnimation(b.animation,b.loop),this.queue.shift())}},apply:function(a){if(this.current)if(this.previous){this.previous.apply(a,this.previousTime,this.previousLoop);var b=this.mixTime/this.mixDuration;b>=1&&(b=1,this.previous=null),this.current.mix(a,this.currentTime,this.currentLoop,b)}else this.current.apply(a,this.currentTime,this.currentLoop)},clearAnimation:function(){this.previous=null,this.current=null,this.queue.length=0},_setAnimation:function(a,b){this.previous=null,a&&this.current&&(this.mixDuration=this.data.getMix(this.current,a),this.mixDuration>0&&(this.mixTime=0,this.previous=this.current,this.previousTime=this.currentTime,this.previousLoop=this.currentLoop)),this.current=a,this.currentLoop=b,this.currentTime=0},setAnimationByName:function(a,b){var c=this.data.skeletonData.findAnimation(a);if(!c)throw"Animation not found: "+a;this.setAnimation(c,b)},setAnimation:function(a,b){this.queue.length=0,this._setAnimation(a,b)},addAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;this.addAnimation(d,b,c)},addAnimation:function(a,b,c){var d={};if(d.animation=a,d.loop=b,!c||0>=c){var e=0==this.queue.length?this.current:this.queue[this.queue.length-1].animation;c=null!=e?e.duration-this.data.getMix(e,a)+(c||0):0}d.delay=c,this.queue.push(d)},isComplete:function(){return!this.current||this.currentTime>=this.current.duration}},n.SkeletonJson=function(a){this.attachmentLoader=a},n.SkeletonJson.prototype={scale:1,readSkeletonData:function(a){for(var b=new n.SkeletonData,c=a.bones,d=0,e=c.length;e>d;d++){var f=c[d],g=null;if(f.parent&&(g=b.findBone(f.parent),!g))throw"Parent bone not found: "+f.parent;var h=new n.BoneData(f.name,g);h.length=(f.length||0)*this.scale,h.x=(f.x||0)*this.scale,h.y=(f.y||0)*this.scale,h.rotation=f.rotation||0,h.scaleX=f.scaleX||1,h.scaleY=f.scaleY||1,b.bones.push(h)}for(var i=a.slots,d=0,e=i.length;e>d;d++){var j=i[d],h=b.findBone(j.bone);if(!h)throw"Slot bone not found: "+j.bone;var k=new n.SlotData(j.name,h),l=j.color;l&&(k.r=n.SkeletonJson.toColor(l,0),k.g=n.SkeletonJson.toColor(l,1),k.b=n.SkeletonJson.toColor(l,2),k.a=n.SkeletonJson.toColor(l,3)),k.attachmentName=j.attachment,b.slots.push(k)}var m=a.skins;for(var o in m)if(m.hasOwnProperty(o)){var p=m[o],q=new n.Skin(o);for(var r in p)if(p.hasOwnProperty(r)){var s=b.findSlotIndex(r),t=p[r];for(var u in t)if(t.hasOwnProperty(u)){var v=this.readAttachment(q,u,t[u]);null!=v&&q.addAttachment(s,u,v)}}b.skins.push(q),"default"==q.name&&(b.defaultSkin=q)}var w=a.animations;for(var x in w)w.hasOwnProperty(x)&&this.readAnimation(x,w[x],b);return b},readAttachment:function(a,b,c){b=c.name||b;var d=n.AttachmentType[c.type||"region"];if(d==n.AttachmentType.region){var e=new n.RegionAttachment;return e.x=(c.x||0)*this.scale,e.y=(c.y||0)*this.scale,e.scaleX=c.scaleX||1,e.scaleY=c.scaleY||1,e.rotation=c.rotation||0,e.width=(c.width||32)*this.scale,e.height=(c.height||32)*this.scale,e.updateOffset(),e.rendererObject={},e.rendererObject.name=b,e.rendererObject.scale={},e.rendererObject.scale.x=e.scaleX,e.rendererObject.scale.y=e.scaleY,e.rendererObject.rotation=-e.rotation*Math.PI/180,e }throw"Unknown attachment type: "+d},readAnimation:function(a,b,c){var d=[],e=0,f=b.bones;for(var g in f)if(f.hasOwnProperty(g)){var h=c.findBoneIndex(g);if(-1==h)throw"Bone not found: "+g;var i=f[g];for(var j in i)if(i.hasOwnProperty(j)){var k=i[j];if("rotate"==j){var l=new n.RotateTimeline(k.length);l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m,q.time,q.angle),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[2*l.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var l,r=1;"scale"==j?l=new n.ScaleTimeline(k.length):(l=new n.TranslateTimeline(k.length),r=this.scale),l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;l.setFrame(m,q.time,s,t),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[3*l.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var l=new n.ColorTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=n.SkeletonJson.toColor(y,0),A=n.SkeletonJson.toColor(y,1),B=n.SkeletonJson.toColor(y,2),C=n.SkeletonJson.toColor(y,3);l.setFrame(m,q.time,z,A,B,C),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[5*l.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var l=new n.AttachmentTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m++,q.time,q.name)}d.push(l),e=Math.max(e,l.frames[l.getFrameCount()-1])}}}c.animations.push(new n.Animation(a,d,e))}},n.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},n.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},n.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new n.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new n.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new n.AtlasPage,e.name=f,e.format=n.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=n.Atlas.TextureFilter[d[0]],e.magFilter=n.Atlas.TextureFilter[d[1]];var l=c.readValue();e.uWrap=n.Atlas.TextureWrap.clampToEdge,e.vWrap=n.Atlas.TextureWrap.clampToEdge,"x"==l?e.uWrap=n.Atlas.TextureWrap.repeat:"y"==l?e.vWrap=n.Atlas.TextureWrap.repeat:"xy"==l&&(e.uWrap=e.vWrap=n.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},n.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},n.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},n.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},n.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},n.AtlasPage=function(){},n.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},n.AtlasRegion=function(){},n.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},n.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},n.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},n.AtlasAttachmentLoader=function(a){this.atlas=a},n.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case n.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new n.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},n.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;h Date: Sun, 3 Nov 2013 12:43:17 +0000 Subject: [PATCH 67/96] Removed rogue console.log --- bin/pixi.dev.js | 16 ++++++++++++---- bin/pixi.js | 2 +- src/pixi/renderers/webgl/WebGLGraphics.js | 1 - 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/bin/pixi.dev.js b/bin/pixi.dev.js index 5f330ad..4583636 100644 --- a/bin/pixi.dev.js +++ b/bin/pixi.dev.js @@ -1,3 +1,14 @@ +/** + * @license + * Pixi.JS - v1.3.0 + * Copyright (c) 2012, Mat Groves + * http://goodboydigital.com/ + * + * Compiled: 2013-11-03 + * + * Pixi.JS is licensed under the MIT License. + * http://www.opensource.org/licenses/mit-license.php + */ /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -4500,7 +4511,6 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) indices.push(indexStart++); }; - console.log(verts) indices.push(indexStart-1); } @@ -11660,7 +11670,6 @@ Object.defineProperty(PIXI.BlurXFilter.prototype, 'blur', { } }); -/** /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -12150,5 +12159,4 @@ Object.defineProperty(PIXI.DotScreenFilter.prototype, 'angle', { } else { root.PIXI = PIXI; } -}).call(this); -//@ sourceMappingURL=pixi.dev.js.map \ No newline at end of file +}).call(this); \ No newline at end of file diff --git a/bin/pixi.js b/bin/pixi.js index d0b9eb6..e09a415 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -10,7 +10,7 @@ * http://www.opensource.org/licenses/mit-license.php */ !function(){function c(){return f.Matrix="undefined"!=typeof Float32Array?Float32Array:Array,f.Matrix}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}var e=this,f=f||{};f.Point=function(a,b){this.x=a||0,this.y=b||0},f.Point.prototype.clone=function(){return new f.Point(this.x,this.y)},f.Point.prototype.constructor=f.Point,f.Rectangle=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Rectangle.prototype.clone=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Rectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},f.Rectangle.prototype.constructor=f.Rectangle,f.Polygon=function(a){if(a instanceof Array||(a=Array.prototype.slice.call(arguments)),"number"==typeof a[0]){for(var b=[],c=0,d=a.length;d>c;c+=2)b.push(new f.Point(a[c],a[c+1]));a=b}this.points=a},f.Polygon.prototype.clone=function(){for(var a=[],b=0;bb!=i>b&&(h-f)*(b-g)/(i-g)+f>a;j&&(c=!c)}return c},f.Polygon.prototype.constructor=f.Polygon,f.Circle=function(a,b,c){this.x=a||0,this.y=b||0,this.radius=c||0},f.Circle.prototype.clone=function(){return new f.Circle(this.x,this.y,this.radius)},f.Circle.prototype.contains=function(a,b){if(this.radius<=0)return!1;var c=this.x-a,d=this.y-b,e=this.radius*this.radius;return c*=c,d*=d,e>=c+d},f.Circle.prototype.constructor=f.Circle,f.Ellipse=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Ellipse.prototype.clone=function(){return new f.Ellipse(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=(a-this.x)/this.width-.5,d=(b-this.y)/this.height-.5;return c*=c,d*=d,.25>c+d},f.Ellipse.getBounds=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.constructor=f.Ellipse,c(),f.mat3={},f.mat3.create=function(){var a=new f.Matrix(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat3.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat4={},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat3.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=b[0],n=b[1],o=b[2],p=b[3],q=b[4],r=b[5],s=b[6],t=b[7],u=b[8];return c[0]=m*d+n*g+o*j,c[1]=m*e+n*h+o*k,c[2]=m*f+n*i+o*l,c[3]=p*d+q*g+r*j,c[4]=p*e+q*h+r*k,c[5]=p*f+q*i+r*l,c[6]=s*d+t*g+u*j,c[7]=s*e+t*h+u*k,c[8]=s*f+t*i+u*l,c},f.mat3.clone=function(a){var b=new f.Matrix(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},f.mat3.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[5];return a[1]=a[3],a[2]=a[6],a[3]=c,a[5]=a[7],a[6]=d,a[7]=e,a}return b[0]=a[0],b[1]=a[3],b[2]=a[6],b[3]=a[1],b[4]=a[4],b[5]=a[7],b[6]=a[2],b[7]=a[5],b[8]=a[8],b},f.mat3.toMat4=function(a,b){return b||(b=f.mat4.create()),b[15]=1,b[14]=0,b[13]=0,b[12]=0,b[11]=0,b[10]=a[8],b[9]=a[7],b[8]=a[6],b[7]=0,b[6]=a[5],b[5]=a[4],b[4]=a[3],b[3]=0,b[2]=a[2],b[1]=a[1],b[0]=a[0],b},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat4.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[3],f=a[6],g=a[7],h=a[11];return a[1]=a[4],a[2]=a[8],a[3]=a[12],a[4]=c,a[6]=a[9],a[7]=a[13],a[8]=d,a[9]=f,a[11]=a[14],a[12]=e,a[13]=g,a[14]=h,a}return b[0]=a[0],b[1]=a[4],b[2]=a[8],b[3]=a[12],b[4]=a[1],b[5]=a[5],b[6]=a[9],b[7]=a[13],b[8]=a[2],b[9]=a[6],b[10]=a[10],b[11]=a[14],b[12]=a[3],b[13]=a[7],b[14]=a[11],b[15]=a[15],b},f.mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=b[0],u=b[1],v=b[2],w=b[3];return c[0]=t*d+u*h+v*l+w*p,c[1]=t*e+u*i+v*m+w*q,c[2]=t*f+u*j+v*n+w*r,c[3]=t*g+u*k+v*o+w*s,t=b[4],u=b[5],v=b[6],w=b[7],c[4]=t*d+u*h+v*l+w*p,c[5]=t*e+u*i+v*m+w*q,c[6]=t*f+u*j+v*n+w*r,c[7]=t*g+u*k+v*o+w*s,t=b[8],u=b[9],v=b[10],w=b[11],c[8]=t*d+u*h+v*l+w*p,c[9]=t*e+u*i+v*m+w*q,c[10]=t*f+u*j+v*n+w*r,c[11]=t*g+u*k+v*o+w*s,t=b[12],u=b[13],v=b[14],w=b[15],c[12]=t*d+u*h+v*l+w*p,c[13]=t*e+u*i+v*m+w*q,c[14]=t*f+u*j+v*n+w*r,c[15]=t*g+u*k+v*o+w*s,c},f.DisplayObject=function(){this.last=this,this.first=this,this.position=new f.Point,this.scale=new f.Point(1,1),this.pivot=new f.Point(0,0),this.rotation=0,this.alpha=1,this.visible=!0,this.hitArea=null,this.buttonMode=!1,this.renderable=!1,this.parent=null,this.stage=null,this.worldAlpha=1,this._interactive=!1,this.worldTransform=f.mat3.create(),this.localTransform=f.mat3.create(),this.color=[],this.dynamic=!0,this._sr=0,this._cr=1,this.filterArea=new f.Rectangle(0,0,1,1)},f.DisplayObject.prototype.constructor=f.DisplayObject,f.DisplayObject.prototype.setInteractive=function(a){this.interactive=a},Object.defineProperty(f.DisplayObject.prototype,"interactive",{get:function(){return this._interactive},set:function(a){this._interactive=a,this.stage&&(this.stage.dirty=!0)}}),Object.defineProperty(f.DisplayObject.prototype,"mask",{get:function(){return this._mask},set:function(a){a?this._mask?(a.start=this._mask.start,a.end=this._mask.end):(this.addFilter(a),a.renderable=!1):(this.removeFilter(this._mask),this._mask.renderable=!0),this._mask=a}}),Object.defineProperty(f.DisplayObject.prototype,"filters",{get:function(){return this._filters},set:function(a){if(a){this._filters&&this.removeFilter(this._filters),this.addFilter(a);for(var b=[],c=0;c=0&&b<=this.children.length))throw new Error(a+" The index "+b+" supplied is out of bounds "+this.children.length);if(void 0!=a.parent&&a.parent.removeChild(a),a.parent=this,this.stage){var c=a;do c.interactive&&(this.stage.dirty=!0),c.stage=this.stage,c=c._iNext;while(c)}var d,e,f=a.first,g=a.last;if(b==this.children.length){e=this.last;for(var h=this,i=this.last;h;)h.last==i&&(h.last=a.last),h=h.parent}else e=0==b?this:this.children[b-1].last;d=e._iNext,d&&(d._iPrev=g,g._iNext=d),f._iPrev=e,e._iNext=f,this.children.splice(b,0,a),this.__renderGroup&&(a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a),this.__renderGroup.addDisplayObjectAndChildren(a))},f.DisplayObjectContainer.prototype.swapChildren=function(){},f.DisplayObjectContainer.prototype.getChildAt=function(a){if(a>=0&&aa;a++)this.children[a].updateTransform()}},f.blendModes={},f.blendModes.NORMAL=0,f.blendModes.SCREEN=1,f.Sprite=function(a){f.DisplayObjectContainer.call(this),this.anchor=new f.Point,this.texture=a,this.blendMode=f.blendModes.NORMAL,this._width=0,this._height=0,a.baseTexture.hasLoaded?this.updateFrame=!0:(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Sprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Sprite.prototype.constructor=f.Sprite,Object.defineProperty(f.Sprite.prototype,"width",{get:function(){return this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(f.Sprite.prototype,"height",{get:function(){return this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),f.Sprite.prototype.setTexture=function(a){this.texture.baseTexture!=a.baseTexture?(this.textureChange=!0,this.texture=a,this.__renderGroup&&this.__renderGroup.updateTexture(this)):this.texture=a,this.updateFrame=!0},f.Sprite.prototype.onTextureUpdate=function(){this._width&&(this.scale.x=this._width/this.texture.frame.width),this._height&&(this.scale.y=this._height/this.texture.frame.height),this.updateFrame=!0},f.Sprite.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache"+this);return new f.Sprite(b)},f.Sprite.fromImage=function(a){var b=f.Texture.fromImage(a);return new f.Sprite(b)},f.MovieClip=function(a){f.Sprite.call(this,a[0]),this.textures=a,this.animationSpeed=1,this.loop=!0,this.onComplete=null,this.currentFrame=0,this.playing=!1},f.MovieClip.prototype=Object.create(f.Sprite.prototype),f.MovieClip.prototype.constructor=f.MovieClip,Object.defineProperty(f.MovieClip.prototype,"totalFrames",{get:function(){return this.textures.length}}),f.MovieClip.prototype.stop=function(){this.playing=!1},f.MovieClip.prototype.play=function(){this.playing=!0},f.MovieClip.prototype.gotoAndStop=function(a){this.playing=!1,this.currentFrame=a;var b=0|this.currentFrame+.5;this.setTexture(this.textures[b%this.textures.length])},f.MovieClip.prototype.gotoAndPlay=function(a){this.currentFrame=a,this.playing=!0},f.MovieClip.prototype.updateTransform=function(){if(f.Sprite.prototype.updateTransform.call(this),this.playing){this.currentFrame+=this.animationSpeed;var a=0|this.currentFrame+.5;this.loop||a=this.textures.length&&(this.gotoAndStop(this.textures.length-1),this.onComplete&&this.onComplete())}},f.FilterBlock=function(){this.visible=!0,this.renderable=!0},f.Text=function(a,b){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),f.Sprite.call(this,f.Texture.fromCanvas(this.canvas)),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.Text.prototype=Object.create(f.Sprite.prototype),f.Text.prototype.constructor=f.Text,f.Text.prototype.setStyle=function(a){a=a||{},a.font=a.font||"bold 20pt Arial",a.fill=a.fill||"black",a.align=a.align||"left",a.stroke=a.stroke||"black",a.strokeThickness=a.strokeThickness||0,a.wordWrap=a.wordWrap||!1,a.wordWrapWidth=a.wordWrapWidth||100,this.style=a,this.dirty=!0},f.Text.prototype.setText=function(a){this.text=a.toString()||" ",this.dirty=!0},f.Text.prototype.updateText=function(){this.context.font=this.style.font;var a=this.text;this.style.wordWrap&&(a=this.wordWrap(this.text));for(var b=a.split(/(?:\r\n|\r|\n)/),c=[],d=0,e=0;ee?f:arguments.callee(a,b,f,d,e):arguments.callee(a,b,c,f,e)},c=function(a,c,d){if(a.measureText(c).width<=d||c.length<1)return c;var e=b(a,c,0,c.length,d);return c.substring(0,e)+"\n"+arguments.callee(a,c.substring(e),d)},d="",e=a.split("\n"),f=0;f=2?parseInt(b[b.length-2],10):f.BitmapText.fonts[this.fontName].size,this.dirty=!0},f.BitmapText.prototype.updateText=function(){for(var a=f.BitmapText.fonts[this.fontName],b=new f.Point,c=null,d=[],e=0,g=[],h=0,i=this.fontSize/a.size,j=0;j=j;j++){var n=0;"right"==this.style.align?n=e-g[j]:"center"==this.style.align&&(n=(e-g[j])/2),m.push(n)}for(j=0;j0;)this.removeChild(this.getChildAt(0));this.updateText(),this.dirty=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.BitmapText.fonts={},f.InteractionManager=function(a){this.stage=a,this.mouse=new f.InteractionData,this.touchs={},this.tempPoint=new f.Point,this.mouseoverEnabled=!0,this.pool=[],this.interactiveItems=[],this.interactionDOMElement=null,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseOut=this.onMouseOut.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.last=0},f.InteractionManager.prototype.constructor=f.InteractionManager,f.InteractionManager.prototype.collectInteractiveSprite=function(a,b){for(var c=a.children,d=c.length,e=d-1;e>=0;e--){var f=c[e];f.interactive?(b.interactiveChildren=!0,this.interactiveItems.push(f),f.children.length>0&&this.collectInteractiveSprite(f,f)):(f.__iParent=null,f.children.length>0&&this.collectInteractiveSprite(f,b))}},f.InteractionManager.prototype.setTarget=function(a){this.target=a,null===this.interactionDOMElement&&this.setTargetDomElement(a.view),document.body.addEventListener("mouseup",this.onMouseUp,!0)},f.InteractionManager.prototype.setTargetDomElement=function(a){null!==this.interactionDOMElement&&(this.interactionDOMElement.style["-ms-content-zooming"]="",this.interactionDOMElement.style["-ms-touch-action"]="",this.interactionDOMElement.removeEventListener("mousemove",this.onMouseMove,!0),this.interactionDOMElement.removeEventListener("mousedown",this.onMouseDown,!0),this.interactionDOMElement.removeEventListener("mouseout",this.onMouseOut,!0),this.interactionDOMElement.removeEventListener("touchstart",this.onTouchStart,!0),this.interactionDOMElement.removeEventListener("touchend",this.onTouchEnd,!0),this.interactionDOMElement.removeEventListener("touchmove",this.onTouchMove,!0)),window.navigator.msPointerEnabled&&(a.style["-ms-content-zooming"]="none",a.style["-ms-touch-action"]="none"),this.interactionDOMElement=a,a.addEventListener("mousemove",this.onMouseMove,!0),a.addEventListener("mousedown",this.onMouseDown,!0),a.addEventListener("mouseout",this.onMouseOut,!0),a.addEventListener("touchstart",this.onTouchStart,!0),a.addEventListener("touchend",this.onTouchEnd,!0),a.addEventListener("touchmove",this.onTouchMove,!0)},f.InteractionManager.prototype.update=function(){if(this.target){var a=Date.now(),b=a-this.last;if(b=30*b/1e3,!(1>b)){if(this.last=a,this.dirty){this.dirty=!1;for(var c=this.interactiveItems.length,d=0;c>d;d++)this.interactiveItems[d].interactiveChildren=!1;this.interactiveItems=[],this.stage.interactive&&this.interactiveItems.push(this.stage),this.collectInteractiveSprite(this.stage,this.stage)}var e=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var d=0;e>d;d++){var f=this.interactiveItems[d];(f.mouseover||f.mouseout||f.buttonMode)&&(f.__hit=this.hitTest(f,this.mouse),this.mouse.target=f,f.__hit?(f.buttonMode&&(this.interactionDOMElement.style.cursor="pointer"),f.__isOver||(f.mouseover&&f.mouseover(this.mouse),f.__isOver=!0)):f.__isOver&&(f.mouseout&&f.mouseout(this.mouse),f.__isOver=!1))}}}},f.InteractionManager.prototype.onMouseMove=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactionDOMElement.getBoundingClientRect();this.mouse.global.x=(a.clientX-b.left)*(this.target.width/b.width),this.mouse.global.y=(a.clientY-b.top)*(this.target.height/b.height);var c=this.interactiveItems.length;this.mouse.global;for(var d=0;c>d;d++){var e=this.interactiveItems[d];e.mousemove&&e.mousemove(this.mouse)}},f.InteractionManager.prototype.onMouseDown=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactiveItems.length;this.mouse.global,this.stage;for(var c=0;b>c;c++){var d=this.interactiveItems[c];if((d.mousedown||d.click)&&(d.__mouseIsDown=!0,d.__hit=this.hitTest(d,this.mouse),d.__hit&&(d.mousedown&&d.mousedown(this.mouse),d.__isDown=!0,!d.interactiveChildren)))break}},f.InteractionManager.prototype.onMouseOut=function(){var a=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var b=0;a>b;b++){var c=this.interactiveItems[b];c.__isOver&&(this.mouse.target=c,c.mouseout&&c.mouseout(this.mouse),c.__isOver=!1)}},f.InteractionManager.prototype.onMouseUp=function(a){this.mouse.originalEvent=a||window.event,this.mouse.global;for(var b=this.interactiveItems.length,c=!1,d=0;b>d;d++){var e=this.interactiveItems[d];(e.mouseup||e.mouseupoutside||e.click)&&(e.__hit=this.hitTest(e,this.mouse),e.__hit&&!c?(e.mouseup&&e.mouseup(this.mouse),e.__isDown&&e.click&&e.click(this.mouse),e.interactiveChildren||(c=!0)):e.__isDown&&e.mouseupoutside&&e.mouseupoutside(this.mouse),e.__isDown=!1)}},f.InteractionManager.prototype.hitTest=function(a,b){var c=b.global;if(a.vcount!==f.visibleCount)return!1;var d=a instanceof f.Sprite,e=a.worldTransform,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=1/(g*k+h*-j),n=k*m*c.x+-h*m*c.y+(l*h-i*k)*m,o=g*m*c.y+-j*m*c.x+(-l*g+i*j)*m;if(b.target=a,a.hitArea&&a.hitArea.contains)return a.hitArea.contains(n,o)?(b.target=a,!0):!1;if(d){var p,q=a.texture.frame.width,r=a.texture.frame.height,s=-q*a.anchor.x;if(n>s&&s+q>n&&(p=-r*a.anchor.y,o>p&&p+r>o))return b.target=a,!0}for(var t=a.children.length,u=0;t>u;u++){var v=a.children[u],w=this.hitTest(v,b);if(w)return b.target=a,!0}return!1},f.InteractionManager.prototype.onTouchMove=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;dd;d++){var h=this.interactiveItems[d];h.touchmove&&h.touchmove(f)}},f.InteractionManager.prototype.onTouchStart=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i];if((j.touchstart||j.tap)&&(j.__hit=this.hitTest(j,g),j.__hit&&(j.touchstart&&j.touchstart(g),j.__isDown=!0,j.__touchData=g,!j.interactiveChildren)))break}}},f.InteractionManager.prototype.onTouchEnd=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i],k=j.__touchData;j.__hit=this.hitTest(j,f),k==f&&(f.originalEvent=a||window.event,(j.touchend||j.tap)&&(j.__hit&&!g?(j.touchend&&j.touchend(f),j.__isDown&&j.tap&&j.tap(f),j.interactiveChildren||(g=!0)):j.__isDown&&j.touchendoutside&&j.touchendoutside(f),j.__isDown=!1),j.__touchData=null)}this.pool.push(f),this.touchs[e.identifier]=null}},f.InteractionData=function(){this.global=new f.Point,this.local=new f.Point,this.target,this.originalEvent},f.InteractionData.prototype.getLocalPosition=function(a){var b=a.worldTransform,c=this.global,d=b[0],e=b[1],g=b[2],h=b[3],i=b[4],j=b[5],k=1/(d*i+e*-h);return new f.Point(i*k*c.x+-e*k*c.y+(j*e-g*i)*k,d*k*c.y+-h*k*c.x+(-j*d+g*h)*k)},f.InteractionData.prototype.constructor=f.InteractionData,f.Stage=function(a){f.DisplayObjectContainer.call(this),this.worldTransform=f.mat3.create(),this.interactive=!0,this.interactionManager=new f.InteractionManager(this),this.dirty=!0,this.__childrenAdded=[],this.__childrenRemoved=[],this.stage=this,this.stage.hitArea=new f.Rectangle(0,0,1e5,1e5),this.setBackgroundColor(a),this.worldVisible=!0},f.Stage.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Stage.prototype.constructor=f.Stage,f.Stage.prototype.setInteractionDelegate=function(a){this.interactionManager.setTargetDomElement(a)},f.Stage.prototype.updateTransform=function(){this.worldAlpha=1,this.vcount=f.visibleCount;for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform();this.dirty&&(this.dirty=!1,this.interactionManager.dirty=!0),this.interactive&&this.interactionManager.update()},f.Stage.prototype.setBackgroundColor=function(a){this.backgroundColor=a||0,this.backgroundColorSplit=d(this.backgroundColor);var b=this.backgroundColor.toString(16);b="000000".substr(0,6-b.length)+b,this.backgroundColorString="#"+b},f.Stage.prototype.getMousePosition=function(){return this.interactionManager.mouse.global};for(var h=0,i=["ms","moz","webkit","o"],j=0;j>>>>>>>>"),console.log("_");var b=0,c=a.first;for(console.log(c);c._iNext;)if(b++,c=c._iNext,console.log(c),b>100){console.log("BREAK");break}},f.EventTarget=function(){var a={};this.addEventListener=this.on=function(b,c){void 0===a[b]&&(a[b]=[]),-1===a[b].indexOf(c)&&a[b].push(c)},this.dispatchEvent=this.emit=function(b){if(a[b.type]&&a[b.type].length)for(var c=0,d=a[b.type].length;d>c;c++)a[b.type][c](b)},this.removeEventListener=this.off=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)}},f.autoDetectRenderer=function(a,b,c,d,e){a||(a=800),b||(b=600);var g=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}();if(g){var h=-1!=navigator.userAgent.toLowerCase().indexOf("msie");g=!h}return g?new f.WebGLRenderer(a,b,c,d,e):new f.CanvasRenderer(a,b,c,d)},f.PolyK={},f.PolyK.Triangulate=function(a){var b=!0,c=a.length>>1;if(3>c)return[];for(var d=[],e=[],g=0;c>g;g++)e.push(g);for(var g=0,h=c;h>3;){var i=e[(g+0)%h],j=e[(g+1)%h],k=e[(g+2)%h],l=a[2*i],m=a[2*i+1],n=a[2*j],o=a[2*j+1],p=a[2*k],q=a[2*k+1],r=!1;if(f.PolyK._convex(l,m,n,o,p,q,b)){r=!0;for(var s=0;h>s;s++){var t=e[s];if(t!=i&&t!=j&&t!=k&&f.PolyK._PointInTriangle(a[2*t],a[2*t+1],l,m,n,o,p,q)){r=!1;break}}}if(r)d.push(i,j,k),e.splice((g+1)%h,1),h--,g=0;else if(g++>3*h){if(!b)return console.log("PIXI Warning: shape too complex to fill"),[];var d=[];e=[];for(var g=0;c>g;g++)e.push(g);g=0,h=c,b=!1}}return d.push(e[0],e[1],e[2]),d},f.PolyK._PointInTriangle=function(a,b,c,d,e,f,g,h){var i=g-c,j=h-d,k=e-c,l=f-d,m=a-c,n=b-d,o=i*i+j*j,p=i*k+j*l,q=i*m+j*n,r=k*k+l*l,s=k*m+l*n,t=1/(o*r-p*p),u=(r*q-p*s)*t,v=(o*s-p*q)*t;return u>=0&&v>=0&&1>u+v},f.PolyK._convex=function(a,b,c,d,e,f,g){return(b-d)*(e-c)+(c-a)*(f-d)>=0==g},f.initDefaultShaders=function(){f.primitiveShader=new f.PrimitiveShader,f.primitiveShader.init(),f.stripShader=new f.StripShader,f.stripShader.init(),f.defaultShader=new f.PixiShader,f.defaultShader.init();var a=f.gl,b=f.defaultShader.program;a.useProgram(b),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.primitiveShader.program),a.disableVertexAttribArray(f.defaultShader.aTextureCoord)},f.deactivatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activateStripShader=function(){var a=f.gl;a.useProgram(f.stripShader.program)},f.deactivateStripShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program)},f.CompileVertexShader=function(a,b){return f._CompileShader(a,b,a.VERTEX_SHADER)},f.CompileFragmentShader=function(a,b){return f._CompileShader(a,b,a.FRAGMENT_SHADER)},f._CompileShader=function(a,b,c){var d=b.join("\n"),e=a.createShader(c);return a.shaderSource(e,d),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)?e:(console.log(a.getShaderInfoLog(e)),null)},f.compileProgram=function(a,b){var c=f.gl,d=f.CompileFragmentShader(c,b),e=f.CompileVertexShader(c,a),g=c.createProgram();return c.attachShader(g,e),c.attachShader(g,d),c.linkProgram(g),c.getProgramParameter(g,c.LINK_STATUS)||console.log("Could not initialise shaders"),g},f.PixiShader=function(){this.program,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;","}"]},f.PixiShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc||f.PixiShader.defaultVertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"); -for(var c in this.uniforms)a[c]=b.getUniformLocation(a,c);this.program=a},f.PixiShader.prototype.syncUniforms=function(){var a=f.gl;for(var b in this.uniforms){var c=this.uniforms[b].type;if("f"==c&&a.uniform1f(this.program[b],this.uniforms[b].value),"f2"==c)a.uniform2f(this.program[b],this.uniforms[b].value.x,this.uniforms[b].value.y);else if("f4"==c)a.uniform4fv(this.program[b],this.uniforms[b].value);else if("mat4"==c)a.uniformMatrix4fv(this.program[b],!1,this.uniforms[b].value);else if("sampler2D"==c){var d=this.uniforms[b].value;a.activeTexture(a.TEXTURE1),a.bindTexture(a.TEXTURE_2D,d.baseTexture._glTexture),a.uniform1i(this.program[b],1)}}},f.PixiShader.defaultVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","varying float vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"],f.StripShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying float vColor;","uniform float alpha;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));","gl_FragColor = gl_FragColor * alpha;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","varying vec2 vTextureCoord;","varying vec2 offsetVector;","varying float vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"]},f.StripShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.PrimitiveShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","gl_FragColor = vColor;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec4 aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform float alpha;","varying vec4 vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","vColor = aColor * alpha;","}"]},f.PrimitiveShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.WebGLGraphics=function(){},f.WebGLGraphics.renderGraphics=function(a,b){var c=f.gl;a._webGL||(a._webGL={points:[],indices:[],lastIndex:0,buffer:c.createBuffer(),indexBuffer:c.createBuffer()}),a.dirty&&(a.dirty=!1,a.clearDirty&&(a.clearDirty=!1,a._webGL.lastIndex=0,a._webGL.points=[],a._webGL.indices=[]),f.WebGLGraphics.updateGraphics(a)),f.activatePrimitiveShader();var d=f.mat3.clone(a.worldTransform);f.mat3.transpose(d),c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA),c.uniformMatrix3fv(f.primitiveShader.translationMatrix,!1,d),c.uniform2f(f.primitiveShader.projectionVector,b.x,-b.y),c.uniform2f(f.primitiveShader.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(f.primitiveShader.alpha,a.worldAlpha),c.bindBuffer(c.ARRAY_BUFFER,a._webGL.buffer),c.vertexAttribPointer(f.primitiveShader.aVertexPosition,2,c.FLOAT,!1,24,0),c.vertexAttribPointer(f.primitiveShader.colorAttribute,4,c.FLOAT,!1,24,8),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),c.drawElements(c.TRIANGLE_STRIP,a._webGL.indices.length,c.UNSIGNED_SHORT,0),f.deactivatePrimitiveShader()},f.WebGLGraphics.updateGraphics=function(a){for(var b=a._webGL.lastIndex;b3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){if(a.lineWidth%2)for(var e=0;ee;e++)k=c[2*(e-1)],l=c[2*(e-1)+1],m=c[2*e],n=c[2*e+1],o=c[2*(e+1)],p=c[2*(e+1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,s=-(n-p),t=m-o,E=Math.sqrt(s*s+t*t),s/=E,t/=E,s*=K,t*=K,w=-r+l-(-r+n),x=-q+m-(-q+k),y=(-q+k)*(-r+n)-(-q+m)*(-r+l),z=-t+p-(-t+n),A=-s+m-(-s+o),B=(-s+o)*(-t+n)-(-s+m)*(-t+p),C=w*A-z*x,0==C&&(C+=1),px=(x*B-A*y)/C,py=(z*y-w*B)/C,D=(px-m)*(px-m)+(py-n)+(py-n),D>19600?(u=q-s,v=r-t,E=Math.sqrt(u*u+v*v),u/=E,v/=E,u*=K,v*=K,F.push(m-u,n-v),F.push(N,O,P,M),F.push(m+u,n+v),F.push(N,O,P,M),F.push(m-u,n-v),F.push(N,O,P,M),I++):(F.push(px,py),F.push(N,O,P,M),F.push(m-(px-m),n-(py-n)),F.push(N,O,P,M));k=c[2*(H-2)],l=c[2*(H-2)+1],m=c[2*(H-1)],n=c[2*(H-1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,F.push(m-q,n-r),F.push(N,O,P,M),F.push(m+q,n+r),F.push(N,O,P,M),G.push(J);for(var e=0;I>e;e++)G.push(J++);console.log(F),G.push(J-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},flip=!1;var l=[],m=0;f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;if(a.open)a.data instanceof Array?this.filterManager.pushFilter(a):(m++,l.push(a),c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.INCR),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP));else if(a.data instanceof Array)this.filterManager.popFilter();else{var d=l.pop(a);d&&(c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.DECR),f.WebGLGraphics.renderGraphics(d.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)),c.disable(c.STENCIL_TEST)}},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(){this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;h3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){if(a.lineWidth%2)for(var e=0;ee;e++)k=c[2*(e-1)],l=c[2*(e-1)+1],m=c[2*e],n=c[2*e+1],o=c[2*(e+1)],p=c[2*(e+1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,s=-(n-p),t=m-o,E=Math.sqrt(s*s+t*t),s/=E,t/=E,s*=K,t*=K,w=-r+l-(-r+n),x=-q+m-(-q+k),y=(-q+k)*(-r+n)-(-q+m)*(-r+l),z=-t+p-(-t+n),A=-s+m-(-s+o),B=(-s+o)*(-t+n)-(-s+m)*(-t+p),C=w*A-z*x,0==C&&(C+=1),px=(x*B-A*y)/C,py=(z*y-w*B)/C,D=(px-m)*(px-m)+(py-n)+(py-n),D>19600?(u=q-s,v=r-t,E=Math.sqrt(u*u+v*v),u/=E,v/=E,u*=K,v*=K,F.push(m-u,n-v),F.push(N,O,P,M),F.push(m+u,n+v),F.push(N,O,P,M),F.push(m-u,n-v),F.push(N,O,P,M),I++):(F.push(px,py),F.push(N,O,P,M),F.push(m-(px-m),n-(py-n)),F.push(N,O,P,M));k=c[2*(H-2)],l=c[2*(H-2)+1],m=c[2*(H-1)],n=c[2*(H-1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,F.push(m-q,n-r),F.push(N,O,P,M),F.push(m+q,n+r),F.push(N,O,P,M),G.push(J);for(var e=0;I>e;e++)G.push(J++);G.push(J-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},flip=!1;var l=[],m=0;f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;if(a.open)a.data instanceof Array?this.filterManager.pushFilter(a):(m++,l.push(a),c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.INCR),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP));else if(a.data instanceof Array)this.filterManager.popFilter();else{var d=l.pop(a);d&&(c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.DECR),f.WebGLGraphics.renderGraphics(d.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)),c.disable(c.STENCIL_TEST)}},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(){this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;hs?s:E,E=E>t?t:E,E=E>u?u:E,E=E>v?v:E,F=F>w?w:F,F=F>x?x:F,F=F>y?y:F,F=F>z?z:F,C=s>C?s:C,C=t>C?t:C,C=u>C?u:C,C=v>C?v:C,D=w>D?w:D,D=x>D?x:D,D=y>D?y:D,D=z>D?z:D),l=!1,A=A._iNext}while(A!=B);a.filterArea.x=E,a.filterArea.y=F,a.filterArea.width=C-E,a.filterArea.height=D-F},f.FilterTexture=function(a,b){var c=f.gl;this.frameBuffer=c.createFramebuffer(),this.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,this.texture),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.bindFramebuffer(c.FRAMEBUFFER,this.framebuffer),c.bindFramebuffer(c.FRAMEBUFFER,this.frameBuffer),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,this.texture,0),this.resize(a,b)},f.FilterTexture.prototype.resize=function(a,b){this.width=a,this.height=b;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a,b,0,c.RGBA,c.UNSIGNED_BYTE,null)},f.CanvasRenderer=function(a,b,c,d){this.transparent=d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.context=this.view.getContext("2d"),this.refresh=!0,this.view.width=this.width,this.view.height=this.height,this.count=0},f.CanvasRenderer.prototype.constructor=f.CanvasRenderer,f.CanvasRenderer.prototype.render=function(a){f.texturesToUpdate=[],f.texturesToDestroy=[],f.visibleCount++,a.updateTransform(),this.view.style.backgroundColor==a.backgroundColorString||this.transparent||(this.view.style.backgroundColor=a.backgroundColorString),this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.width,this.height),this.renderDisplayObject(a),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0&&(f.Texture.frameUpdates=[])},f.CanvasRenderer.prototype.resize=function(a,b){this.width=a,this.height=b,this.view.width=a,this.view.height=b},f.CanvasRenderer.prototype.renderDisplayObject=function(a){var b,c=this.context;c.globalCompositeOperation="source-over";var d=a.last._iNext;a=a.first;do if(b=a.worldTransform,a.visible)if(a.renderable){if(a instanceof f.Sprite){var e=a.texture.frame;e&&e.width&&e.height&&(c.globalAlpha=a.worldAlpha,c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),c.drawImage(a.texture.baseTexture.source,e.x,e.y,e.width,e.height,a.anchor.x*-e.width,a.anchor.y*-e.height,e.width,e.height))}else if(a instanceof f.Strip)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderStrip(a);else if(a instanceof f.TilingSprite)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderTilingSprite(a);else if(a instanceof f.CustomRenderable)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),a.renderCanvas(this);else if(a instanceof f.Graphics)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),f.CanvasGraphics.renderGraphics(a,c);else if(a instanceof f.FilterBlock&&a.data instanceof f.Graphics){var g=a.data;if(a.open){c.save();var h=g.alpha,i=g.worldTransform;c.setTransform(i[0],i[3],i[1],i[4],i[2],i[5]),g.worldAlpha=.5,c.worldAlpha=0,f.CanvasGraphics.renderGraphicsMask(g,c),c.clip(),g.worldAlpha=h}else c.restore()}a=a._iNext}else a=a._iNext;else a=a.last._iNext;while(a!=d)},f.CanvasRenderer.prototype.renderStripFlat=function(a){var b=this.context,c=a.verticies;a.uvs;var d=c.length/2;this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},f.CanvasRenderer.prototype.renderTilingSprite=function(a){var b=this.context;b.globalAlpha=a.worldAlpha,a.__tilePattern||(a.__tilePattern=b.createPattern(a.texture.baseTexture.source,"repeat")),b.beginPath();var c=a.tilePosition,d=a.tileScale;b.scale(d.x,d.y),b.translate(c.x,c.y),b.fillStyle=a.__tilePattern,b.fillRect(-c.x,-c.y,a.width/d.x,a.height/d.y),b.scale(1/d.x,1/d.y),b.translate(-c.x,-c.y),b.closePath()},f.CanvasRenderer.prototype.renderStrip=function(a){var b=this.context,c=a.verticies,d=a.uvs,e=c.length/2;this.count++;for(var f=1;e-2>f;f++){var g=2*f,h=c[g],i=c[g+2],j=c[g+4],k=c[g+1],l=c[g+3],m=c[g+5],n=d[g]*a.texture.width,o=d[g+2]*a.texture.width,p=d[g+4]*a.texture.width,q=d[g+1]*a.texture.height,r=d[g+3]*a.texture.height,s=d[g+5]*a.texture.height;b.save(),b.beginPath(),b.moveTo(h,k),b.lineTo(i,l),b.lineTo(j,m),b.closePath(),b.clip();var t=n*r+q*p+o*s-r*p-q*o-n*s,u=h*r+q*j+i*s-r*j-q*i-h*s,v=n*i+h*p+o*j-i*p-h*o-n*j,w=n*r*j+q*i*p+h*o*s-h*r*p-q*o*j-n*i*s,x=k*r+q*m+l*s-r*m-q*l-k*s,y=n*l+k*p+o*m-l*p-k*o-n*m,z=n*r*m+q*l*p+k*o*s-k*r*p-q*o*m-n*l*s;b.transform(u/t,x/t,v/t,y/t,w/t,z/t),b.drawImage(a.texture.baseTexture.source,0,0),b.restore()}},f.CanvasGraphics=function(){},f.CanvasGraphics.renderGraphics=function(a,b){for(var c=a.worldAlpha,d=0;d1&&(c=1,console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var d=0;1>d;d++){var e=a.graphicsData[d],g=e.points;if(e.type==f.Graphics.POLY){b.beginPath(),b.moveTo(g[0],g[1]);for(var h=1;hb?b:d,e=b+m>e?b+m:e,g=g>c?b:g,h=c+n>h?c+n:h}else if(k===f.Graphics.CIRC||k===f.Graphics.ELIP){b=a.x,c=a.y;var o=a.radius+l/2;d=d>b-o?b-o:d,e=b+o>e?b+o:e,g=g>c-o?c-o:g,h=c+o>h?c+o:h}else for(var p=0;pb-l?b-l:d,e=b+l>e?b+l:e,g=g>c-l?c-l:g,h=c+l>h?c+l:h}this.bounds=new f.Rectangle(d,g,e-d,h-g)}},f.Graphics.POLY=0,f.Graphics.RECT=1,f.Graphics.CIRC=2,f.Graphics.ELIP=3,f.Strip=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.blendMode=f.blendModes.NORMAL;try{this.uvs=new Float32Array([0,1,1,1,1,0,0,1]),this.verticies=new Float32Array([0,0,0,0,0,0,0,0,0]),this.colors=new Float32Array([1,1,1,1]),this.indices=new Uint16Array([0,1,2,3])}catch(d){this.uvs=[0,1,1,1,1,0,0,1],this.verticies=[0,0,0,0,0,0,0,0,0],this.colors=[1,1,1,1],this.indices=[0,1,2,3]}this.width=b,this.height=c,a.baseTexture.hasLoaded?(this.width=this.texture.frame.width,this.height=this.texture.frame.height,this.updateFrame=!0):(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Strip.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Strip.prototype.constructor=f.Strip,f.Strip.prototype.setTexture=function(a){this.texture=a,this.width=a.frame.width,this.height=a.frame.height,this.updateFrame=!0},f.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Rope=function(a,b){f.Strip.call(this,a),this.points=b;try{this.verticies=new Float32Array(4*b.length),this.uvs=new Float32Array(4*b.length),this.colors=new Float32Array(2*b.length),this.indices=new Uint16Array(2*b.length)}catch(c){this.verticies=verticies,this.uvs=uvs,this.colors=colors,this.indices=indices}this.refresh()},f.Rope.prototype=Object.create(f.Strip.prototype),f.Rope.prototype.constructor=f.Rope,f.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=this.indices,d=this.colors,e=a[0],f=a[0];this.count-=.2,b[0]=0,b[1]=1,b[2]=0,b[3]=1,d[0]=1,d[1]=1,c[0]=0,c[1]=1;for(var g=a.length,h=1;g>h;h++){var f=a[h],i=4*h,j=h/(g-1);h%2?(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1):(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1),i=2*h,d[i]=1,d[i+1]=1,i=2*h,c[i]=i,c[i+1]=i+1,e=f}}},f.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var b,c=this.verticies,d=a[0],e={x:0,y:0},g=a[0];this.count-=.2,c[0]=g.x+e.x,c[1]=g.y+e.y,c[2]=g.x-e.x,c[3]=g.y-e.y;for(var h=a.length,i=1;h>i;i++){var g=a[i],j=4*i;b=i1&&(k=1);var l=Math.sqrt(e.x*e.x+e.y*e.y),m=this.texture.height/2;e.x/=l,e.y/=l,e.x*=m,e.y*=m,c[j]=g.x+e.x,c[j+1]=g.y+e.y,c[j+2]=g.x-e.x,c[j+3]=g.y-e.y,d=g}f.DisplayObjectContainer.prototype.updateTransform.call(this)}},f.Rope.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.width=b,this.height=c,this.tileScale=new f.Point(1,1),this.tilePosition=new f.Point(0,0),this.renderable=!0,this.blendMode=f.blendModes.NORMAL},f.TilingSprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.TilingSprite.prototype.constructor=f.TilingSprite,f.TilingSprite.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Spine=function(a){if(f.DisplayObjectContainer.call(this),this.spineData=f.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new n.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new n.AnimationStateData(this.spineData),this.state=new n.AnimationState(this.stateData),this.slotContainers=[];for(var b=0,c=this.skeleton.drawOrder.length;c>b;b++){var d=this.skeleton.drawOrder[b],e=d.attachment,g=new f.DisplayObjectContainer;if(this.slotContainers.push(g),this.addChild(g),e instanceof n.RegionAttachment){var h=e.rendererObject.name,i=this.createSprite(d,e.rendererObject);d.currentSprite=i,d.currentSpriteName=h,g.addChild(i)}}},f.Spine.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Spine.prototype.constructor=f.Spine,f.Spine.prototype.updateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var b=this.skeleton.drawOrder,c=0,d=b.length;d>c;c++){var e=b[c],g=e.attachment,h=this.slotContainers[c];if(g instanceof n.RegionAttachment){if(g.rendererObject&&(!e.currentSpriteName||e.currentSpriteName!=g.name)){var i=g.rendererObject.name;if(void 0!==e.currentSprite&&(e.currentSprite.visible=!1),e.sprites=e.sprites||{},void 0!==e.sprites[i])e.sprites[i].visible=!0;else{var j=this.createSprite(e,g.rendererObject);h.addChild(j)}e.currentSprite=e.sprites[i],e.currentSpriteName=i}h.visible=!0;var k=e.bone;h.position.x=k.worldX+g.x*k.m00+g.y*k.m01,h.position.y=k.worldY+g.x*k.m10+g.y*k.m11,h.scale.x=k.worldScaleX,h.scale.y=k.worldScaleY,h.rotation=-(e.bone.worldRotation*Math.PI/180)}else h.visible=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.Spine.prototype.createSprite=function(a,b){var c=f.TextureCache[b.name]?b.name:b.name+".png",d=new f.Sprite(f.Texture.fromFrame(c));return d.scale=b.scale,d.rotation=b.rotation,d.anchor.x=d.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[b.name]=d,d};var n={};n.BoneData=function(a,b){this.name=a,this.parent=b},n.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1},n.SlotData=function(a,b){this.name=a,this.boneData=b},n.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null},n.Bone=function(a,b){this.data=a,this.parent=b,this.setToSetupPose()},n.Bone.yDown=!1,n.Bone.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,updateWorldTransform:function(a,b){var c=this.parent;null!=c?(this.worldX=this.x*c.m00+this.y*c.m01+c.worldX,this.worldY=this.x*c.m10+this.y*c.m11+c.worldY,this.worldScaleX=c.worldScaleX*this.scaleX,this.worldScaleY=c.worldScaleY*this.scaleY,this.worldRotation=c.worldRotation+this.rotation):(this.worldX=this.x,this.worldY=this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotation);var d=this.worldRotation*Math.PI/180,e=Math.cos(d),f=Math.sin(d);this.m00=e*this.worldScaleX,this.m10=f*this.worldScaleX,this.m01=-f*this.worldScaleY,this.m11=e*this.worldScaleY,a&&(this.m00=-this.m00,this.m01=-this.m01),b&&(this.m10=-this.m10,this.m11=-this.m11),n.Bone.yDown&&(this.m10=-this.m10,this.m11=-this.m11)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY}},n.Slot=function(a,b,c){this.data=a,this.skeleton=b,this.bone=c,this.setToSetupPose()},n.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,setAttachment:function(a){this.attachment=a,this._attachmentTime=this.skeleton.time},setAttachmentTime:function(a){this._attachmentTime=this.skeleton.time-a},getAttachmentTime:function(){return this.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},n.Skin=function(a){this.name=a,this.attachments={}},n.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},n.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},n.Animation.prototype={apply:function(a,b,c){c&&0!=this.duration&&(b%=this.duration);for(var d=this.timelines,e=0,f=d.length;f>e;e++)d[e].apply(a,b,1)},mix:function(a,b,c,d){c&&0!=this.duration&&(b%=this.duration);for(var e=this.timelines,f=0,g=e.length;g>f;f++)e[f].apply(a,b,d)}},n.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(0==e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},n.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},n.Curves=function(a){this.curves=[],this.curves.length=6*(a-1)},n.Curves.prototype={setLinear:function(a){this.curves[6*a]=0},setStepped:function(a){this.curves[6*a]=-1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=6*a,r=this.curves;r[q]=b*i+m*j+o*h,r[q+1]=c*i+n*j+p*h,r[q+2]=m*k+o*l,r[q+3]=n*k+p*l,r[q+4]=o*l,r[q+5]=p*l},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=6*a,d=this.curves,e=d[c];if(!e)return b;if(-1==e)return 0;for(var f=d[c+1],g=d[c+2],h=d[c+3],i=d[c+4],j=d[c+5],k=e,l=f,m=8;;){if(k>=b){var n=k-e,o=l-f;return o+(l-o)*(b-n)/(k-n)}if(0==m)break;m--,e+=g,f+=h,g+=i,h+=j,k+=e,l+=f}return l+(1-l)*(b-k)/(1-k)}},n.RotateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=2*a},n.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-2]){for(var f=e.data.rotation+d[d.length-1]-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;return e.rotation+=f*c,void 0}var g=n.binarySearch(d,b,2),h=d[g-1],i=d[g],j=1-(b-i)/(d[g-2]-i);j=this.curves.getCurvePercent(g/2-1,j);for(var f=d[g+1]-h;f>180;)f-=360;for(;-180>f;)f+=360;for(f=e.data.rotation+(h+f*j)-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;e.rotation+=f*c}}},n.TranslateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.x+=(e.data.x+d[d.length-2]-e.x)*c,e.y+=(e.data.y+d[d.length-1]-e.y)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.x+=(e.data.x+g+(d[f+1]-g)*j-e.x)*c,e.y+=(e.data.y+h+(d[f+2]-h)*j-e.y)*c}}},n.ScaleTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.scaleX+=(e.data.scaleX-1+d[d.length-2]-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+d[d.length-1]-e.scaleY)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.scaleX+=(e.data.scaleX-1+g+(d[f+1]-g)*j-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+h+(d[f+2]-h)*j-e.scaleY)*c}}},n.ColorTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=5*a},n.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(c,d){c*=5,this.frames[c]=d,this.frames[c+1]=r,this.frames[c+2]=g,this.frames[c+3]=b,this.frames[c+4]=a},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-5]){var f=d.length-1;return e.r=d[f-3],e.g=d[f-2],e.b=d[f-1],e.a=d[f],void 0}var g=n.binarySearch(d,b,5),h=d[g-4],i=d[g-3],j=d[g-2],k=d[g-1],l=d[g],m=1-(b-l)/(d[g-5]-l);m=this.curves.getCurvePercent(g/5-1,m);var o=h+(d[g+1]-h)*m,p=i+(d[g+2]-i)*m,q=j+(d[g+3]-j)*m,r=k+(d[g+4]-k)*m;1>c?(e.r+=(o-e.r)*c,e.g+=(p-e.g)*c,e.b+=(q-e.b)*c,e.a+=(r-e.a)*c):(e.r=o,e.g=p,e.b=q,e.a=r)}}},n.AttachmentTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},n.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b){var c=this.frames;if(!(b=c[c.length-1]?c.length-1:n.binarySearch(c,b,1)-1;var e=this.attachmentNames[d];a.slots[this.slotIndex].setAttachment(e?a.getAttachmentBySlotIndex(this.slotIndex,e):null)}}},n.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.animations=[]},n.SkeletonData.prototype={defaultSkin:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},n.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,c=a.bones.length;c>b;b++){var d=a.bones[b],e=d.parent?this.bones[a.bones.indexOf(d.parent)]:null;this.bones.push(new n.Bone(d,e))}this.slots=[],this.drawOrder=[];for(var b=0,c=a.slots.length;c>b;b++){var f=a.slots[b],g=this.bones[a.bones.indexOf(f.boneData)],h=new n.Slot(f,this,g);this.slots.push(h),this.drawOrder.push(h)}},n.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateWorldTransform:function(){for(var a=this.flipX,b=this.flipY,c=this.bones,d=0,e=c.length;e>d;d++)c[d].updateWorldTransform(a,b)},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose()},setSlotsToSetupPose:function(){for(var a=this.slots,b=0,c=a.length;c>b;b++)a[b].setToSetupPose(b)},getRootBone:function(){return 0==this.bones.length?null:this.bones[0]},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a);if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){this.skin&&a&&a._attachAll(this,this.skin),this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.size;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachment(d,b),null==g))throw"Attachment not found: "+b+", for slot: "+a;return f.setAttachment(g),void 0}}throw"Slot not found: "+a},update:function(a){time+=a}},n.AttachmentType={region:0},n.RegionAttachment=function(){this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},n.RegionAttachment.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,c=-this.width/2*this.scaleX+this.regionOffsetX*a,d=-this.height/2*this.scaleY+this.regionOffsetY*b,e=c+this.regionWidth*a,f=d+this.regionHeight*b,g=this.rotation*Math.PI/180,h=Math.cos(g),i=Math.sin(g),j=c*h+this.x,k=c*i,l=d*h+this.y,m=d*i,n=e*h+this.x,o=e*i,p=f*h+this.y,q=f*i,r=this.offset;r[0]=j-m,r[1]=l+k,r[2]=j-q,r[3]=p+k,r[4]=n-q,r[5]=p+o,r[6]=n-m,r[7]=l+o},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},n.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},n.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=this.animationToMixTime[a.name+":"+b.name];return c?c:this.defaultMix}},n.AnimationState=function(a){this.data=a,this.queue=[]},n.AnimationState.prototype={current:null,previous:null,currentTime:0,previousTime:0,currentLoop:!1,previousLoop:!1,mixTime:0,mixDuration:0,update:function(a){if(this.currentTime+=a,this.previousTime+=a,this.mixTime+=a,this.queue.length>0){var b=this.queue[0];this.currentTime>=b.delay&&(this._setAnimation(b.animation,b.loop),this.queue.shift())}},apply:function(a){if(this.current)if(this.previous){this.previous.apply(a,this.previousTime,this.previousLoop);var b=this.mixTime/this.mixDuration;b>=1&&(b=1,this.previous=null),this.current.mix(a,this.currentTime,this.currentLoop,b)}else this.current.apply(a,this.currentTime,this.currentLoop)},clearAnimation:function(){this.previous=null,this.current=null,this.queue.length=0},_setAnimation:function(a,b){this.previous=null,a&&this.current&&(this.mixDuration=this.data.getMix(this.current,a),this.mixDuration>0&&(this.mixTime=0,this.previous=this.current,this.previousTime=this.currentTime,this.previousLoop=this.currentLoop)),this.current=a,this.currentLoop=b,this.currentTime=0},setAnimationByName:function(a,b){var c=this.data.skeletonData.findAnimation(a);if(!c)throw"Animation not found: "+a;this.setAnimation(c,b)},setAnimation:function(a,b){this.queue.length=0,this._setAnimation(a,b)},addAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;this.addAnimation(d,b,c)},addAnimation:function(a,b,c){var d={};if(d.animation=a,d.loop=b,!c||0>=c){var e=0==this.queue.length?this.current:this.queue[this.queue.length-1].animation;c=null!=e?e.duration-this.data.getMix(e,a)+(c||0):0}d.delay=c,this.queue.push(d)},isComplete:function(){return!this.current||this.currentTime>=this.current.duration}},n.SkeletonJson=function(a){this.attachmentLoader=a},n.SkeletonJson.prototype={scale:1,readSkeletonData:function(a){for(var b=new n.SkeletonData,c=a.bones,d=0,e=c.length;e>d;d++){var f=c[d],g=null;if(f.parent&&(g=b.findBone(f.parent),!g))throw"Parent bone not found: "+f.parent;var h=new n.BoneData(f.name,g);h.length=(f.length||0)*this.scale,h.x=(f.x||0)*this.scale,h.y=(f.y||0)*this.scale,h.rotation=f.rotation||0,h.scaleX=f.scaleX||1,h.scaleY=f.scaleY||1,b.bones.push(h)}for(var i=a.slots,d=0,e=i.length;e>d;d++){var j=i[d],h=b.findBone(j.bone);if(!h)throw"Slot bone not found: "+j.bone;var k=new n.SlotData(j.name,h),l=j.color;l&&(k.r=n.SkeletonJson.toColor(l,0),k.g=n.SkeletonJson.toColor(l,1),k.b=n.SkeletonJson.toColor(l,2),k.a=n.SkeletonJson.toColor(l,3)),k.attachmentName=j.attachment,b.slots.push(k)}var m=a.skins;for(var o in m)if(m.hasOwnProperty(o)){var p=m[o],q=new n.Skin(o);for(var r in p)if(p.hasOwnProperty(r)){var s=b.findSlotIndex(r),t=p[r];for(var u in t)if(t.hasOwnProperty(u)){var v=this.readAttachment(q,u,t[u]);null!=v&&q.addAttachment(s,u,v)}}b.skins.push(q),"default"==q.name&&(b.defaultSkin=q)}var w=a.animations;for(var x in w)w.hasOwnProperty(x)&&this.readAnimation(x,w[x],b);return b},readAttachment:function(a,b,c){b=c.name||b;var d=n.AttachmentType[c.type||"region"];if(d==n.AttachmentType.region){var e=new n.RegionAttachment;return e.x=(c.x||0)*this.scale,e.y=(c.y||0)*this.scale,e.scaleX=c.scaleX||1,e.scaleY=c.scaleY||1,e.rotation=c.rotation||0,e.width=(c.width||32)*this.scale,e.height=(c.height||32)*this.scale,e.updateOffset(),e.rendererObject={},e.rendererObject.name=b,e.rendererObject.scale={},e.rendererObject.scale.x=e.scaleX,e.rendererObject.scale.y=e.scaleY,e.rendererObject.rotation=-e.rotation*Math.PI/180,e }throw"Unknown attachment type: "+d},readAnimation:function(a,b,c){var d=[],e=0,f=b.bones;for(var g in f)if(f.hasOwnProperty(g)){var h=c.findBoneIndex(g);if(-1==h)throw"Bone not found: "+g;var i=f[g];for(var j in i)if(i.hasOwnProperty(j)){var k=i[j];if("rotate"==j){var l=new n.RotateTimeline(k.length);l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m,q.time,q.angle),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[2*l.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var l,r=1;"scale"==j?l=new n.ScaleTimeline(k.length):(l=new n.TranslateTimeline(k.length),r=this.scale),l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;l.setFrame(m,q.time,s,t),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[3*l.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var l=new n.ColorTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=n.SkeletonJson.toColor(y,0),A=n.SkeletonJson.toColor(y,1),B=n.SkeletonJson.toColor(y,2),C=n.SkeletonJson.toColor(y,3);l.setFrame(m,q.time,z,A,B,C),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[5*l.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var l=new n.AttachmentTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m++,q.time,q.name)}d.push(l),e=Math.max(e,l.frames[l.getFrameCount()-1])}}}c.animations.push(new n.Animation(a,d,e))}},n.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},n.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},n.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new n.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new n.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new n.AtlasPage,e.name=f,e.format=n.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=n.Atlas.TextureFilter[d[0]],e.magFilter=n.Atlas.TextureFilter[d[1]];var l=c.readValue();e.uWrap=n.Atlas.TextureWrap.clampToEdge,e.vWrap=n.Atlas.TextureWrap.clampToEdge,"x"==l?e.uWrap=n.Atlas.TextureWrap.repeat:"y"==l?e.vWrap=n.Atlas.TextureWrap.repeat:"xy"==l&&(e.uWrap=e.vWrap=n.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},n.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},n.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},n.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},n.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},n.AtlasPage=function(){},n.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},n.AtlasRegion=function(){},n.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},n.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},n.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},n.AtlasAttachmentLoader=function(a){this.atlas=a},n.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case n.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new n.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},n.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;h Date: Sun, 3 Nov 2013 17:19:35 +0000 Subject: [PATCH 68/96] Graphics Bug fixs Fixed bug where webGL graphics not working in safari Fixed bug where Collinear points cause lines to be draw oddly --- bin/pixi.dev.js | 72 +++++---- bin/pixi.dev.js.map | 2 +- bin/pixi.js | 10 +- .../example 13 - Graphics/indexLineTest.html | 146 ++++++++++++++++++ src/pixi/renderers/webgl/PixiShader.js | 8 +- src/pixi/renderers/webgl/PrimitiveShader.js | 10 +- src/pixi/renderers/webgl/WebGLGraphics.js | 27 ++-- src/pixi/renderers/webgl/WebGLShaders.js | 13 ++ 8 files changed, 232 insertions(+), 56 deletions(-) create mode 100644 examples/example 13 - Graphics/indexLineTest.html diff --git a/bin/pixi.dev.js b/bin/pixi.dev.js index 4583636..11f4d76 100644 --- a/bin/pixi.dev.js +++ b/bin/pixi.dev.js @@ -1,14 +1,3 @@ -/** - * @license - * Pixi.JS - v1.3.0 - * Copyright (c) 2012, Mat Groves - * http://goodboydigital.com/ - * - * Compiled: 2013-11-03 - * - * Pixi.JS is licensed under the MIT License. - * http://www.opensource.org/licenses/mit-license.php - */ /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -3722,7 +3711,13 @@ PIXI.activatePrimitiveShader = function() var gl = PIXI.gl; gl.useProgram(PIXI.primitiveShader.program); + + gl.disableVertexAttribArray(PIXI.defaultShader.aVertexPosition); + gl.disableVertexAttribArray(PIXI.defaultShader.colorAttribute); gl.disableVertexAttribArray(PIXI.defaultShader.aTextureCoord); + + gl.enableVertexAttribArray(PIXI.primitiveShader.aVertexPosition); + gl.enableVertexAttribArray(PIXI.primitiveShader.colorAttribute); } PIXI.deactivatePrimitiveShader = function() @@ -3730,7 +3725,14 @@ PIXI.deactivatePrimitiveShader = function() var gl = PIXI.gl; gl.useProgram(PIXI.defaultShader.program); + + gl.disableVertexAttribArray(PIXI.primitiveShader.aVertexPosition); + gl.disableVertexAttribArray(PIXI.primitiveShader.colorAttribute); + + gl.enableVertexAttribArray(PIXI.defaultShader.aVertexPosition); + gl.enableVertexAttribArray(PIXI.defaultShader.colorAttribute); gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord); + } PIXI.activateStripShader = function() @@ -3833,11 +3835,11 @@ PIXI.PixiShader.prototype.init = function() this.uSampler = gl.getUniformLocation(program, "uSampler"); this.projectionVector = gl.getUniformLocation(program, "projectionVector"); this.offsetVector = gl.getUniformLocation(program, "offsetVector"); + //this.dimensions = gl.getUniformLocation(this.program, "dimensions"); + + // get and store the attributes + this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); this.colorAttribute = gl.getAttribLocation(program, "aColor"); - //this.dimensions = gl.getUniformLocation(this.program, "dimensions"); - - // get and store the attributes - this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); this.aTextureCoord = gl.getAttribLocation(program, "aTextureCoord"); // add those custom shaders! @@ -4032,13 +4034,13 @@ PIXI.PrimitiveShader.prototype.init = function() // get and store the uniforms for the shader this.projectionVector = gl.getUniformLocation(program, "projectionVector"); this.offsetVector = gl.getUniformLocation(program, "offsetVector"); + + // get and store the attributes + this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); this.colorAttribute = gl.getAttribLocation(program, "aColor"); - // get and store the attributes - this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); - - this.translationMatrix = gl.getUniformLocation(program, "translationMatrix"); - this.alpha = gl.getUniformLocation(program, "alpha"); + this.translationMatrix = gl.getUniformLocation(program, "translationMatrix"); + this.alpha = gl.getUniformLocation(program, "alpha"); this.program = program; } @@ -4107,20 +4109,15 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.uniform2f(PIXI.primitiveShader.offsetVector, -PIXI.offset.x, -PIXI.offset.y); gl.uniform1f(PIXI.primitiveShader.alpha, graphics.worldAlpha); - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - // WHY DOES THIS LINE NEED TO BE THERE??? - //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - // its not even used.. but need to be set or it breaks? - // only on pc though.. - gl.vertexAttribPointer(PIXI.primitiveShader.aVertexPosition, 2, gl.FLOAT, false, 4 * 6, 0); gl.vertexAttribPointer(PIXI.primitiveShader.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4); // set the index buffer! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); + gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); PIXI.deactivatePrimitiveShader(); @@ -4441,16 +4438,27 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y); denom = a1*b2 - a2*b1; - - if (denom == 0) { - denom+=1; - } + + if(Math.abs(denom) < 0.1 ) + { + + denom+=10.1; + verts.push(p2x - perpx , p2y - perpy, + r, g, b, alpha); + + verts.push(p2x + perpx , p2y + perpy, + r, g, b, alpha); + + continue; + } px = (b1*c2 - b2*c1)/denom; py = (a2*c1 - a1*c2)/denom; + pdist = (px -p2x) * (px -p2x) + (py -p2y) + (py -p2y); + if(pdist > 140 * 140) { perp3x = perpx - perp2x; @@ -4475,6 +4483,7 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) } else { + verts.push(px , py); verts.push(r, g, b, alpha); @@ -12159,4 +12168,5 @@ Object.defineProperty(PIXI.DotScreenFilter.prototype, 'angle', { } else { root.PIXI = PIXI; } -}).call(this); \ No newline at end of file +}).call(this); +//@ sourceMappingURL=pixi.dev.js.map \ No newline at end of file diff --git a/bin/pixi.dev.js.map b/bin/pixi.dev.js.map index e3ed3a5..154b544 100644 --- a/bin/pixi.dev.js.map +++ b/bin/pixi.dev.js.map @@ -65,6 +65,6 @@ "src/pixi/Outro.js" ], "names": [], - "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sB;AC5jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7gBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpgCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACpgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACn7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACpKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,c", + "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sB;AC5jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnhBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpgCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACpgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACn7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACpKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,c", "sourceRoot": "../" } \ No newline at end of file diff --git a/bin/pixi.js b/bin/pixi.js index e09a415..dbe9411 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -9,8 +9,8 @@ * Pixi.JS is licensed under the MIT License. * http://www.opensource.org/licenses/mit-license.php */ -!function(){function c(){return f.Matrix="undefined"!=typeof Float32Array?Float32Array:Array,f.Matrix}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}var e=this,f=f||{};f.Point=function(a,b){this.x=a||0,this.y=b||0},f.Point.prototype.clone=function(){return new f.Point(this.x,this.y)},f.Point.prototype.constructor=f.Point,f.Rectangle=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Rectangle.prototype.clone=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Rectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},f.Rectangle.prototype.constructor=f.Rectangle,f.Polygon=function(a){if(a instanceof Array||(a=Array.prototype.slice.call(arguments)),"number"==typeof a[0]){for(var b=[],c=0,d=a.length;d>c;c+=2)b.push(new f.Point(a[c],a[c+1]));a=b}this.points=a},f.Polygon.prototype.clone=function(){for(var a=[],b=0;bb!=i>b&&(h-f)*(b-g)/(i-g)+f>a;j&&(c=!c)}return c},f.Polygon.prototype.constructor=f.Polygon,f.Circle=function(a,b,c){this.x=a||0,this.y=b||0,this.radius=c||0},f.Circle.prototype.clone=function(){return new f.Circle(this.x,this.y,this.radius)},f.Circle.prototype.contains=function(a,b){if(this.radius<=0)return!1;var c=this.x-a,d=this.y-b,e=this.radius*this.radius;return c*=c,d*=d,e>=c+d},f.Circle.prototype.constructor=f.Circle,f.Ellipse=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Ellipse.prototype.clone=function(){return new f.Ellipse(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=(a-this.x)/this.width-.5,d=(b-this.y)/this.height-.5;return c*=c,d*=d,.25>c+d},f.Ellipse.getBounds=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.constructor=f.Ellipse,c(),f.mat3={},f.mat3.create=function(){var a=new f.Matrix(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat3.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat4={},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat3.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=b[0],n=b[1],o=b[2],p=b[3],q=b[4],r=b[5],s=b[6],t=b[7],u=b[8];return c[0]=m*d+n*g+o*j,c[1]=m*e+n*h+o*k,c[2]=m*f+n*i+o*l,c[3]=p*d+q*g+r*j,c[4]=p*e+q*h+r*k,c[5]=p*f+q*i+r*l,c[6]=s*d+t*g+u*j,c[7]=s*e+t*h+u*k,c[8]=s*f+t*i+u*l,c},f.mat3.clone=function(a){var b=new f.Matrix(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},f.mat3.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[5];return a[1]=a[3],a[2]=a[6],a[3]=c,a[5]=a[7],a[6]=d,a[7]=e,a}return b[0]=a[0],b[1]=a[3],b[2]=a[6],b[3]=a[1],b[4]=a[4],b[5]=a[7],b[6]=a[2],b[7]=a[5],b[8]=a[8],b},f.mat3.toMat4=function(a,b){return b||(b=f.mat4.create()),b[15]=1,b[14]=0,b[13]=0,b[12]=0,b[11]=0,b[10]=a[8],b[9]=a[7],b[8]=a[6],b[7]=0,b[6]=a[5],b[5]=a[4],b[4]=a[3],b[3]=0,b[2]=a[2],b[1]=a[1],b[0]=a[0],b},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat4.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[3],f=a[6],g=a[7],h=a[11];return a[1]=a[4],a[2]=a[8],a[3]=a[12],a[4]=c,a[6]=a[9],a[7]=a[13],a[8]=d,a[9]=f,a[11]=a[14],a[12]=e,a[13]=g,a[14]=h,a}return b[0]=a[0],b[1]=a[4],b[2]=a[8],b[3]=a[12],b[4]=a[1],b[5]=a[5],b[6]=a[9],b[7]=a[13],b[8]=a[2],b[9]=a[6],b[10]=a[10],b[11]=a[14],b[12]=a[3],b[13]=a[7],b[14]=a[11],b[15]=a[15],b},f.mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=b[0],u=b[1],v=b[2],w=b[3];return c[0]=t*d+u*h+v*l+w*p,c[1]=t*e+u*i+v*m+w*q,c[2]=t*f+u*j+v*n+w*r,c[3]=t*g+u*k+v*o+w*s,t=b[4],u=b[5],v=b[6],w=b[7],c[4]=t*d+u*h+v*l+w*p,c[5]=t*e+u*i+v*m+w*q,c[6]=t*f+u*j+v*n+w*r,c[7]=t*g+u*k+v*o+w*s,t=b[8],u=b[9],v=b[10],w=b[11],c[8]=t*d+u*h+v*l+w*p,c[9]=t*e+u*i+v*m+w*q,c[10]=t*f+u*j+v*n+w*r,c[11]=t*g+u*k+v*o+w*s,t=b[12],u=b[13],v=b[14],w=b[15],c[12]=t*d+u*h+v*l+w*p,c[13]=t*e+u*i+v*m+w*q,c[14]=t*f+u*j+v*n+w*r,c[15]=t*g+u*k+v*o+w*s,c},f.DisplayObject=function(){this.last=this,this.first=this,this.position=new f.Point,this.scale=new f.Point(1,1),this.pivot=new f.Point(0,0),this.rotation=0,this.alpha=1,this.visible=!0,this.hitArea=null,this.buttonMode=!1,this.renderable=!1,this.parent=null,this.stage=null,this.worldAlpha=1,this._interactive=!1,this.worldTransform=f.mat3.create(),this.localTransform=f.mat3.create(),this.color=[],this.dynamic=!0,this._sr=0,this._cr=1,this.filterArea=new f.Rectangle(0,0,1,1)},f.DisplayObject.prototype.constructor=f.DisplayObject,f.DisplayObject.prototype.setInteractive=function(a){this.interactive=a},Object.defineProperty(f.DisplayObject.prototype,"interactive",{get:function(){return this._interactive},set:function(a){this._interactive=a,this.stage&&(this.stage.dirty=!0)}}),Object.defineProperty(f.DisplayObject.prototype,"mask",{get:function(){return this._mask},set:function(a){a?this._mask?(a.start=this._mask.start,a.end=this._mask.end):(this.addFilter(a),a.renderable=!1):(this.removeFilter(this._mask),this._mask.renderable=!0),this._mask=a}}),Object.defineProperty(f.DisplayObject.prototype,"filters",{get:function(){return this._filters},set:function(a){if(a){this._filters&&this.removeFilter(this._filters),this.addFilter(a);for(var b=[],c=0;c=0&&b<=this.children.length))throw new Error(a+" The index "+b+" supplied is out of bounds "+this.children.length);if(void 0!=a.parent&&a.parent.removeChild(a),a.parent=this,this.stage){var c=a;do c.interactive&&(this.stage.dirty=!0),c.stage=this.stage,c=c._iNext;while(c)}var d,e,f=a.first,g=a.last;if(b==this.children.length){e=this.last;for(var h=this,i=this.last;h;)h.last==i&&(h.last=a.last),h=h.parent}else e=0==b?this:this.children[b-1].last;d=e._iNext,d&&(d._iPrev=g,g._iNext=d),f._iPrev=e,e._iNext=f,this.children.splice(b,0,a),this.__renderGroup&&(a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a),this.__renderGroup.addDisplayObjectAndChildren(a))},f.DisplayObjectContainer.prototype.swapChildren=function(){},f.DisplayObjectContainer.prototype.getChildAt=function(a){if(a>=0&&aa;a++)this.children[a].updateTransform()}},f.blendModes={},f.blendModes.NORMAL=0,f.blendModes.SCREEN=1,f.Sprite=function(a){f.DisplayObjectContainer.call(this),this.anchor=new f.Point,this.texture=a,this.blendMode=f.blendModes.NORMAL,this._width=0,this._height=0,a.baseTexture.hasLoaded?this.updateFrame=!0:(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Sprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Sprite.prototype.constructor=f.Sprite,Object.defineProperty(f.Sprite.prototype,"width",{get:function(){return this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(f.Sprite.prototype,"height",{get:function(){return this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),f.Sprite.prototype.setTexture=function(a){this.texture.baseTexture!=a.baseTexture?(this.textureChange=!0,this.texture=a,this.__renderGroup&&this.__renderGroup.updateTexture(this)):this.texture=a,this.updateFrame=!0},f.Sprite.prototype.onTextureUpdate=function(){this._width&&(this.scale.x=this._width/this.texture.frame.width),this._height&&(this.scale.y=this._height/this.texture.frame.height),this.updateFrame=!0},f.Sprite.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache"+this);return new f.Sprite(b)},f.Sprite.fromImage=function(a){var b=f.Texture.fromImage(a);return new f.Sprite(b)},f.MovieClip=function(a){f.Sprite.call(this,a[0]),this.textures=a,this.animationSpeed=1,this.loop=!0,this.onComplete=null,this.currentFrame=0,this.playing=!1},f.MovieClip.prototype=Object.create(f.Sprite.prototype),f.MovieClip.prototype.constructor=f.MovieClip,Object.defineProperty(f.MovieClip.prototype,"totalFrames",{get:function(){return this.textures.length}}),f.MovieClip.prototype.stop=function(){this.playing=!1},f.MovieClip.prototype.play=function(){this.playing=!0},f.MovieClip.prototype.gotoAndStop=function(a){this.playing=!1,this.currentFrame=a;var b=0|this.currentFrame+.5;this.setTexture(this.textures[b%this.textures.length])},f.MovieClip.prototype.gotoAndPlay=function(a){this.currentFrame=a,this.playing=!0},f.MovieClip.prototype.updateTransform=function(){if(f.Sprite.prototype.updateTransform.call(this),this.playing){this.currentFrame+=this.animationSpeed;var a=0|this.currentFrame+.5;this.loop||a=this.textures.length&&(this.gotoAndStop(this.textures.length-1),this.onComplete&&this.onComplete())}},f.FilterBlock=function(){this.visible=!0,this.renderable=!0},f.Text=function(a,b){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),f.Sprite.call(this,f.Texture.fromCanvas(this.canvas)),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.Text.prototype=Object.create(f.Sprite.prototype),f.Text.prototype.constructor=f.Text,f.Text.prototype.setStyle=function(a){a=a||{},a.font=a.font||"bold 20pt Arial",a.fill=a.fill||"black",a.align=a.align||"left",a.stroke=a.stroke||"black",a.strokeThickness=a.strokeThickness||0,a.wordWrap=a.wordWrap||!1,a.wordWrapWidth=a.wordWrapWidth||100,this.style=a,this.dirty=!0},f.Text.prototype.setText=function(a){this.text=a.toString()||" ",this.dirty=!0},f.Text.prototype.updateText=function(){this.context.font=this.style.font;var a=this.text;this.style.wordWrap&&(a=this.wordWrap(this.text));for(var b=a.split(/(?:\r\n|\r|\n)/),c=[],d=0,e=0;ee?f:arguments.callee(a,b,f,d,e):arguments.callee(a,b,c,f,e)},c=function(a,c,d){if(a.measureText(c).width<=d||c.length<1)return c;var e=b(a,c,0,c.length,d);return c.substring(0,e)+"\n"+arguments.callee(a,c.substring(e),d)},d="",e=a.split("\n"),f=0;f=2?parseInt(b[b.length-2],10):f.BitmapText.fonts[this.fontName].size,this.dirty=!0},f.BitmapText.prototype.updateText=function(){for(var a=f.BitmapText.fonts[this.fontName],b=new f.Point,c=null,d=[],e=0,g=[],h=0,i=this.fontSize/a.size,j=0;j=j;j++){var n=0;"right"==this.style.align?n=e-g[j]:"center"==this.style.align&&(n=(e-g[j])/2),m.push(n)}for(j=0;j0;)this.removeChild(this.getChildAt(0));this.updateText(),this.dirty=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.BitmapText.fonts={},f.InteractionManager=function(a){this.stage=a,this.mouse=new f.InteractionData,this.touchs={},this.tempPoint=new f.Point,this.mouseoverEnabled=!0,this.pool=[],this.interactiveItems=[],this.interactionDOMElement=null,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseOut=this.onMouseOut.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.last=0},f.InteractionManager.prototype.constructor=f.InteractionManager,f.InteractionManager.prototype.collectInteractiveSprite=function(a,b){for(var c=a.children,d=c.length,e=d-1;e>=0;e--){var f=c[e];f.interactive?(b.interactiveChildren=!0,this.interactiveItems.push(f),f.children.length>0&&this.collectInteractiveSprite(f,f)):(f.__iParent=null,f.children.length>0&&this.collectInteractiveSprite(f,b))}},f.InteractionManager.prototype.setTarget=function(a){this.target=a,null===this.interactionDOMElement&&this.setTargetDomElement(a.view),document.body.addEventListener("mouseup",this.onMouseUp,!0)},f.InteractionManager.prototype.setTargetDomElement=function(a){null!==this.interactionDOMElement&&(this.interactionDOMElement.style["-ms-content-zooming"]="",this.interactionDOMElement.style["-ms-touch-action"]="",this.interactionDOMElement.removeEventListener("mousemove",this.onMouseMove,!0),this.interactionDOMElement.removeEventListener("mousedown",this.onMouseDown,!0),this.interactionDOMElement.removeEventListener("mouseout",this.onMouseOut,!0),this.interactionDOMElement.removeEventListener("touchstart",this.onTouchStart,!0),this.interactionDOMElement.removeEventListener("touchend",this.onTouchEnd,!0),this.interactionDOMElement.removeEventListener("touchmove",this.onTouchMove,!0)),window.navigator.msPointerEnabled&&(a.style["-ms-content-zooming"]="none",a.style["-ms-touch-action"]="none"),this.interactionDOMElement=a,a.addEventListener("mousemove",this.onMouseMove,!0),a.addEventListener("mousedown",this.onMouseDown,!0),a.addEventListener("mouseout",this.onMouseOut,!0),a.addEventListener("touchstart",this.onTouchStart,!0),a.addEventListener("touchend",this.onTouchEnd,!0),a.addEventListener("touchmove",this.onTouchMove,!0)},f.InteractionManager.prototype.update=function(){if(this.target){var a=Date.now(),b=a-this.last;if(b=30*b/1e3,!(1>b)){if(this.last=a,this.dirty){this.dirty=!1;for(var c=this.interactiveItems.length,d=0;c>d;d++)this.interactiveItems[d].interactiveChildren=!1;this.interactiveItems=[],this.stage.interactive&&this.interactiveItems.push(this.stage),this.collectInteractiveSprite(this.stage,this.stage)}var e=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var d=0;e>d;d++){var f=this.interactiveItems[d];(f.mouseover||f.mouseout||f.buttonMode)&&(f.__hit=this.hitTest(f,this.mouse),this.mouse.target=f,f.__hit?(f.buttonMode&&(this.interactionDOMElement.style.cursor="pointer"),f.__isOver||(f.mouseover&&f.mouseover(this.mouse),f.__isOver=!0)):f.__isOver&&(f.mouseout&&f.mouseout(this.mouse),f.__isOver=!1))}}}},f.InteractionManager.prototype.onMouseMove=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactionDOMElement.getBoundingClientRect();this.mouse.global.x=(a.clientX-b.left)*(this.target.width/b.width),this.mouse.global.y=(a.clientY-b.top)*(this.target.height/b.height);var c=this.interactiveItems.length;this.mouse.global;for(var d=0;c>d;d++){var e=this.interactiveItems[d];e.mousemove&&e.mousemove(this.mouse)}},f.InteractionManager.prototype.onMouseDown=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactiveItems.length;this.mouse.global,this.stage;for(var c=0;b>c;c++){var d=this.interactiveItems[c];if((d.mousedown||d.click)&&(d.__mouseIsDown=!0,d.__hit=this.hitTest(d,this.mouse),d.__hit&&(d.mousedown&&d.mousedown(this.mouse),d.__isDown=!0,!d.interactiveChildren)))break}},f.InteractionManager.prototype.onMouseOut=function(){var a=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var b=0;a>b;b++){var c=this.interactiveItems[b];c.__isOver&&(this.mouse.target=c,c.mouseout&&c.mouseout(this.mouse),c.__isOver=!1)}},f.InteractionManager.prototype.onMouseUp=function(a){this.mouse.originalEvent=a||window.event,this.mouse.global;for(var b=this.interactiveItems.length,c=!1,d=0;b>d;d++){var e=this.interactiveItems[d];(e.mouseup||e.mouseupoutside||e.click)&&(e.__hit=this.hitTest(e,this.mouse),e.__hit&&!c?(e.mouseup&&e.mouseup(this.mouse),e.__isDown&&e.click&&e.click(this.mouse),e.interactiveChildren||(c=!0)):e.__isDown&&e.mouseupoutside&&e.mouseupoutside(this.mouse),e.__isDown=!1)}},f.InteractionManager.prototype.hitTest=function(a,b){var c=b.global;if(a.vcount!==f.visibleCount)return!1;var d=a instanceof f.Sprite,e=a.worldTransform,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=1/(g*k+h*-j),n=k*m*c.x+-h*m*c.y+(l*h-i*k)*m,o=g*m*c.y+-j*m*c.x+(-l*g+i*j)*m;if(b.target=a,a.hitArea&&a.hitArea.contains)return a.hitArea.contains(n,o)?(b.target=a,!0):!1;if(d){var p,q=a.texture.frame.width,r=a.texture.frame.height,s=-q*a.anchor.x;if(n>s&&s+q>n&&(p=-r*a.anchor.y,o>p&&p+r>o))return b.target=a,!0}for(var t=a.children.length,u=0;t>u;u++){var v=a.children[u],w=this.hitTest(v,b);if(w)return b.target=a,!0}return!1},f.InteractionManager.prototype.onTouchMove=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;dd;d++){var h=this.interactiveItems[d];h.touchmove&&h.touchmove(f)}},f.InteractionManager.prototype.onTouchStart=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i];if((j.touchstart||j.tap)&&(j.__hit=this.hitTest(j,g),j.__hit&&(j.touchstart&&j.touchstart(g),j.__isDown=!0,j.__touchData=g,!j.interactiveChildren)))break}}},f.InteractionManager.prototype.onTouchEnd=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i],k=j.__touchData;j.__hit=this.hitTest(j,f),k==f&&(f.originalEvent=a||window.event,(j.touchend||j.tap)&&(j.__hit&&!g?(j.touchend&&j.touchend(f),j.__isDown&&j.tap&&j.tap(f),j.interactiveChildren||(g=!0)):j.__isDown&&j.touchendoutside&&j.touchendoutside(f),j.__isDown=!1),j.__touchData=null)}this.pool.push(f),this.touchs[e.identifier]=null}},f.InteractionData=function(){this.global=new f.Point,this.local=new f.Point,this.target,this.originalEvent},f.InteractionData.prototype.getLocalPosition=function(a){var b=a.worldTransform,c=this.global,d=b[0],e=b[1],g=b[2],h=b[3],i=b[4],j=b[5],k=1/(d*i+e*-h);return new f.Point(i*k*c.x+-e*k*c.y+(j*e-g*i)*k,d*k*c.y+-h*k*c.x+(-j*d+g*h)*k)},f.InteractionData.prototype.constructor=f.InteractionData,f.Stage=function(a){f.DisplayObjectContainer.call(this),this.worldTransform=f.mat3.create(),this.interactive=!0,this.interactionManager=new f.InteractionManager(this),this.dirty=!0,this.__childrenAdded=[],this.__childrenRemoved=[],this.stage=this,this.stage.hitArea=new f.Rectangle(0,0,1e5,1e5),this.setBackgroundColor(a),this.worldVisible=!0},f.Stage.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Stage.prototype.constructor=f.Stage,f.Stage.prototype.setInteractionDelegate=function(a){this.interactionManager.setTargetDomElement(a)},f.Stage.prototype.updateTransform=function(){this.worldAlpha=1,this.vcount=f.visibleCount;for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform();this.dirty&&(this.dirty=!1,this.interactionManager.dirty=!0),this.interactive&&this.interactionManager.update()},f.Stage.prototype.setBackgroundColor=function(a){this.backgroundColor=a||0,this.backgroundColorSplit=d(this.backgroundColor);var b=this.backgroundColor.toString(16);b="000000".substr(0,6-b.length)+b,this.backgroundColorString="#"+b},f.Stage.prototype.getMousePosition=function(){return this.interactionManager.mouse.global};for(var h=0,i=["ms","moz","webkit","o"],j=0;j>>>>>>>>"),console.log("_");var b=0,c=a.first;for(console.log(c);c._iNext;)if(b++,c=c._iNext,console.log(c),b>100){console.log("BREAK");break}},f.EventTarget=function(){var a={};this.addEventListener=this.on=function(b,c){void 0===a[b]&&(a[b]=[]),-1===a[b].indexOf(c)&&a[b].push(c)},this.dispatchEvent=this.emit=function(b){if(a[b.type]&&a[b.type].length)for(var c=0,d=a[b.type].length;d>c;c++)a[b.type][c](b)},this.removeEventListener=this.off=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)}},f.autoDetectRenderer=function(a,b,c,d,e){a||(a=800),b||(b=600);var g=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}();if(g){var h=-1!=navigator.userAgent.toLowerCase().indexOf("msie");g=!h}return g?new f.WebGLRenderer(a,b,c,d,e):new f.CanvasRenderer(a,b,c,d)},f.PolyK={},f.PolyK.Triangulate=function(a){var b=!0,c=a.length>>1;if(3>c)return[];for(var d=[],e=[],g=0;c>g;g++)e.push(g);for(var g=0,h=c;h>3;){var i=e[(g+0)%h],j=e[(g+1)%h],k=e[(g+2)%h],l=a[2*i],m=a[2*i+1],n=a[2*j],o=a[2*j+1],p=a[2*k],q=a[2*k+1],r=!1;if(f.PolyK._convex(l,m,n,o,p,q,b)){r=!0;for(var s=0;h>s;s++){var t=e[s];if(t!=i&&t!=j&&t!=k&&f.PolyK._PointInTriangle(a[2*t],a[2*t+1],l,m,n,o,p,q)){r=!1;break}}}if(r)d.push(i,j,k),e.splice((g+1)%h,1),h--,g=0;else if(g++>3*h){if(!b)return console.log("PIXI Warning: shape too complex to fill"),[];var d=[];e=[];for(var g=0;c>g;g++)e.push(g);g=0,h=c,b=!1}}return d.push(e[0],e[1],e[2]),d},f.PolyK._PointInTriangle=function(a,b,c,d,e,f,g,h){var i=g-c,j=h-d,k=e-c,l=f-d,m=a-c,n=b-d,o=i*i+j*j,p=i*k+j*l,q=i*m+j*n,r=k*k+l*l,s=k*m+l*n,t=1/(o*r-p*p),u=(r*q-p*s)*t,v=(o*s-p*q)*t;return u>=0&&v>=0&&1>u+v},f.PolyK._convex=function(a,b,c,d,e,f,g){return(b-d)*(e-c)+(c-a)*(f-d)>=0==g},f.initDefaultShaders=function(){f.primitiveShader=new f.PrimitiveShader,f.primitiveShader.init(),f.stripShader=new f.StripShader,f.stripShader.init(),f.defaultShader=new f.PixiShader,f.defaultShader.init();var a=f.gl,b=f.defaultShader.program;a.useProgram(b),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.primitiveShader.program),a.disableVertexAttribArray(f.defaultShader.aTextureCoord)},f.deactivatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activateStripShader=function(){var a=f.gl;a.useProgram(f.stripShader.program)},f.deactivateStripShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program)},f.CompileVertexShader=function(a,b){return f._CompileShader(a,b,a.VERTEX_SHADER)},f.CompileFragmentShader=function(a,b){return f._CompileShader(a,b,a.FRAGMENT_SHADER)},f._CompileShader=function(a,b,c){var d=b.join("\n"),e=a.createShader(c);return a.shaderSource(e,d),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)?e:(console.log(a.getShaderInfoLog(e)),null)},f.compileProgram=function(a,b){var c=f.gl,d=f.CompileFragmentShader(c,b),e=f.CompileVertexShader(c,a),g=c.createProgram();return c.attachShader(g,e),c.attachShader(g,d),c.linkProgram(g),c.getProgramParameter(g,c.LINK_STATUS)||console.log("Could not initialise shaders"),g},f.PixiShader=function(){this.program,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;","}"]},f.PixiShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc||f.PixiShader.defaultVertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"); -for(var c in this.uniforms)a[c]=b.getUniformLocation(a,c);this.program=a},f.PixiShader.prototype.syncUniforms=function(){var a=f.gl;for(var b in this.uniforms){var c=this.uniforms[b].type;if("f"==c&&a.uniform1f(this.program[b],this.uniforms[b].value),"f2"==c)a.uniform2f(this.program[b],this.uniforms[b].value.x,this.uniforms[b].value.y);else if("f4"==c)a.uniform4fv(this.program[b],this.uniforms[b].value);else if("mat4"==c)a.uniformMatrix4fv(this.program[b],!1,this.uniforms[b].value);else if("sampler2D"==c){var d=this.uniforms[b].value;a.activeTexture(a.TEXTURE1),a.bindTexture(a.TEXTURE_2D,d.baseTexture._glTexture),a.uniform1i(this.program[b],1)}}},f.PixiShader.defaultVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","varying float vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"],f.StripShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying float vColor;","uniform float alpha;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));","gl_FragColor = gl_FragColor * alpha;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","varying vec2 vTextureCoord;","varying vec2 offsetVector;","varying float vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"]},f.StripShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.PrimitiveShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","gl_FragColor = vColor;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec4 aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform float alpha;","varying vec4 vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","vColor = aColor * alpha;","}"]},f.PrimitiveShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.WebGLGraphics=function(){},f.WebGLGraphics.renderGraphics=function(a,b){var c=f.gl;a._webGL||(a._webGL={points:[],indices:[],lastIndex:0,buffer:c.createBuffer(),indexBuffer:c.createBuffer()}),a.dirty&&(a.dirty=!1,a.clearDirty&&(a.clearDirty=!1,a._webGL.lastIndex=0,a._webGL.points=[],a._webGL.indices=[]),f.WebGLGraphics.updateGraphics(a)),f.activatePrimitiveShader();var d=f.mat3.clone(a.worldTransform);f.mat3.transpose(d),c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA),c.uniformMatrix3fv(f.primitiveShader.translationMatrix,!1,d),c.uniform2f(f.primitiveShader.projectionVector,b.x,-b.y),c.uniform2f(f.primitiveShader.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(f.primitiveShader.alpha,a.worldAlpha),c.bindBuffer(c.ARRAY_BUFFER,a._webGL.buffer),c.vertexAttribPointer(f.primitiveShader.aVertexPosition,2,c.FLOAT,!1,24,0),c.vertexAttribPointer(f.primitiveShader.colorAttribute,4,c.FLOAT,!1,24,8),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),c.drawElements(c.TRIANGLE_STRIP,a._webGL.indices.length,c.UNSIGNED_SHORT,0),f.deactivatePrimitiveShader()},f.WebGLGraphics.updateGraphics=function(a){for(var b=a._webGL.lastIndex;b3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){if(a.lineWidth%2)for(var e=0;ee;e++)k=c[2*(e-1)],l=c[2*(e-1)+1],m=c[2*e],n=c[2*e+1],o=c[2*(e+1)],p=c[2*(e+1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,s=-(n-p),t=m-o,E=Math.sqrt(s*s+t*t),s/=E,t/=E,s*=K,t*=K,w=-r+l-(-r+n),x=-q+m-(-q+k),y=(-q+k)*(-r+n)-(-q+m)*(-r+l),z=-t+p-(-t+n),A=-s+m-(-s+o),B=(-s+o)*(-t+n)-(-s+m)*(-t+p),C=w*A-z*x,0==C&&(C+=1),px=(x*B-A*y)/C,py=(z*y-w*B)/C,D=(px-m)*(px-m)+(py-n)+(py-n),D>19600?(u=q-s,v=r-t,E=Math.sqrt(u*u+v*v),u/=E,v/=E,u*=K,v*=K,F.push(m-u,n-v),F.push(N,O,P,M),F.push(m+u,n+v),F.push(N,O,P,M),F.push(m-u,n-v),F.push(N,O,P,M),I++):(F.push(px,py),F.push(N,O,P,M),F.push(m-(px-m),n-(py-n)),F.push(N,O,P,M));k=c[2*(H-2)],l=c[2*(H-2)+1],m=c[2*(H-1)],n=c[2*(H-1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,F.push(m-q,n-r),F.push(N,O,P,M),F.push(m+q,n+r),F.push(N,O,P,M),G.push(J);for(var e=0;I>e;e++)G.push(J++);G.push(J-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},flip=!1;var l=[],m=0;f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;if(a.open)a.data instanceof Array?this.filterManager.pushFilter(a):(m++,l.push(a),c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.INCR),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP));else if(a.data instanceof Array)this.filterManager.popFilter();else{var d=l.pop(a);d&&(c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.DECR),f.WebGLGraphics.renderGraphics(d.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)),c.disable(c.STENCIL_TEST)}},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(){this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;hs?s:E,E=E>t?t:E,E=E>u?u:E,E=E>v?v:E,F=F>w?w:F,F=F>x?x:F,F=F>y?y:F,F=F>z?z:F,C=s>C?s:C,C=t>C?t:C,C=u>C?u:C,C=v>C?v:C,D=w>D?w:D,D=x>D?x:D,D=y>D?y:D,D=z>D?z:D),l=!1,A=A._iNext}while(A!=B);a.filterArea.x=E,a.filterArea.y=F,a.filterArea.width=C-E,a.filterArea.height=D-F},f.FilterTexture=function(a,b){var c=f.gl;this.frameBuffer=c.createFramebuffer(),this.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,this.texture),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.bindFramebuffer(c.FRAMEBUFFER,this.framebuffer),c.bindFramebuffer(c.FRAMEBUFFER,this.frameBuffer),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,this.texture,0),this.resize(a,b)},f.FilterTexture.prototype.resize=function(a,b){this.width=a,this.height=b;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a,b,0,c.RGBA,c.UNSIGNED_BYTE,null)},f.CanvasRenderer=function(a,b,c,d){this.transparent=d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.context=this.view.getContext("2d"),this.refresh=!0,this.view.width=this.width,this.view.height=this.height,this.count=0},f.CanvasRenderer.prototype.constructor=f.CanvasRenderer,f.CanvasRenderer.prototype.render=function(a){f.texturesToUpdate=[],f.texturesToDestroy=[],f.visibleCount++,a.updateTransform(),this.view.style.backgroundColor==a.backgroundColorString||this.transparent||(this.view.style.backgroundColor=a.backgroundColorString),this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.width,this.height),this.renderDisplayObject(a),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0&&(f.Texture.frameUpdates=[])},f.CanvasRenderer.prototype.resize=function(a,b){this.width=a,this.height=b,this.view.width=a,this.view.height=b},f.CanvasRenderer.prototype.renderDisplayObject=function(a){var b,c=this.context;c.globalCompositeOperation="source-over";var d=a.last._iNext;a=a.first;do if(b=a.worldTransform,a.visible)if(a.renderable){if(a instanceof f.Sprite){var e=a.texture.frame;e&&e.width&&e.height&&(c.globalAlpha=a.worldAlpha,c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),c.drawImage(a.texture.baseTexture.source,e.x,e.y,e.width,e.height,a.anchor.x*-e.width,a.anchor.y*-e.height,e.width,e.height))}else if(a instanceof f.Strip)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderStrip(a);else if(a instanceof f.TilingSprite)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderTilingSprite(a);else if(a instanceof f.CustomRenderable)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),a.renderCanvas(this);else if(a instanceof f.Graphics)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),f.CanvasGraphics.renderGraphics(a,c);else if(a instanceof f.FilterBlock&&a.data instanceof f.Graphics){var g=a.data;if(a.open){c.save();var h=g.alpha,i=g.worldTransform;c.setTransform(i[0],i[3],i[1],i[4],i[2],i[5]),g.worldAlpha=.5,c.worldAlpha=0,f.CanvasGraphics.renderGraphicsMask(g,c),c.clip(),g.worldAlpha=h}else c.restore()}a=a._iNext}else a=a._iNext;else a=a.last._iNext;while(a!=d)},f.CanvasRenderer.prototype.renderStripFlat=function(a){var b=this.context,c=a.verticies;a.uvs;var d=c.length/2;this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},f.CanvasRenderer.prototype.renderTilingSprite=function(a){var b=this.context;b.globalAlpha=a.worldAlpha,a.__tilePattern||(a.__tilePattern=b.createPattern(a.texture.baseTexture.source,"repeat")),b.beginPath();var c=a.tilePosition,d=a.tileScale;b.scale(d.x,d.y),b.translate(c.x,c.y),b.fillStyle=a.__tilePattern,b.fillRect(-c.x,-c.y,a.width/d.x,a.height/d.y),b.scale(1/d.x,1/d.y),b.translate(-c.x,-c.y),b.closePath()},f.CanvasRenderer.prototype.renderStrip=function(a){var b=this.context,c=a.verticies,d=a.uvs,e=c.length/2;this.count++;for(var f=1;e-2>f;f++){var g=2*f,h=c[g],i=c[g+2],j=c[g+4],k=c[g+1],l=c[g+3],m=c[g+5],n=d[g]*a.texture.width,o=d[g+2]*a.texture.width,p=d[g+4]*a.texture.width,q=d[g+1]*a.texture.height,r=d[g+3]*a.texture.height,s=d[g+5]*a.texture.height;b.save(),b.beginPath(),b.moveTo(h,k),b.lineTo(i,l),b.lineTo(j,m),b.closePath(),b.clip();var t=n*r+q*p+o*s-r*p-q*o-n*s,u=h*r+q*j+i*s-r*j-q*i-h*s,v=n*i+h*p+o*j-i*p-h*o-n*j,w=n*r*j+q*i*p+h*o*s-h*r*p-q*o*j-n*i*s,x=k*r+q*m+l*s-r*m-q*l-k*s,y=n*l+k*p+o*m-l*p-k*o-n*m,z=n*r*m+q*l*p+k*o*s-k*r*p-q*o*m-n*l*s;b.transform(u/t,x/t,v/t,y/t,w/t,z/t),b.drawImage(a.texture.baseTexture.source,0,0),b.restore()}},f.CanvasGraphics=function(){},f.CanvasGraphics.renderGraphics=function(a,b){for(var c=a.worldAlpha,d=0;d1&&(c=1,console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var d=0;1>d;d++){var e=a.graphicsData[d],g=e.points;if(e.type==f.Graphics.POLY){b.beginPath(),b.moveTo(g[0],g[1]);for(var h=1;hb?b:d,e=b+m>e?b+m:e,g=g>c?b:g,h=c+n>h?c+n:h}else if(k===f.Graphics.CIRC||k===f.Graphics.ELIP){b=a.x,c=a.y;var o=a.radius+l/2;d=d>b-o?b-o:d,e=b+o>e?b+o:e,g=g>c-o?c-o:g,h=c+o>h?c+o:h}else for(var p=0;pb-l?b-l:d,e=b+l>e?b+l:e,g=g>c-l?c-l:g,h=c+l>h?c+l:h}this.bounds=new f.Rectangle(d,g,e-d,h-g)}},f.Graphics.POLY=0,f.Graphics.RECT=1,f.Graphics.CIRC=2,f.Graphics.ELIP=3,f.Strip=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.blendMode=f.blendModes.NORMAL;try{this.uvs=new Float32Array([0,1,1,1,1,0,0,1]),this.verticies=new Float32Array([0,0,0,0,0,0,0,0,0]),this.colors=new Float32Array([1,1,1,1]),this.indices=new Uint16Array([0,1,2,3])}catch(d){this.uvs=[0,1,1,1,1,0,0,1],this.verticies=[0,0,0,0,0,0,0,0,0],this.colors=[1,1,1,1],this.indices=[0,1,2,3]}this.width=b,this.height=c,a.baseTexture.hasLoaded?(this.width=this.texture.frame.width,this.height=this.texture.frame.height,this.updateFrame=!0):(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Strip.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Strip.prototype.constructor=f.Strip,f.Strip.prototype.setTexture=function(a){this.texture=a,this.width=a.frame.width,this.height=a.frame.height,this.updateFrame=!0},f.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Rope=function(a,b){f.Strip.call(this,a),this.points=b;try{this.verticies=new Float32Array(4*b.length),this.uvs=new Float32Array(4*b.length),this.colors=new Float32Array(2*b.length),this.indices=new Uint16Array(2*b.length)}catch(c){this.verticies=verticies,this.uvs=uvs,this.colors=colors,this.indices=indices}this.refresh()},f.Rope.prototype=Object.create(f.Strip.prototype),f.Rope.prototype.constructor=f.Rope,f.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=this.indices,d=this.colors,e=a[0],f=a[0];this.count-=.2,b[0]=0,b[1]=1,b[2]=0,b[3]=1,d[0]=1,d[1]=1,c[0]=0,c[1]=1;for(var g=a.length,h=1;g>h;h++){var f=a[h],i=4*h,j=h/(g-1);h%2?(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1):(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1),i=2*h,d[i]=1,d[i+1]=1,i=2*h,c[i]=i,c[i+1]=i+1,e=f}}},f.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var b,c=this.verticies,d=a[0],e={x:0,y:0},g=a[0];this.count-=.2,c[0]=g.x+e.x,c[1]=g.y+e.y,c[2]=g.x-e.x,c[3]=g.y-e.y;for(var h=a.length,i=1;h>i;i++){var g=a[i],j=4*i;b=i1&&(k=1);var l=Math.sqrt(e.x*e.x+e.y*e.y),m=this.texture.height/2;e.x/=l,e.y/=l,e.x*=m,e.y*=m,c[j]=g.x+e.x,c[j+1]=g.y+e.y,c[j+2]=g.x-e.x,c[j+3]=g.y-e.y,d=g}f.DisplayObjectContainer.prototype.updateTransform.call(this)}},f.Rope.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.width=b,this.height=c,this.tileScale=new f.Point(1,1),this.tilePosition=new f.Point(0,0),this.renderable=!0,this.blendMode=f.blendModes.NORMAL},f.TilingSprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.TilingSprite.prototype.constructor=f.TilingSprite,f.TilingSprite.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Spine=function(a){if(f.DisplayObjectContainer.call(this),this.spineData=f.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new n.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new n.AnimationStateData(this.spineData),this.state=new n.AnimationState(this.stateData),this.slotContainers=[];for(var b=0,c=this.skeleton.drawOrder.length;c>b;b++){var d=this.skeleton.drawOrder[b],e=d.attachment,g=new f.DisplayObjectContainer;if(this.slotContainers.push(g),this.addChild(g),e instanceof n.RegionAttachment){var h=e.rendererObject.name,i=this.createSprite(d,e.rendererObject);d.currentSprite=i,d.currentSpriteName=h,g.addChild(i)}}},f.Spine.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Spine.prototype.constructor=f.Spine,f.Spine.prototype.updateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var b=this.skeleton.drawOrder,c=0,d=b.length;d>c;c++){var e=b[c],g=e.attachment,h=this.slotContainers[c];if(g instanceof n.RegionAttachment){if(g.rendererObject&&(!e.currentSpriteName||e.currentSpriteName!=g.name)){var i=g.rendererObject.name;if(void 0!==e.currentSprite&&(e.currentSprite.visible=!1),e.sprites=e.sprites||{},void 0!==e.sprites[i])e.sprites[i].visible=!0;else{var j=this.createSprite(e,g.rendererObject);h.addChild(j)}e.currentSprite=e.sprites[i],e.currentSpriteName=i}h.visible=!0;var k=e.bone;h.position.x=k.worldX+g.x*k.m00+g.y*k.m01,h.position.y=k.worldY+g.x*k.m10+g.y*k.m11,h.scale.x=k.worldScaleX,h.scale.y=k.worldScaleY,h.rotation=-(e.bone.worldRotation*Math.PI/180)}else h.visible=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.Spine.prototype.createSprite=function(a,b){var c=f.TextureCache[b.name]?b.name:b.name+".png",d=new f.Sprite(f.Texture.fromFrame(c));return d.scale=b.scale,d.rotation=b.rotation,d.anchor.x=d.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[b.name]=d,d};var n={};n.BoneData=function(a,b){this.name=a,this.parent=b},n.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1},n.SlotData=function(a,b){this.name=a,this.boneData=b},n.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null},n.Bone=function(a,b){this.data=a,this.parent=b,this.setToSetupPose()},n.Bone.yDown=!1,n.Bone.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,updateWorldTransform:function(a,b){var c=this.parent;null!=c?(this.worldX=this.x*c.m00+this.y*c.m01+c.worldX,this.worldY=this.x*c.m10+this.y*c.m11+c.worldY,this.worldScaleX=c.worldScaleX*this.scaleX,this.worldScaleY=c.worldScaleY*this.scaleY,this.worldRotation=c.worldRotation+this.rotation):(this.worldX=this.x,this.worldY=this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotation);var d=this.worldRotation*Math.PI/180,e=Math.cos(d),f=Math.sin(d);this.m00=e*this.worldScaleX,this.m10=f*this.worldScaleX,this.m01=-f*this.worldScaleY,this.m11=e*this.worldScaleY,a&&(this.m00=-this.m00,this.m01=-this.m01),b&&(this.m10=-this.m10,this.m11=-this.m11),n.Bone.yDown&&(this.m10=-this.m10,this.m11=-this.m11)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY}},n.Slot=function(a,b,c){this.data=a,this.skeleton=b,this.bone=c,this.setToSetupPose()},n.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,setAttachment:function(a){this.attachment=a,this._attachmentTime=this.skeleton.time},setAttachmentTime:function(a){this._attachmentTime=this.skeleton.time-a},getAttachmentTime:function(){return this.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},n.Skin=function(a){this.name=a,this.attachments={}},n.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},n.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},n.Animation.prototype={apply:function(a,b,c){c&&0!=this.duration&&(b%=this.duration);for(var d=this.timelines,e=0,f=d.length;f>e;e++)d[e].apply(a,b,1)},mix:function(a,b,c,d){c&&0!=this.duration&&(b%=this.duration);for(var e=this.timelines,f=0,g=e.length;g>f;f++)e[f].apply(a,b,d)}},n.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(0==e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},n.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},n.Curves=function(a){this.curves=[],this.curves.length=6*(a-1)},n.Curves.prototype={setLinear:function(a){this.curves[6*a]=0},setStepped:function(a){this.curves[6*a]=-1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=6*a,r=this.curves;r[q]=b*i+m*j+o*h,r[q+1]=c*i+n*j+p*h,r[q+2]=m*k+o*l,r[q+3]=n*k+p*l,r[q+4]=o*l,r[q+5]=p*l},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=6*a,d=this.curves,e=d[c];if(!e)return b;if(-1==e)return 0;for(var f=d[c+1],g=d[c+2],h=d[c+3],i=d[c+4],j=d[c+5],k=e,l=f,m=8;;){if(k>=b){var n=k-e,o=l-f;return o+(l-o)*(b-n)/(k-n)}if(0==m)break;m--,e+=g,f+=h,g+=i,h+=j,k+=e,l+=f}return l+(1-l)*(b-k)/(1-k)}},n.RotateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=2*a},n.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-2]){for(var f=e.data.rotation+d[d.length-1]-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;return e.rotation+=f*c,void 0}var g=n.binarySearch(d,b,2),h=d[g-1],i=d[g],j=1-(b-i)/(d[g-2]-i);j=this.curves.getCurvePercent(g/2-1,j);for(var f=d[g+1]-h;f>180;)f-=360;for(;-180>f;)f+=360;for(f=e.data.rotation+(h+f*j)-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;e.rotation+=f*c}}},n.TranslateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.x+=(e.data.x+d[d.length-2]-e.x)*c,e.y+=(e.data.y+d[d.length-1]-e.y)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.x+=(e.data.x+g+(d[f+1]-g)*j-e.x)*c,e.y+=(e.data.y+h+(d[f+2]-h)*j-e.y)*c}}},n.ScaleTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.scaleX+=(e.data.scaleX-1+d[d.length-2]-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+d[d.length-1]-e.scaleY)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.scaleX+=(e.data.scaleX-1+g+(d[f+1]-g)*j-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+h+(d[f+2]-h)*j-e.scaleY)*c}}},n.ColorTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=5*a},n.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(c,d){c*=5,this.frames[c]=d,this.frames[c+1]=r,this.frames[c+2]=g,this.frames[c+3]=b,this.frames[c+4]=a},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-5]){var f=d.length-1;return e.r=d[f-3],e.g=d[f-2],e.b=d[f-1],e.a=d[f],void 0}var g=n.binarySearch(d,b,5),h=d[g-4],i=d[g-3],j=d[g-2],k=d[g-1],l=d[g],m=1-(b-l)/(d[g-5]-l);m=this.curves.getCurvePercent(g/5-1,m);var o=h+(d[g+1]-h)*m,p=i+(d[g+2]-i)*m,q=j+(d[g+3]-j)*m,r=k+(d[g+4]-k)*m;1>c?(e.r+=(o-e.r)*c,e.g+=(p-e.g)*c,e.b+=(q-e.b)*c,e.a+=(r-e.a)*c):(e.r=o,e.g=p,e.b=q,e.a=r)}}},n.AttachmentTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},n.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b){var c=this.frames;if(!(b=c[c.length-1]?c.length-1:n.binarySearch(c,b,1)-1;var e=this.attachmentNames[d];a.slots[this.slotIndex].setAttachment(e?a.getAttachmentBySlotIndex(this.slotIndex,e):null)}}},n.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.animations=[]},n.SkeletonData.prototype={defaultSkin:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},n.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,c=a.bones.length;c>b;b++){var d=a.bones[b],e=d.parent?this.bones[a.bones.indexOf(d.parent)]:null;this.bones.push(new n.Bone(d,e))}this.slots=[],this.drawOrder=[];for(var b=0,c=a.slots.length;c>b;b++){var f=a.slots[b],g=this.bones[a.bones.indexOf(f.boneData)],h=new n.Slot(f,this,g);this.slots.push(h),this.drawOrder.push(h)}},n.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateWorldTransform:function(){for(var a=this.flipX,b=this.flipY,c=this.bones,d=0,e=c.length;e>d;d++)c[d].updateWorldTransform(a,b)},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose()},setSlotsToSetupPose:function(){for(var a=this.slots,b=0,c=a.length;c>b;b++)a[b].setToSetupPose(b)},getRootBone:function(){return 0==this.bones.length?null:this.bones[0]},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a);if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){this.skin&&a&&a._attachAll(this,this.skin),this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.size;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachment(d,b),null==g))throw"Attachment not found: "+b+", for slot: "+a;return f.setAttachment(g),void 0}}throw"Slot not found: "+a},update:function(a){time+=a}},n.AttachmentType={region:0},n.RegionAttachment=function(){this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},n.RegionAttachment.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,c=-this.width/2*this.scaleX+this.regionOffsetX*a,d=-this.height/2*this.scaleY+this.regionOffsetY*b,e=c+this.regionWidth*a,f=d+this.regionHeight*b,g=this.rotation*Math.PI/180,h=Math.cos(g),i=Math.sin(g),j=c*h+this.x,k=c*i,l=d*h+this.y,m=d*i,n=e*h+this.x,o=e*i,p=f*h+this.y,q=f*i,r=this.offset;r[0]=j-m,r[1]=l+k,r[2]=j-q,r[3]=p+k,r[4]=n-q,r[5]=p+o,r[6]=n-m,r[7]=l+o},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},n.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},n.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=this.animationToMixTime[a.name+":"+b.name];return c?c:this.defaultMix}},n.AnimationState=function(a){this.data=a,this.queue=[]},n.AnimationState.prototype={current:null,previous:null,currentTime:0,previousTime:0,currentLoop:!1,previousLoop:!1,mixTime:0,mixDuration:0,update:function(a){if(this.currentTime+=a,this.previousTime+=a,this.mixTime+=a,this.queue.length>0){var b=this.queue[0];this.currentTime>=b.delay&&(this._setAnimation(b.animation,b.loop),this.queue.shift())}},apply:function(a){if(this.current)if(this.previous){this.previous.apply(a,this.previousTime,this.previousLoop);var b=this.mixTime/this.mixDuration;b>=1&&(b=1,this.previous=null),this.current.mix(a,this.currentTime,this.currentLoop,b)}else this.current.apply(a,this.currentTime,this.currentLoop)},clearAnimation:function(){this.previous=null,this.current=null,this.queue.length=0},_setAnimation:function(a,b){this.previous=null,a&&this.current&&(this.mixDuration=this.data.getMix(this.current,a),this.mixDuration>0&&(this.mixTime=0,this.previous=this.current,this.previousTime=this.currentTime,this.previousLoop=this.currentLoop)),this.current=a,this.currentLoop=b,this.currentTime=0},setAnimationByName:function(a,b){var c=this.data.skeletonData.findAnimation(a);if(!c)throw"Animation not found: "+a;this.setAnimation(c,b)},setAnimation:function(a,b){this.queue.length=0,this._setAnimation(a,b)},addAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;this.addAnimation(d,b,c)},addAnimation:function(a,b,c){var d={};if(d.animation=a,d.loop=b,!c||0>=c){var e=0==this.queue.length?this.current:this.queue[this.queue.length-1].animation;c=null!=e?e.duration-this.data.getMix(e,a)+(c||0):0}d.delay=c,this.queue.push(d)},isComplete:function(){return!this.current||this.currentTime>=this.current.duration}},n.SkeletonJson=function(a){this.attachmentLoader=a},n.SkeletonJson.prototype={scale:1,readSkeletonData:function(a){for(var b=new n.SkeletonData,c=a.bones,d=0,e=c.length;e>d;d++){var f=c[d],g=null;if(f.parent&&(g=b.findBone(f.parent),!g))throw"Parent bone not found: "+f.parent;var h=new n.BoneData(f.name,g);h.length=(f.length||0)*this.scale,h.x=(f.x||0)*this.scale,h.y=(f.y||0)*this.scale,h.rotation=f.rotation||0,h.scaleX=f.scaleX||1,h.scaleY=f.scaleY||1,b.bones.push(h)}for(var i=a.slots,d=0,e=i.length;e>d;d++){var j=i[d],h=b.findBone(j.bone);if(!h)throw"Slot bone not found: "+j.bone;var k=new n.SlotData(j.name,h),l=j.color;l&&(k.r=n.SkeletonJson.toColor(l,0),k.g=n.SkeletonJson.toColor(l,1),k.b=n.SkeletonJson.toColor(l,2),k.a=n.SkeletonJson.toColor(l,3)),k.attachmentName=j.attachment,b.slots.push(k)}var m=a.skins;for(var o in m)if(m.hasOwnProperty(o)){var p=m[o],q=new n.Skin(o);for(var r in p)if(p.hasOwnProperty(r)){var s=b.findSlotIndex(r),t=p[r];for(var u in t)if(t.hasOwnProperty(u)){var v=this.readAttachment(q,u,t[u]);null!=v&&q.addAttachment(s,u,v)}}b.skins.push(q),"default"==q.name&&(b.defaultSkin=q)}var w=a.animations;for(var x in w)w.hasOwnProperty(x)&&this.readAnimation(x,w[x],b);return b},readAttachment:function(a,b,c){b=c.name||b;var d=n.AttachmentType[c.type||"region"];if(d==n.AttachmentType.region){var e=new n.RegionAttachment;return e.x=(c.x||0)*this.scale,e.y=(c.y||0)*this.scale,e.scaleX=c.scaleX||1,e.scaleY=c.scaleY||1,e.rotation=c.rotation||0,e.width=(c.width||32)*this.scale,e.height=(c.height||32)*this.scale,e.updateOffset(),e.rendererObject={},e.rendererObject.name=b,e.rendererObject.scale={},e.rendererObject.scale.x=e.scaleX,e.rendererObject.scale.y=e.scaleY,e.rendererObject.rotation=-e.rotation*Math.PI/180,e -}throw"Unknown attachment type: "+d},readAnimation:function(a,b,c){var d=[],e=0,f=b.bones;for(var g in f)if(f.hasOwnProperty(g)){var h=c.findBoneIndex(g);if(-1==h)throw"Bone not found: "+g;var i=f[g];for(var j in i)if(i.hasOwnProperty(j)){var k=i[j];if("rotate"==j){var l=new n.RotateTimeline(k.length);l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m,q.time,q.angle),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[2*l.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var l,r=1;"scale"==j?l=new n.ScaleTimeline(k.length):(l=new n.TranslateTimeline(k.length),r=this.scale),l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;l.setFrame(m,q.time,s,t),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[3*l.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var l=new n.ColorTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=n.SkeletonJson.toColor(y,0),A=n.SkeletonJson.toColor(y,1),B=n.SkeletonJson.toColor(y,2),C=n.SkeletonJson.toColor(y,3);l.setFrame(m,q.time,z,A,B,C),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[5*l.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var l=new n.AttachmentTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m++,q.time,q.name)}d.push(l),e=Math.max(e,l.frames[l.getFrameCount()-1])}}}c.animations.push(new n.Animation(a,d,e))}},n.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},n.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},n.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new n.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new n.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new n.AtlasPage,e.name=f,e.format=n.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=n.Atlas.TextureFilter[d[0]],e.magFilter=n.Atlas.TextureFilter[d[1]];var l=c.readValue();e.uWrap=n.Atlas.TextureWrap.clampToEdge,e.vWrap=n.Atlas.TextureWrap.clampToEdge,"x"==l?e.uWrap=n.Atlas.TextureWrap.repeat:"y"==l?e.vWrap=n.Atlas.TextureWrap.repeat:"xy"==l&&(e.uWrap=e.vWrap=n.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},n.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},n.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},n.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},n.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},n.AtlasPage=function(){},n.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},n.AtlasRegion=function(){},n.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},n.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},n.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},n.AtlasAttachmentLoader=function(a){this.atlas=a},n.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case n.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new n.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},n.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;h>16)/255,(255&a>>8)/255,(255&a)/255]}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}var e=this,f=f||{};f.Point=function(a,b){this.x=a||0,this.y=b||0},f.Point.prototype.clone=function(){return new f.Point(this.x,this.y)},f.Point.prototype.constructor=f.Point,f.Rectangle=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Rectangle.prototype.clone=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Rectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},f.Rectangle.prototype.constructor=f.Rectangle,f.Polygon=function(a){if(a instanceof Array||(a=Array.prototype.slice.call(arguments)),"number"==typeof a[0]){for(var b=[],c=0,d=a.length;d>c;c+=2)b.push(new f.Point(a[c],a[c+1]));a=b}this.points=a},f.Polygon.prototype.clone=function(){for(var a=[],b=0;bb!=i>b&&(h-f)*(b-g)/(i-g)+f>a;j&&(c=!c)}return c},f.Polygon.prototype.constructor=f.Polygon,f.Circle=function(a,b,c){this.x=a||0,this.y=b||0,this.radius=c||0},f.Circle.prototype.clone=function(){return new f.Circle(this.x,this.y,this.radius)},f.Circle.prototype.contains=function(a,b){if(this.radius<=0)return!1;var c=this.x-a,d=this.y-b,e=this.radius*this.radius;return c*=c,d*=d,e>=c+d},f.Circle.prototype.constructor=f.Circle,f.Ellipse=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Ellipse.prototype.clone=function(){return new f.Ellipse(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=(a-this.x)/this.width-.5,d=(b-this.y)/this.height-.5;return c*=c,d*=d,.25>c+d},f.Ellipse.getBounds=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.constructor=f.Ellipse,c(),f.mat3={},f.mat3.create=function(){var a=new f.Matrix(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat3.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat4={},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat3.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=b[0],n=b[1],o=b[2],p=b[3],q=b[4],r=b[5],s=b[6],t=b[7],u=b[8];return c[0]=m*d+n*g+o*j,c[1]=m*e+n*h+o*k,c[2]=m*f+n*i+o*l,c[3]=p*d+q*g+r*j,c[4]=p*e+q*h+r*k,c[5]=p*f+q*i+r*l,c[6]=s*d+t*g+u*j,c[7]=s*e+t*h+u*k,c[8]=s*f+t*i+u*l,c},f.mat3.clone=function(a){var b=new f.Matrix(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},f.mat3.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[5];return a[1]=a[3],a[2]=a[6],a[3]=c,a[5]=a[7],a[6]=d,a[7]=e,a}return b[0]=a[0],b[1]=a[3],b[2]=a[6],b[3]=a[1],b[4]=a[4],b[5]=a[7],b[6]=a[2],b[7]=a[5],b[8]=a[8],b},f.mat3.toMat4=function(a,b){return b||(b=f.mat4.create()),b[15]=1,b[14]=0,b[13]=0,b[12]=0,b[11]=0,b[10]=a[8],b[9]=a[7],b[8]=a[6],b[7]=0,b[6]=a[5],b[5]=a[4],b[4]=a[3],b[3]=0,b[2]=a[2],b[1]=a[1],b[0]=a[0],b},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat4.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[3],f=a[6],g=a[7],h=a[11];return a[1]=a[4],a[2]=a[8],a[3]=a[12],a[4]=c,a[6]=a[9],a[7]=a[13],a[8]=d,a[9]=f,a[11]=a[14],a[12]=e,a[13]=g,a[14]=h,a}return b[0]=a[0],b[1]=a[4],b[2]=a[8],b[3]=a[12],b[4]=a[1],b[5]=a[5],b[6]=a[9],b[7]=a[13],b[8]=a[2],b[9]=a[6],b[10]=a[10],b[11]=a[14],b[12]=a[3],b[13]=a[7],b[14]=a[11],b[15]=a[15],b},f.mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=b[0],u=b[1],v=b[2],w=b[3];return c[0]=t*d+u*h+v*l+w*p,c[1]=t*e+u*i+v*m+w*q,c[2]=t*f+u*j+v*n+w*r,c[3]=t*g+u*k+v*o+w*s,t=b[4],u=b[5],v=b[6],w=b[7],c[4]=t*d+u*h+v*l+w*p,c[5]=t*e+u*i+v*m+w*q,c[6]=t*f+u*j+v*n+w*r,c[7]=t*g+u*k+v*o+w*s,t=b[8],u=b[9],v=b[10],w=b[11],c[8]=t*d+u*h+v*l+w*p,c[9]=t*e+u*i+v*m+w*q,c[10]=t*f+u*j+v*n+w*r,c[11]=t*g+u*k+v*o+w*s,t=b[12],u=b[13],v=b[14],w=b[15],c[12]=t*d+u*h+v*l+w*p,c[13]=t*e+u*i+v*m+w*q,c[14]=t*f+u*j+v*n+w*r,c[15]=t*g+u*k+v*o+w*s,c},f.DisplayObject=function(){this.last=this,this.first=this,this.position=new f.Point,this.scale=new f.Point(1,1),this.pivot=new f.Point(0,0),this.rotation=0,this.alpha=1,this.visible=!0,this.hitArea=null,this.buttonMode=!1,this.renderable=!1,this.parent=null,this.stage=null,this.worldAlpha=1,this._interactive=!1,this.worldTransform=f.mat3.create(),this.localTransform=f.mat3.create(),this.color=[],this.dynamic=!0,this._sr=0,this._cr=1,this.filterArea=new f.Rectangle(0,0,1,1)},f.DisplayObject.prototype.constructor=f.DisplayObject,f.DisplayObject.prototype.setInteractive=function(a){this.interactive=a},Object.defineProperty(f.DisplayObject.prototype,"interactive",{get:function(){return this._interactive},set:function(a){this._interactive=a,this.stage&&(this.stage.dirty=!0)}}),Object.defineProperty(f.DisplayObject.prototype,"mask",{get:function(){return this._mask},set:function(a){a?this._mask?(a.start=this._mask.start,a.end=this._mask.end):(this.addFilter(a),a.renderable=!1):(this.removeFilter(this._mask),this._mask.renderable=!0),this._mask=a}}),Object.defineProperty(f.DisplayObject.prototype,"filters",{get:function(){return this._filters},set:function(a){if(a){this._filters&&this.removeFilter(this._filters),this.addFilter(a);for(var b=[],c=0;c=0&&b<=this.children.length))throw new Error(a+" The index "+b+" supplied is out of bounds "+this.children.length);if(void 0!=a.parent&&a.parent.removeChild(a),a.parent=this,this.stage){var c=a;do c.interactive&&(this.stage.dirty=!0),c.stage=this.stage,c=c._iNext;while(c)}var d,e,f=a.first,g=a.last;if(b==this.children.length){e=this.last;for(var h=this,i=this.last;h;)h.last==i&&(h.last=a.last),h=h.parent}else e=0==b?this:this.children[b-1].last;d=e._iNext,d&&(d._iPrev=g,g._iNext=d),f._iPrev=e,e._iNext=f,this.children.splice(b,0,a),this.__renderGroup&&(a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a),this.__renderGroup.addDisplayObjectAndChildren(a))},f.DisplayObjectContainer.prototype.swapChildren=function(){},f.DisplayObjectContainer.prototype.getChildAt=function(a){if(a>=0&&aa;a++)this.children[a].updateTransform()}},f.blendModes={},f.blendModes.NORMAL=0,f.blendModes.SCREEN=1,f.Sprite=function(a){f.DisplayObjectContainer.call(this),this.anchor=new f.Point,this.texture=a,this.blendMode=f.blendModes.NORMAL,this._width=0,this._height=0,a.baseTexture.hasLoaded?this.updateFrame=!0:(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Sprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Sprite.prototype.constructor=f.Sprite,Object.defineProperty(f.Sprite.prototype,"width",{get:function(){return this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(f.Sprite.prototype,"height",{get:function(){return this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),f.Sprite.prototype.setTexture=function(a){this.texture.baseTexture!=a.baseTexture?(this.textureChange=!0,this.texture=a,this.__renderGroup&&this.__renderGroup.updateTexture(this)):this.texture=a,this.updateFrame=!0},f.Sprite.prototype.onTextureUpdate=function(){this._width&&(this.scale.x=this._width/this.texture.frame.width),this._height&&(this.scale.y=this._height/this.texture.frame.height),this.updateFrame=!0},f.Sprite.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache"+this);return new f.Sprite(b)},f.Sprite.fromImage=function(a){var b=f.Texture.fromImage(a);return new f.Sprite(b)},f.MovieClip=function(a){f.Sprite.call(this,a[0]),this.textures=a,this.animationSpeed=1,this.loop=!0,this.onComplete=null,this.currentFrame=0,this.playing=!1},f.MovieClip.prototype=Object.create(f.Sprite.prototype),f.MovieClip.prototype.constructor=f.MovieClip,Object.defineProperty(f.MovieClip.prototype,"totalFrames",{get:function(){return this.textures.length}}),f.MovieClip.prototype.stop=function(){this.playing=!1},f.MovieClip.prototype.play=function(){this.playing=!0},f.MovieClip.prototype.gotoAndStop=function(a){this.playing=!1,this.currentFrame=a;var b=0|this.currentFrame+.5;this.setTexture(this.textures[b%this.textures.length])},f.MovieClip.prototype.gotoAndPlay=function(a){this.currentFrame=a,this.playing=!0},f.MovieClip.prototype.updateTransform=function(){if(f.Sprite.prototype.updateTransform.call(this),this.playing){this.currentFrame+=this.animationSpeed;var a=0|this.currentFrame+.5;this.loop||a=this.textures.length&&(this.gotoAndStop(this.textures.length-1),this.onComplete&&this.onComplete())}},f.FilterBlock=function(){this.visible=!0,this.renderable=!0},f.Text=function(a,b){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),f.Sprite.call(this,f.Texture.fromCanvas(this.canvas)),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.Text.prototype=Object.create(f.Sprite.prototype),f.Text.prototype.constructor=f.Text,f.Text.prototype.setStyle=function(a){a=a||{},a.font=a.font||"bold 20pt Arial",a.fill=a.fill||"black",a.align=a.align||"left",a.stroke=a.stroke||"black",a.strokeThickness=a.strokeThickness||0,a.wordWrap=a.wordWrap||!1,a.wordWrapWidth=a.wordWrapWidth||100,this.style=a,this.dirty=!0},f.Text.prototype.setText=function(a){this.text=a.toString()||" ",this.dirty=!0},f.Text.prototype.updateText=function(){this.context.font=this.style.font;var a=this.text;this.style.wordWrap&&(a=this.wordWrap(this.text));for(var b=a.split(/(?:\r\n|\r|\n)/),c=[],d=0,e=0;ee?f:arguments.callee(a,b,f,d,e):arguments.callee(a,b,c,f,e)},c=function(a,c,d){if(a.measureText(c).width<=d||c.length<1)return c;var e=b(a,c,0,c.length,d);return c.substring(0,e)+"\n"+arguments.callee(a,c.substring(e),d)},d="",e=a.split("\n"),f=0;f=2?parseInt(b[b.length-2],10):f.BitmapText.fonts[this.fontName].size,this.dirty=!0},f.BitmapText.prototype.updateText=function(){for(var a=f.BitmapText.fonts[this.fontName],b=new f.Point,c=null,d=[],e=0,g=[],h=0,i=this.fontSize/a.size,j=0;j=j;j++){var n=0;"right"==this.style.align?n=e-g[j]:"center"==this.style.align&&(n=(e-g[j])/2),m.push(n)}for(j=0;j0;)this.removeChild(this.getChildAt(0));this.updateText(),this.dirty=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.BitmapText.fonts={},f.InteractionManager=function(a){this.stage=a,this.mouse=new f.InteractionData,this.touchs={},this.tempPoint=new f.Point,this.mouseoverEnabled=!0,this.pool=[],this.interactiveItems=[],this.interactionDOMElement=null,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseOut=this.onMouseOut.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.last=0},f.InteractionManager.prototype.constructor=f.InteractionManager,f.InteractionManager.prototype.collectInteractiveSprite=function(a,b){for(var c=a.children,d=c.length,e=d-1;e>=0;e--){var f=c[e];f.interactive?(b.interactiveChildren=!0,this.interactiveItems.push(f),f.children.length>0&&this.collectInteractiveSprite(f,f)):(f.__iParent=null,f.children.length>0&&this.collectInteractiveSprite(f,b))}},f.InteractionManager.prototype.setTarget=function(a){this.target=a,null===this.interactionDOMElement&&this.setTargetDomElement(a.view),document.body.addEventListener("mouseup",this.onMouseUp,!0)},f.InteractionManager.prototype.setTargetDomElement=function(a){null!==this.interactionDOMElement&&(this.interactionDOMElement.style["-ms-content-zooming"]="",this.interactionDOMElement.style["-ms-touch-action"]="",this.interactionDOMElement.removeEventListener("mousemove",this.onMouseMove,!0),this.interactionDOMElement.removeEventListener("mousedown",this.onMouseDown,!0),this.interactionDOMElement.removeEventListener("mouseout",this.onMouseOut,!0),this.interactionDOMElement.removeEventListener("touchstart",this.onTouchStart,!0),this.interactionDOMElement.removeEventListener("touchend",this.onTouchEnd,!0),this.interactionDOMElement.removeEventListener("touchmove",this.onTouchMove,!0)),window.navigator.msPointerEnabled&&(a.style["-ms-content-zooming"]="none",a.style["-ms-touch-action"]="none"),this.interactionDOMElement=a,a.addEventListener("mousemove",this.onMouseMove,!0),a.addEventListener("mousedown",this.onMouseDown,!0),a.addEventListener("mouseout",this.onMouseOut,!0),a.addEventListener("touchstart",this.onTouchStart,!0),a.addEventListener("touchend",this.onTouchEnd,!0),a.addEventListener("touchmove",this.onTouchMove,!0)},f.InteractionManager.prototype.update=function(){if(this.target){var a=Date.now(),b=a-this.last;if(b=30*b/1e3,!(1>b)){if(this.last=a,this.dirty){this.dirty=!1;for(var c=this.interactiveItems.length,d=0;c>d;d++)this.interactiveItems[d].interactiveChildren=!1;this.interactiveItems=[],this.stage.interactive&&this.interactiveItems.push(this.stage),this.collectInteractiveSprite(this.stage,this.stage)}var e=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var d=0;e>d;d++){var f=this.interactiveItems[d];(f.mouseover||f.mouseout||f.buttonMode)&&(f.__hit=this.hitTest(f,this.mouse),this.mouse.target=f,f.__hit?(f.buttonMode&&(this.interactionDOMElement.style.cursor="pointer"),f.__isOver||(f.mouseover&&f.mouseover(this.mouse),f.__isOver=!0)):f.__isOver&&(f.mouseout&&f.mouseout(this.mouse),f.__isOver=!1))}}}},f.InteractionManager.prototype.onMouseMove=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactionDOMElement.getBoundingClientRect();this.mouse.global.x=(a.clientX-b.left)*(this.target.width/b.width),this.mouse.global.y=(a.clientY-b.top)*(this.target.height/b.height);var c=this.interactiveItems.length;this.mouse.global;for(var d=0;c>d;d++){var e=this.interactiveItems[d];e.mousemove&&e.mousemove(this.mouse)}},f.InteractionManager.prototype.onMouseDown=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactiveItems.length;this.mouse.global,this.stage;for(var c=0;b>c;c++){var d=this.interactiveItems[c];if((d.mousedown||d.click)&&(d.__mouseIsDown=!0,d.__hit=this.hitTest(d,this.mouse),d.__hit&&(d.mousedown&&d.mousedown(this.mouse),d.__isDown=!0,!d.interactiveChildren)))break}},f.InteractionManager.prototype.onMouseOut=function(){var a=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var b=0;a>b;b++){var c=this.interactiveItems[b];c.__isOver&&(this.mouse.target=c,c.mouseout&&c.mouseout(this.mouse),c.__isOver=!1)}},f.InteractionManager.prototype.onMouseUp=function(a){this.mouse.originalEvent=a||window.event,this.mouse.global;for(var b=this.interactiveItems.length,c=!1,d=0;b>d;d++){var e=this.interactiveItems[d];(e.mouseup||e.mouseupoutside||e.click)&&(e.__hit=this.hitTest(e,this.mouse),e.__hit&&!c?(e.mouseup&&e.mouseup(this.mouse),e.__isDown&&e.click&&e.click(this.mouse),e.interactiveChildren||(c=!0)):e.__isDown&&e.mouseupoutside&&e.mouseupoutside(this.mouse),e.__isDown=!1)}},f.InteractionManager.prototype.hitTest=function(a,b){var c=b.global;if(a.vcount!==f.visibleCount)return!1;var d=a instanceof f.Sprite,e=a.worldTransform,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=1/(g*k+h*-j),n=k*m*c.x+-h*m*c.y+(l*h-i*k)*m,o=g*m*c.y+-j*m*c.x+(-l*g+i*j)*m;if(b.target=a,a.hitArea&&a.hitArea.contains)return a.hitArea.contains(n,o)?(b.target=a,!0):!1;if(d){var p,q=a.texture.frame.width,r=a.texture.frame.height,s=-q*a.anchor.x;if(n>s&&s+q>n&&(p=-r*a.anchor.y,o>p&&p+r>o))return b.target=a,!0}for(var t=a.children.length,u=0;t>u;u++){var v=a.children[u],w=this.hitTest(v,b);if(w)return b.target=a,!0}return!1},f.InteractionManager.prototype.onTouchMove=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;dd;d++){var h=this.interactiveItems[d];h.touchmove&&h.touchmove(f)}},f.InteractionManager.prototype.onTouchStart=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i];if((j.touchstart||j.tap)&&(j.__hit=this.hitTest(j,g),j.__hit&&(j.touchstart&&j.touchstart(g),j.__isDown=!0,j.__touchData=g,!j.interactiveChildren)))break}}},f.InteractionManager.prototype.onTouchEnd=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i],k=j.__touchData;j.__hit=this.hitTest(j,f),k==f&&(f.originalEvent=a||window.event,(j.touchend||j.tap)&&(j.__hit&&!g?(j.touchend&&j.touchend(f),j.__isDown&&j.tap&&j.tap(f),j.interactiveChildren||(g=!0)):j.__isDown&&j.touchendoutside&&j.touchendoutside(f),j.__isDown=!1),j.__touchData=null)}this.pool.push(f),this.touchs[e.identifier]=null}},f.InteractionData=function(){this.global=new f.Point,this.local=new f.Point,this.target,this.originalEvent},f.InteractionData.prototype.getLocalPosition=function(a){var b=a.worldTransform,c=this.global,d=b[0],e=b[1],g=b[2],h=b[3],i=b[4],j=b[5],k=1/(d*i+e*-h);return new f.Point(i*k*c.x+-e*k*c.y+(j*e-g*i)*k,d*k*c.y+-h*k*c.x+(-j*d+g*h)*k)},f.InteractionData.prototype.constructor=f.InteractionData,f.Stage=function(a){f.DisplayObjectContainer.call(this),this.worldTransform=f.mat3.create(),this.interactive=!0,this.interactionManager=new f.InteractionManager(this),this.dirty=!0,this.__childrenAdded=[],this.__childrenRemoved=[],this.stage=this,this.stage.hitArea=new f.Rectangle(0,0,1e5,1e5),this.setBackgroundColor(a),this.worldVisible=!0},f.Stage.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Stage.prototype.constructor=f.Stage,f.Stage.prototype.setInteractionDelegate=function(a){this.interactionManager.setTargetDomElement(a)},f.Stage.prototype.updateTransform=function(){this.worldAlpha=1,this.vcount=f.visibleCount;for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform();this.dirty&&(this.dirty=!1,this.interactionManager.dirty=!0),this.interactive&&this.interactionManager.update()},f.Stage.prototype.setBackgroundColor=function(a){this.backgroundColor=a||0,this.backgroundColorSplit=d(this.backgroundColor);var b=this.backgroundColor.toString(16);b="000000".substr(0,6-b.length)+b,this.backgroundColorString="#"+b},f.Stage.prototype.getMousePosition=function(){return this.interactionManager.mouse.global};for(var h=0,i=["ms","moz","webkit","o"],j=0;j>>>>>>>>"),console.log("_");var b=0,c=a.first;for(console.log(c);c._iNext;)if(b++,c=c._iNext,console.log(c),b>100){console.log("BREAK");break}},f.EventTarget=function(){var a={};this.addEventListener=this.on=function(b,c){void 0===a[b]&&(a[b]=[]),-1===a[b].indexOf(c)&&a[b].push(c)},this.dispatchEvent=this.emit=function(b){if(a[b.type]&&a[b.type].length)for(var c=0,d=a[b.type].length;d>c;c++)a[b.type][c](b)},this.removeEventListener=this.off=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)}},f.autoDetectRenderer=function(a,b,c,d,e){a||(a=800),b||(b=600);var g=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}();if(g){var h=-1!=navigator.userAgent.toLowerCase().indexOf("msie");g=!h}return g?new f.WebGLRenderer(a,b,c,d,e):new f.CanvasRenderer(a,b,c,d)},f.PolyK={},f.PolyK.Triangulate=function(a){var b=!0,c=a.length>>1;if(3>c)return[];for(var d=[],e=[],g=0;c>g;g++)e.push(g);for(var g=0,h=c;h>3;){var i=e[(g+0)%h],j=e[(g+1)%h],k=e[(g+2)%h],l=a[2*i],m=a[2*i+1],n=a[2*j],o=a[2*j+1],p=a[2*k],q=a[2*k+1],r=!1;if(f.PolyK._convex(l,m,n,o,p,q,b)){r=!0;for(var s=0;h>s;s++){var t=e[s];if(t!=i&&t!=j&&t!=k&&f.PolyK._PointInTriangle(a[2*t],a[2*t+1],l,m,n,o,p,q)){r=!1;break}}}if(r)d.push(i,j,k),e.splice((g+1)%h,1),h--,g=0;else if(g++>3*h){if(!b)return console.log("PIXI Warning: shape too complex to fill"),[];var d=[];e=[];for(var g=0;c>g;g++)e.push(g);g=0,h=c,b=!1}}return d.push(e[0],e[1],e[2]),d},f.PolyK._PointInTriangle=function(a,b,c,d,e,f,g,h){var i=g-c,j=h-d,k=e-c,l=f-d,m=a-c,n=b-d,o=i*i+j*j,p=i*k+j*l,q=i*m+j*n,r=k*k+l*l,s=k*m+l*n,t=1/(o*r-p*p),u=(r*q-p*s)*t,v=(o*s-p*q)*t;return u>=0&&v>=0&&1>u+v},f.PolyK._convex=function(a,b,c,d,e,f,g){return(b-d)*(e-c)+(c-a)*(f-d)>=0==g},f.initDefaultShaders=function(){f.primitiveShader=new f.PrimitiveShader,f.primitiveShader.init(),f.stripShader=new f.StripShader,f.stripShader.init(),f.defaultShader=new f.PixiShader,f.defaultShader.init();var a=f.gl,b=f.defaultShader.program;a.useProgram(b),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.primitiveShader.program),a.disableVertexAttribArray(f.defaultShader.aVertexPosition),a.disableVertexAttribArray(f.defaultShader.colorAttribute),a.disableVertexAttribArray(f.defaultShader.aTextureCoord),a.enableVertexAttribArray(f.primitiveShader.aVertexPosition),a.enableVertexAttribArray(f.primitiveShader.colorAttribute)},f.deactivatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program),a.disableVertexAttribArray(f.primitiveShader.aVertexPosition),a.disableVertexAttribArray(f.primitiveShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activateStripShader=function(){var a=f.gl;a.useProgram(f.stripShader.program)},f.deactivateStripShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program)},f.CompileVertexShader=function(a,b){return f._CompileShader(a,b,a.VERTEX_SHADER)},f.CompileFragmentShader=function(a,b){return f._CompileShader(a,b,a.FRAGMENT_SHADER)},f._CompileShader=function(a,b,c){var d=b.join("\n"),e=a.createShader(c);return a.shaderSource(e,d),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)?e:(console.log(a.getShaderInfoLog(e)),null)},f.compileProgram=function(a,b){var c=f.gl,d=f.CompileFragmentShader(c,b),e=f.CompileVertexShader(c,a),g=c.createProgram();return c.attachShader(g,e),c.attachShader(g,d),c.linkProgram(g),c.getProgramParameter(g,c.LINK_STATUS)||console.log("Could not initialise shaders"),g},f.PixiShader=function(){this.program,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;","}"]},f.PixiShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc||f.PixiShader.defaultVertexSrc,this.fragmentSrc),b=f.gl; +b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord");for(var c in this.uniforms)a[c]=b.getUniformLocation(a,c);this.program=a},f.PixiShader.prototype.syncUniforms=function(){var a=f.gl;for(var b in this.uniforms){var c=this.uniforms[b].type;if("f"==c&&a.uniform1f(this.program[b],this.uniforms[b].value),"f2"==c)a.uniform2f(this.program[b],this.uniforms[b].value.x,this.uniforms[b].value.y);else if("f4"==c)a.uniform4fv(this.program[b],this.uniforms[b].value);else if("mat4"==c)a.uniformMatrix4fv(this.program[b],!1,this.uniforms[b].value);else if("sampler2D"==c){var d=this.uniforms[b].value;a.activeTexture(a.TEXTURE1),a.bindTexture(a.TEXTURE_2D,d.baseTexture._glTexture),a.uniform1i(this.program[b],1)}}},f.PixiShader.defaultVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","varying float vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"],f.StripShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying float vColor;","uniform float alpha;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));","gl_FragColor = gl_FragColor * alpha;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","varying vec2 vTextureCoord;","varying vec2 offsetVector;","varying float vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"]},f.StripShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.PrimitiveShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","gl_FragColor = vColor;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec4 aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform float alpha;","varying vec4 vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","vColor = aColor * alpha;","}"]},f.PrimitiveShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.WebGLGraphics=function(){},f.WebGLGraphics.renderGraphics=function(a,b){var c=f.gl;a._webGL||(a._webGL={points:[],indices:[],lastIndex:0,buffer:c.createBuffer(),indexBuffer:c.createBuffer()}),a.dirty&&(a.dirty=!1,a.clearDirty&&(a.clearDirty=!1,a._webGL.lastIndex=0,a._webGL.points=[],a._webGL.indices=[]),f.WebGLGraphics.updateGraphics(a)),f.activatePrimitiveShader();var d=f.mat3.clone(a.worldTransform);f.mat3.transpose(d),c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA),c.uniformMatrix3fv(f.primitiveShader.translationMatrix,!1,d),c.uniform2f(f.primitiveShader.projectionVector,b.x,-b.y),c.uniform2f(f.primitiveShader.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(f.primitiveShader.alpha,a.worldAlpha),c.bindBuffer(c.ARRAY_BUFFER,a._webGL.buffer),c.vertexAttribPointer(f.primitiveShader.aVertexPosition,2,c.FLOAT,!1,24,0),c.vertexAttribPointer(f.primitiveShader.colorAttribute,4,c.FLOAT,!1,24,8),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),c.drawElements(c.TRIANGLE_STRIP,a._webGL.indices.length,c.UNSIGNED_SHORT,0),f.deactivatePrimitiveShader()},f.WebGLGraphics.updateGraphics=function(a){for(var b=a._webGL.lastIndex;b3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){if(a.lineWidth%2)for(var e=0;ee;e++)k=c[2*(e-1)],l=c[2*(e-1)+1],m=c[2*e],n=c[2*e+1],o=c[2*(e+1)],p=c[2*(e+1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,s=-(n-p),t=m-o,E=Math.sqrt(s*s+t*t),s/=E,t/=E,s*=K,t*=K,w=-r+l-(-r+n),x=-q+m-(-q+k),y=(-q+k)*(-r+n)-(-q+m)*(-r+l),z=-t+p-(-t+n),A=-s+m-(-s+o),B=(-s+o)*(-t+n)-(-s+m)*(-t+p),C=w*A-z*x,Math.abs(C)<.1?(C+=10.1,F.push(m-q,n-r,N,O,P,M),F.push(m+q,n+r,N,O,P,M)):(px=(x*B-A*y)/C,py=(z*y-w*B)/C,D=(px-m)*(px-m)+(py-n)+(py-n),D>19600?(u=q-s,v=r-t,E=Math.sqrt(u*u+v*v),u/=E,v/=E,u*=K,v*=K,F.push(m-u,n-v),F.push(N,O,P,M),F.push(m+u,n+v),F.push(N,O,P,M),F.push(m-u,n-v),F.push(N,O,P,M),I++):(F.push(px,py),F.push(N,O,P,M),F.push(m-(px-m),n-(py-n)),F.push(N,O,P,M)));k=c[2*(H-2)],l=c[2*(H-2)+1],m=c[2*(H-1)],n=c[2*(H-1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,F.push(m-q,n-r),F.push(N,O,P,M),F.push(m+q,n+r),F.push(N,O,P,M),G.push(J);for(var e=0;I>e;e++)G.push(J++);G.push(J-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},flip=!1;var l=[],m=0;f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;if(a.open)a.data instanceof Array?this.filterManager.pushFilter(a):(m++,l.push(a),c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.INCR),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP));else if(a.data instanceof Array)this.filterManager.popFilter();else{var d=l.pop(a);d&&(c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.DECR),f.WebGLGraphics.renderGraphics(d.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)),c.disable(c.STENCIL_TEST)}},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(){this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;hs?s:E,E=E>t?t:E,E=E>u?u:E,E=E>v?v:E,F=F>w?w:F,F=F>x?x:F,F=F>y?y:F,F=F>z?z:F,C=s>C?s:C,C=t>C?t:C,C=u>C?u:C,C=v>C?v:C,D=w>D?w:D,D=x>D?x:D,D=y>D?y:D,D=z>D?z:D),l=!1,A=A._iNext}while(A!=B);a.filterArea.x=E,a.filterArea.y=F,a.filterArea.width=C-E,a.filterArea.height=D-F},f.FilterTexture=function(a,b){var c=f.gl;this.frameBuffer=c.createFramebuffer(),this.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,this.texture),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.bindFramebuffer(c.FRAMEBUFFER,this.framebuffer),c.bindFramebuffer(c.FRAMEBUFFER,this.frameBuffer),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,this.texture,0),this.resize(a,b)},f.FilterTexture.prototype.resize=function(a,b){this.width=a,this.height=b;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a,b,0,c.RGBA,c.UNSIGNED_BYTE,null)},f.CanvasRenderer=function(a,b,c,d){this.transparent=d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.context=this.view.getContext("2d"),this.refresh=!0,this.view.width=this.width,this.view.height=this.height,this.count=0},f.CanvasRenderer.prototype.constructor=f.CanvasRenderer,f.CanvasRenderer.prototype.render=function(a){f.texturesToUpdate=[],f.texturesToDestroy=[],f.visibleCount++,a.updateTransform(),this.view.style.backgroundColor==a.backgroundColorString||this.transparent||(this.view.style.backgroundColor=a.backgroundColorString),this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.width,this.height),this.renderDisplayObject(a),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0&&(f.Texture.frameUpdates=[])},f.CanvasRenderer.prototype.resize=function(a,b){this.width=a,this.height=b,this.view.width=a,this.view.height=b},f.CanvasRenderer.prototype.renderDisplayObject=function(a){var b,c=this.context;c.globalCompositeOperation="source-over";var d=a.last._iNext;a=a.first;do if(b=a.worldTransform,a.visible)if(a.renderable){if(a instanceof f.Sprite){var e=a.texture.frame;e&&e.width&&e.height&&(c.globalAlpha=a.worldAlpha,c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),c.drawImage(a.texture.baseTexture.source,e.x,e.y,e.width,e.height,a.anchor.x*-e.width,a.anchor.y*-e.height,e.width,e.height))}else if(a instanceof f.Strip)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderStrip(a);else if(a instanceof f.TilingSprite)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderTilingSprite(a);else if(a instanceof f.CustomRenderable)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),a.renderCanvas(this);else if(a instanceof f.Graphics)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),f.CanvasGraphics.renderGraphics(a,c);else if(a instanceof f.FilterBlock&&a.data instanceof f.Graphics){var g=a.data;if(a.open){c.save();var h=g.alpha,i=g.worldTransform;c.setTransform(i[0],i[3],i[1],i[4],i[2],i[5]),g.worldAlpha=.5,c.worldAlpha=0,f.CanvasGraphics.renderGraphicsMask(g,c),c.clip(),g.worldAlpha=h}else c.restore()}a=a._iNext}else a=a._iNext;else a=a.last._iNext;while(a!=d)},f.CanvasRenderer.prototype.renderStripFlat=function(a){var b=this.context,c=a.verticies;a.uvs;var d=c.length/2;this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},f.CanvasRenderer.prototype.renderTilingSprite=function(a){var b=this.context;b.globalAlpha=a.worldAlpha,a.__tilePattern||(a.__tilePattern=b.createPattern(a.texture.baseTexture.source,"repeat")),b.beginPath();var c=a.tilePosition,d=a.tileScale;b.scale(d.x,d.y),b.translate(c.x,c.y),b.fillStyle=a.__tilePattern,b.fillRect(-c.x,-c.y,a.width/d.x,a.height/d.y),b.scale(1/d.x,1/d.y),b.translate(-c.x,-c.y),b.closePath()},f.CanvasRenderer.prototype.renderStrip=function(a){var b=this.context,c=a.verticies,d=a.uvs,e=c.length/2;this.count++;for(var f=1;e-2>f;f++){var g=2*f,h=c[g],i=c[g+2],j=c[g+4],k=c[g+1],l=c[g+3],m=c[g+5],n=d[g]*a.texture.width,o=d[g+2]*a.texture.width,p=d[g+4]*a.texture.width,q=d[g+1]*a.texture.height,r=d[g+3]*a.texture.height,s=d[g+5]*a.texture.height;b.save(),b.beginPath(),b.moveTo(h,k),b.lineTo(i,l),b.lineTo(j,m),b.closePath(),b.clip();var t=n*r+q*p+o*s-r*p-q*o-n*s,u=h*r+q*j+i*s-r*j-q*i-h*s,v=n*i+h*p+o*j-i*p-h*o-n*j,w=n*r*j+q*i*p+h*o*s-h*r*p-q*o*j-n*i*s,x=k*r+q*m+l*s-r*m-q*l-k*s,y=n*l+k*p+o*m-l*p-k*o-n*m,z=n*r*m+q*l*p+k*o*s-k*r*p-q*o*m-n*l*s;b.transform(u/t,x/t,v/t,y/t,w/t,z/t),b.drawImage(a.texture.baseTexture.source,0,0),b.restore()}},f.CanvasGraphics=function(){},f.CanvasGraphics.renderGraphics=function(a,b){for(var c=a.worldAlpha,d=0;d1&&(c=1,console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var d=0;1>d;d++){var e=a.graphicsData[d],g=e.points;if(e.type==f.Graphics.POLY){b.beginPath(),b.moveTo(g[0],g[1]);for(var h=1;hb?b:d,e=b+m>e?b+m:e,g=g>c?b:g,h=c+n>h?c+n:h}else if(k===f.Graphics.CIRC||k===f.Graphics.ELIP){b=a.x,c=a.y;var o=a.radius+l/2;d=d>b-o?b-o:d,e=b+o>e?b+o:e,g=g>c-o?c-o:g,h=c+o>h?c+o:h}else for(var p=0;pb-l?b-l:d,e=b+l>e?b+l:e,g=g>c-l?c-l:g,h=c+l>h?c+l:h}this.bounds=new f.Rectangle(d,g,e-d,h-g)}},f.Graphics.POLY=0,f.Graphics.RECT=1,f.Graphics.CIRC=2,f.Graphics.ELIP=3,f.Strip=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.blendMode=f.blendModes.NORMAL;try{this.uvs=new Float32Array([0,1,1,1,1,0,0,1]),this.verticies=new Float32Array([0,0,0,0,0,0,0,0,0]),this.colors=new Float32Array([1,1,1,1]),this.indices=new Uint16Array([0,1,2,3])}catch(d){this.uvs=[0,1,1,1,1,0,0,1],this.verticies=[0,0,0,0,0,0,0,0,0],this.colors=[1,1,1,1],this.indices=[0,1,2,3]}this.width=b,this.height=c,a.baseTexture.hasLoaded?(this.width=this.texture.frame.width,this.height=this.texture.frame.height,this.updateFrame=!0):(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Strip.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Strip.prototype.constructor=f.Strip,f.Strip.prototype.setTexture=function(a){this.texture=a,this.width=a.frame.width,this.height=a.frame.height,this.updateFrame=!0},f.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Rope=function(a,b){f.Strip.call(this,a),this.points=b;try{this.verticies=new Float32Array(4*b.length),this.uvs=new Float32Array(4*b.length),this.colors=new Float32Array(2*b.length),this.indices=new Uint16Array(2*b.length)}catch(c){this.verticies=verticies,this.uvs=uvs,this.colors=colors,this.indices=indices}this.refresh()},f.Rope.prototype=Object.create(f.Strip.prototype),f.Rope.prototype.constructor=f.Rope,f.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=this.indices,d=this.colors,e=a[0],f=a[0];this.count-=.2,b[0]=0,b[1]=1,b[2]=0,b[3]=1,d[0]=1,d[1]=1,c[0]=0,c[1]=1;for(var g=a.length,h=1;g>h;h++){var f=a[h],i=4*h,j=h/(g-1);h%2?(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1):(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1),i=2*h,d[i]=1,d[i+1]=1,i=2*h,c[i]=i,c[i+1]=i+1,e=f}}},f.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var b,c=this.verticies,d=a[0],e={x:0,y:0},g=a[0];this.count-=.2,c[0]=g.x+e.x,c[1]=g.y+e.y,c[2]=g.x-e.x,c[3]=g.y-e.y;for(var h=a.length,i=1;h>i;i++){var g=a[i],j=4*i;b=i1&&(k=1);var l=Math.sqrt(e.x*e.x+e.y*e.y),m=this.texture.height/2;e.x/=l,e.y/=l,e.x*=m,e.y*=m,c[j]=g.x+e.x,c[j+1]=g.y+e.y,c[j+2]=g.x-e.x,c[j+3]=g.y-e.y,d=g}f.DisplayObjectContainer.prototype.updateTransform.call(this)}},f.Rope.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.width=b,this.height=c,this.tileScale=new f.Point(1,1),this.tilePosition=new f.Point(0,0),this.renderable=!0,this.blendMode=f.blendModes.NORMAL},f.TilingSprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.TilingSprite.prototype.constructor=f.TilingSprite,f.TilingSprite.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Spine=function(a){if(f.DisplayObjectContainer.call(this),this.spineData=f.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new n.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new n.AnimationStateData(this.spineData),this.state=new n.AnimationState(this.stateData),this.slotContainers=[];for(var b=0,c=this.skeleton.drawOrder.length;c>b;b++){var d=this.skeleton.drawOrder[b],e=d.attachment,g=new f.DisplayObjectContainer;if(this.slotContainers.push(g),this.addChild(g),e instanceof n.RegionAttachment){var h=e.rendererObject.name,i=this.createSprite(d,e.rendererObject);d.currentSprite=i,d.currentSpriteName=h,g.addChild(i)}}},f.Spine.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Spine.prototype.constructor=f.Spine,f.Spine.prototype.updateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var b=this.skeleton.drawOrder,c=0,d=b.length;d>c;c++){var e=b[c],g=e.attachment,h=this.slotContainers[c];if(g instanceof n.RegionAttachment){if(g.rendererObject&&(!e.currentSpriteName||e.currentSpriteName!=g.name)){var i=g.rendererObject.name;if(void 0!==e.currentSprite&&(e.currentSprite.visible=!1),e.sprites=e.sprites||{},void 0!==e.sprites[i])e.sprites[i].visible=!0;else{var j=this.createSprite(e,g.rendererObject);h.addChild(j)}e.currentSprite=e.sprites[i],e.currentSpriteName=i}h.visible=!0;var k=e.bone;h.position.x=k.worldX+g.x*k.m00+g.y*k.m01,h.position.y=k.worldY+g.x*k.m10+g.y*k.m11,h.scale.x=k.worldScaleX,h.scale.y=k.worldScaleY,h.rotation=-(e.bone.worldRotation*Math.PI/180)}else h.visible=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.Spine.prototype.createSprite=function(a,b){var c=f.TextureCache[b.name]?b.name:b.name+".png",d=new f.Sprite(f.Texture.fromFrame(c));return d.scale=b.scale,d.rotation=b.rotation,d.anchor.x=d.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[b.name]=d,d};var n={};n.BoneData=function(a,b){this.name=a,this.parent=b},n.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1},n.SlotData=function(a,b){this.name=a,this.boneData=b},n.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null},n.Bone=function(a,b){this.data=a,this.parent=b,this.setToSetupPose()},n.Bone.yDown=!1,n.Bone.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,updateWorldTransform:function(a,b){var c=this.parent;null!=c?(this.worldX=this.x*c.m00+this.y*c.m01+c.worldX,this.worldY=this.x*c.m10+this.y*c.m11+c.worldY,this.worldScaleX=c.worldScaleX*this.scaleX,this.worldScaleY=c.worldScaleY*this.scaleY,this.worldRotation=c.worldRotation+this.rotation):(this.worldX=this.x,this.worldY=this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotation);var d=this.worldRotation*Math.PI/180,e=Math.cos(d),f=Math.sin(d);this.m00=e*this.worldScaleX,this.m10=f*this.worldScaleX,this.m01=-f*this.worldScaleY,this.m11=e*this.worldScaleY,a&&(this.m00=-this.m00,this.m01=-this.m01),b&&(this.m10=-this.m10,this.m11=-this.m11),n.Bone.yDown&&(this.m10=-this.m10,this.m11=-this.m11)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY}},n.Slot=function(a,b,c){this.data=a,this.skeleton=b,this.bone=c,this.setToSetupPose()},n.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,setAttachment:function(a){this.attachment=a,this._attachmentTime=this.skeleton.time},setAttachmentTime:function(a){this._attachmentTime=this.skeleton.time-a},getAttachmentTime:function(){return this.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},n.Skin=function(a){this.name=a,this.attachments={}},n.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},n.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},n.Animation.prototype={apply:function(a,b,c){c&&0!=this.duration&&(b%=this.duration);for(var d=this.timelines,e=0,f=d.length;f>e;e++)d[e].apply(a,b,1)},mix:function(a,b,c,d){c&&0!=this.duration&&(b%=this.duration);for(var e=this.timelines,f=0,g=e.length;g>f;f++)e[f].apply(a,b,d)}},n.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(0==e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},n.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},n.Curves=function(a){this.curves=[],this.curves.length=6*(a-1)},n.Curves.prototype={setLinear:function(a){this.curves[6*a]=0},setStepped:function(a){this.curves[6*a]=-1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=6*a,r=this.curves;r[q]=b*i+m*j+o*h,r[q+1]=c*i+n*j+p*h,r[q+2]=m*k+o*l,r[q+3]=n*k+p*l,r[q+4]=o*l,r[q+5]=p*l},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=6*a,d=this.curves,e=d[c];if(!e)return b;if(-1==e)return 0;for(var f=d[c+1],g=d[c+2],h=d[c+3],i=d[c+4],j=d[c+5],k=e,l=f,m=8;;){if(k>=b){var n=k-e,o=l-f;return o+(l-o)*(b-n)/(k-n)}if(0==m)break;m--,e+=g,f+=h,g+=i,h+=j,k+=e,l+=f}return l+(1-l)*(b-k)/(1-k)}},n.RotateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=2*a},n.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-2]){for(var f=e.data.rotation+d[d.length-1]-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;return e.rotation+=f*c,void 0}var g=n.binarySearch(d,b,2),h=d[g-1],i=d[g],j=1-(b-i)/(d[g-2]-i);j=this.curves.getCurvePercent(g/2-1,j);for(var f=d[g+1]-h;f>180;)f-=360;for(;-180>f;)f+=360;for(f=e.data.rotation+(h+f*j)-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;e.rotation+=f*c}}},n.TranslateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.x+=(e.data.x+d[d.length-2]-e.x)*c,e.y+=(e.data.y+d[d.length-1]-e.y)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.x+=(e.data.x+g+(d[f+1]-g)*j-e.x)*c,e.y+=(e.data.y+h+(d[f+2]-h)*j-e.y)*c}}},n.ScaleTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.scaleX+=(e.data.scaleX-1+d[d.length-2]-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+d[d.length-1]-e.scaleY)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.scaleX+=(e.data.scaleX-1+g+(d[f+1]-g)*j-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+h+(d[f+2]-h)*j-e.scaleY)*c}}},n.ColorTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=5*a},n.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(c,d){c*=5,this.frames[c]=d,this.frames[c+1]=r,this.frames[c+2]=g,this.frames[c+3]=b,this.frames[c+4]=a},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-5]){var f=d.length-1;return e.r=d[f-3],e.g=d[f-2],e.b=d[f-1],e.a=d[f],void 0}var g=n.binarySearch(d,b,5),h=d[g-4],i=d[g-3],j=d[g-2],k=d[g-1],l=d[g],m=1-(b-l)/(d[g-5]-l);m=this.curves.getCurvePercent(g/5-1,m);var o=h+(d[g+1]-h)*m,p=i+(d[g+2]-i)*m,q=j+(d[g+3]-j)*m,r=k+(d[g+4]-k)*m;1>c?(e.r+=(o-e.r)*c,e.g+=(p-e.g)*c,e.b+=(q-e.b)*c,e.a+=(r-e.a)*c):(e.r=o,e.g=p,e.b=q,e.a=r)}}},n.AttachmentTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},n.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b){var c=this.frames;if(!(b=c[c.length-1]?c.length-1:n.binarySearch(c,b,1)-1;var e=this.attachmentNames[d];a.slots[this.slotIndex].setAttachment(e?a.getAttachmentBySlotIndex(this.slotIndex,e):null)}}},n.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.animations=[]},n.SkeletonData.prototype={defaultSkin:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},n.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,c=a.bones.length;c>b;b++){var d=a.bones[b],e=d.parent?this.bones[a.bones.indexOf(d.parent)]:null;this.bones.push(new n.Bone(d,e))}this.slots=[],this.drawOrder=[];for(var b=0,c=a.slots.length;c>b;b++){var f=a.slots[b],g=this.bones[a.bones.indexOf(f.boneData)],h=new n.Slot(f,this,g);this.slots.push(h),this.drawOrder.push(h)}},n.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateWorldTransform:function(){for(var a=this.flipX,b=this.flipY,c=this.bones,d=0,e=c.length;e>d;d++)c[d].updateWorldTransform(a,b)},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose()},setSlotsToSetupPose:function(){for(var a=this.slots,b=0,c=a.length;c>b;b++)a[b].setToSetupPose(b)},getRootBone:function(){return 0==this.bones.length?null:this.bones[0]},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a);if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){this.skin&&a&&a._attachAll(this,this.skin),this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.size;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachment(d,b),null==g))throw"Attachment not found: "+b+", for slot: "+a;return f.setAttachment(g),void 0}}throw"Slot not found: "+a},update:function(a){time+=a}},n.AttachmentType={region:0},n.RegionAttachment=function(){this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},n.RegionAttachment.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,c=-this.width/2*this.scaleX+this.regionOffsetX*a,d=-this.height/2*this.scaleY+this.regionOffsetY*b,e=c+this.regionWidth*a,f=d+this.regionHeight*b,g=this.rotation*Math.PI/180,h=Math.cos(g),i=Math.sin(g),j=c*h+this.x,k=c*i,l=d*h+this.y,m=d*i,n=e*h+this.x,o=e*i,p=f*h+this.y,q=f*i,r=this.offset;r[0]=j-m,r[1]=l+k,r[2]=j-q,r[3]=p+k,r[4]=n-q,r[5]=p+o,r[6]=n-m,r[7]=l+o},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},n.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},n.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=this.animationToMixTime[a.name+":"+b.name];return c?c:this.defaultMix}},n.AnimationState=function(a){this.data=a,this.queue=[]},n.AnimationState.prototype={current:null,previous:null,currentTime:0,previousTime:0,currentLoop:!1,previousLoop:!1,mixTime:0,mixDuration:0,update:function(a){if(this.currentTime+=a,this.previousTime+=a,this.mixTime+=a,this.queue.length>0){var b=this.queue[0];this.currentTime>=b.delay&&(this._setAnimation(b.animation,b.loop),this.queue.shift())}},apply:function(a){if(this.current)if(this.previous){this.previous.apply(a,this.previousTime,this.previousLoop);var b=this.mixTime/this.mixDuration;b>=1&&(b=1,this.previous=null),this.current.mix(a,this.currentTime,this.currentLoop,b)}else this.current.apply(a,this.currentTime,this.currentLoop)},clearAnimation:function(){this.previous=null,this.current=null,this.queue.length=0},_setAnimation:function(a,b){this.previous=null,a&&this.current&&(this.mixDuration=this.data.getMix(this.current,a),this.mixDuration>0&&(this.mixTime=0,this.previous=this.current,this.previousTime=this.currentTime,this.previousLoop=this.currentLoop)),this.current=a,this.currentLoop=b,this.currentTime=0},setAnimationByName:function(a,b){var c=this.data.skeletonData.findAnimation(a);if(!c)throw"Animation not found: "+a;this.setAnimation(c,b)},setAnimation:function(a,b){this.queue.length=0,this._setAnimation(a,b)},addAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;this.addAnimation(d,b,c)},addAnimation:function(a,b,c){var d={};if(d.animation=a,d.loop=b,!c||0>=c){var e=0==this.queue.length?this.current:this.queue[this.queue.length-1].animation;c=null!=e?e.duration-this.data.getMix(e,a)+(c||0):0}d.delay=c,this.queue.push(d)},isComplete:function(){return!this.current||this.currentTime>=this.current.duration}},n.SkeletonJson=function(a){this.attachmentLoader=a},n.SkeletonJson.prototype={scale:1,readSkeletonData:function(a){for(var b=new n.SkeletonData,c=a.bones,d=0,e=c.length;e>d;d++){var f=c[d],g=null;if(f.parent&&(g=b.findBone(f.parent),!g))throw"Parent bone not found: "+f.parent;var h=new n.BoneData(f.name,g);h.length=(f.length||0)*this.scale,h.x=(f.x||0)*this.scale,h.y=(f.y||0)*this.scale,h.rotation=f.rotation||0,h.scaleX=f.scaleX||1,h.scaleY=f.scaleY||1,b.bones.push(h)}for(var i=a.slots,d=0,e=i.length;e>d;d++){var j=i[d],h=b.findBone(j.bone);if(!h)throw"Slot bone not found: "+j.bone; +var k=new n.SlotData(j.name,h),l=j.color;l&&(k.r=n.SkeletonJson.toColor(l,0),k.g=n.SkeletonJson.toColor(l,1),k.b=n.SkeletonJson.toColor(l,2),k.a=n.SkeletonJson.toColor(l,3)),k.attachmentName=j.attachment,b.slots.push(k)}var m=a.skins;for(var o in m)if(m.hasOwnProperty(o)){var p=m[o],q=new n.Skin(o);for(var r in p)if(p.hasOwnProperty(r)){var s=b.findSlotIndex(r),t=p[r];for(var u in t)if(t.hasOwnProperty(u)){var v=this.readAttachment(q,u,t[u]);null!=v&&q.addAttachment(s,u,v)}}b.skins.push(q),"default"==q.name&&(b.defaultSkin=q)}var w=a.animations;for(var x in w)w.hasOwnProperty(x)&&this.readAnimation(x,w[x],b);return b},readAttachment:function(a,b,c){b=c.name||b;var d=n.AttachmentType[c.type||"region"];if(d==n.AttachmentType.region){var e=new n.RegionAttachment;return e.x=(c.x||0)*this.scale,e.y=(c.y||0)*this.scale,e.scaleX=c.scaleX||1,e.scaleY=c.scaleY||1,e.rotation=c.rotation||0,e.width=(c.width||32)*this.scale,e.height=(c.height||32)*this.scale,e.updateOffset(),e.rendererObject={},e.rendererObject.name=b,e.rendererObject.scale={},e.rendererObject.scale.x=e.scaleX,e.rendererObject.scale.y=e.scaleY,e.rendererObject.rotation=-e.rotation*Math.PI/180,e}throw"Unknown attachment type: "+d},readAnimation:function(a,b,c){var d=[],e=0,f=b.bones;for(var g in f)if(f.hasOwnProperty(g)){var h=c.findBoneIndex(g);if(-1==h)throw"Bone not found: "+g;var i=f[g];for(var j in i)if(i.hasOwnProperty(j)){var k=i[j];if("rotate"==j){var l=new n.RotateTimeline(k.length);l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m,q.time,q.angle),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[2*l.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var l,r=1;"scale"==j?l=new n.ScaleTimeline(k.length):(l=new n.TranslateTimeline(k.length),r=this.scale),l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;l.setFrame(m,q.time,s,t),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[3*l.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var l=new n.ColorTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=n.SkeletonJson.toColor(y,0),A=n.SkeletonJson.toColor(y,1),B=n.SkeletonJson.toColor(y,2),C=n.SkeletonJson.toColor(y,3);l.setFrame(m,q.time,z,A,B,C),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[5*l.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var l=new n.AttachmentTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m++,q.time,q.name)}d.push(l),e=Math.max(e,l.frames[l.getFrameCount()-1])}}}c.animations.push(new n.Animation(a,d,e))}},n.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},n.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},n.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new n.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new n.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new n.AtlasPage,e.name=f,e.format=n.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=n.Atlas.TextureFilter[d[0]],e.magFilter=n.Atlas.TextureFilter[d[1]];var l=c.readValue();e.uWrap=n.Atlas.TextureWrap.clampToEdge,e.vWrap=n.Atlas.TextureWrap.clampToEdge,"x"==l?e.uWrap=n.Atlas.TextureWrap.repeat:"y"==l?e.vWrap=n.Atlas.TextureWrap.repeat:"xy"==l&&(e.uWrap=e.vWrap=n.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},n.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},n.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},n.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},n.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},n.AtlasPage=function(){},n.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},n.AtlasRegion=function(){},n.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},n.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},n.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},n.AtlasAttachmentLoader=function(a){this.atlas=a},n.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case n.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new n.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},n.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;h + + + pixi.js example 13 - Graphics + + + + + + + + + + diff --git a/src/pixi/renderers/webgl/PixiShader.js b/src/pixi/renderers/webgl/PixiShader.js index fb15649..7938c8a 100644 --- a/src/pixi/renderers/webgl/PixiShader.js +++ b/src/pixi/renderers/webgl/PixiShader.js @@ -32,11 +32,11 @@ PIXI.PixiShader.prototype.init = function() this.uSampler = gl.getUniformLocation(program, "uSampler"); this.projectionVector = gl.getUniformLocation(program, "projectionVector"); this.offsetVector = gl.getUniformLocation(program, "offsetVector"); + //this.dimensions = gl.getUniformLocation(this.program, "dimensions"); + + // get and store the attributes + this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); this.colorAttribute = gl.getAttribLocation(program, "aColor"); - //this.dimensions = gl.getUniformLocation(this.program, "dimensions"); - - // get and store the attributes - this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); this.aTextureCoord = gl.getAttribLocation(program, "aTextureCoord"); // add those custom shaders! diff --git a/src/pixi/renderers/webgl/PrimitiveShader.js b/src/pixi/renderers/webgl/PrimitiveShader.js index e4b007e..1089d84 100644 --- a/src/pixi/renderers/webgl/PrimitiveShader.js +++ b/src/pixi/renderers/webgl/PrimitiveShader.js @@ -45,13 +45,13 @@ PIXI.PrimitiveShader.prototype.init = function() // get and store the uniforms for the shader this.projectionVector = gl.getUniformLocation(program, "projectionVector"); this.offsetVector = gl.getUniformLocation(program, "offsetVector"); + + // get and store the attributes + this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); this.colorAttribute = gl.getAttribLocation(program, "aColor"); - // get and store the attributes - this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); - - this.translationMatrix = gl.getUniformLocation(program, "translationMatrix"); - this.alpha = gl.getUniformLocation(program, "alpha"); + this.translationMatrix = gl.getUniformLocation(program, "translationMatrix"); + this.alpha = gl.getUniformLocation(program, "alpha"); this.program = program; } diff --git a/src/pixi/renderers/webgl/WebGLGraphics.js b/src/pixi/renderers/webgl/WebGLGraphics.js index f0ddb32..1d94985 100644 --- a/src/pixi/renderers/webgl/WebGLGraphics.js +++ b/src/pixi/renderers/webgl/WebGLGraphics.js @@ -62,20 +62,15 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) gl.uniform2f(PIXI.primitiveShader.offsetVector, -PIXI.offset.x, -PIXI.offset.y); gl.uniform1f(PIXI.primitiveShader.alpha, graphics.worldAlpha); - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - // WHY DOES THIS LINE NEED TO BE THERE??? - //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - // its not even used.. but need to be set or it breaks? - // only on pc though.. - gl.vertexAttribPointer(PIXI.primitiveShader.aVertexPosition, 2, gl.FLOAT, false, 4 * 6, 0); gl.vertexAttribPointer(PIXI.primitiveShader.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4); // set the index buffer! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); + gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); PIXI.deactivatePrimitiveShader(); @@ -396,16 +391,27 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y); denom = a1*b2 - a2*b1; - - if (denom == 0) { - denom+=1; - } + + if(Math.abs(denom) < 0.1 ) + { + + denom+=10.1; + verts.push(p2x - perpx , p2y - perpy, + r, g, b, alpha); + + verts.push(p2x + perpx , p2y + perpy, + r, g, b, alpha); + + continue; + } px = (b1*c2 - b2*c1)/denom; py = (a2*c1 - a1*c2)/denom; + pdist = (px -p2x) * (px -p2x) + (py -p2y) + (py -p2y); + if(pdist > 140 * 140) { perp3x = perpx - perp2x; @@ -430,6 +436,7 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) } else { + verts.push(px , py); verts.push(r, g, b, alpha); diff --git a/src/pixi/renderers/webgl/WebGLShaders.js b/src/pixi/renderers/webgl/WebGLShaders.js index af57c95..44123d2 100644 --- a/src/pixi/renderers/webgl/WebGLShaders.js +++ b/src/pixi/renderers/webgl/WebGLShaders.js @@ -30,7 +30,13 @@ PIXI.activatePrimitiveShader = function() var gl = PIXI.gl; gl.useProgram(PIXI.primitiveShader.program); + + gl.disableVertexAttribArray(PIXI.defaultShader.aVertexPosition); + gl.disableVertexAttribArray(PIXI.defaultShader.colorAttribute); gl.disableVertexAttribArray(PIXI.defaultShader.aTextureCoord); + + gl.enableVertexAttribArray(PIXI.primitiveShader.aVertexPosition); + gl.enableVertexAttribArray(PIXI.primitiveShader.colorAttribute); } PIXI.deactivatePrimitiveShader = function() @@ -38,7 +44,14 @@ PIXI.deactivatePrimitiveShader = function() var gl = PIXI.gl; gl.useProgram(PIXI.defaultShader.program); + + gl.disableVertexAttribArray(PIXI.primitiveShader.aVertexPosition); + gl.disableVertexAttribArray(PIXI.primitiveShader.colorAttribute); + + gl.enableVertexAttribArray(PIXI.defaultShader.aVertexPosition); + gl.enableVertexAttribArray(PIXI.defaultShader.colorAttribute); gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord); + } PIXI.activateStripShader = function() From c165b2ebbdff8201b6625e95dd201b5592ba703e Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Sun, 3 Nov 2013 17:50:39 +0000 Subject: [PATCH 69/96] Moved program uniforms Moved program uniforms locations to the PixiShader rather than the glProgram --- bin/pixi.dev.js | 14 +++++++------- bin/pixi.js | 2 +- src/pixi/renderers/webgl/PixiShader.js | 14 +++++++------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/bin/pixi.dev.js b/bin/pixi.dev.js index 11f4d76..56b7360 100644 --- a/bin/pixi.dev.js +++ b/bin/pixi.dev.js @@ -3847,8 +3847,8 @@ PIXI.PixiShader.prototype.init = function() { // get the uniform locations.. - program[key] = gl.getUniformLocation(program, key); - + // program[key] = + this.uniforms[key].uniformLocation = gl.getUniformLocation(program, key); } @@ -3868,21 +3868,21 @@ PIXI.PixiShader.prototype.syncUniforms = function() // need to grow this! if(type == "f") { - gl.uniform1f(this.program[key], this.uniforms[key].value); + gl.uniform1f(this.uniforms[key].uniformLocation, this.uniforms[key].value); } if(type == "f2") { // console.log(this.program[key]) - gl.uniform2f(this.program[key], this.uniforms[key].value.x, this.uniforms[key].value.y); + gl.uniform2f(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y); } else if(type == "f4") { // console.log(this.uniforms[key].value) - gl.uniform4fv(this.program[key], this.uniforms[key].value); + gl.uniform4fv(this.uniforms[key].uniformLocation, this.uniforms[key].value); } else if(type == "mat4") { - gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); + gl.uniformMatrix4fv(this.uniforms[key].uniformLocation, false, this.uniforms[key].value); } else if(type == "sampler2D") { @@ -3892,7 +3892,7 @@ PIXI.PixiShader.prototype.syncUniforms = function() gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, texture.baseTexture._glTexture); - gl.uniform1i(this.program[key], 1); + gl.uniform1i(this.uniforms[key].uniformLocation, 1); // activate texture.. // gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); diff --git a/bin/pixi.js b/bin/pixi.js index dbe9411..5485500 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -10,7 +10,7 @@ * http://www.opensource.org/licenses/mit-license.php */ !function(){function c(){return f.Matrix="undefined"!=typeof Float32Array?Float32Array:Array,f.Matrix}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}var e=this,f=f||{};f.Point=function(a,b){this.x=a||0,this.y=b||0},f.Point.prototype.clone=function(){return new f.Point(this.x,this.y)},f.Point.prototype.constructor=f.Point,f.Rectangle=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Rectangle.prototype.clone=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Rectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},f.Rectangle.prototype.constructor=f.Rectangle,f.Polygon=function(a){if(a instanceof Array||(a=Array.prototype.slice.call(arguments)),"number"==typeof a[0]){for(var b=[],c=0,d=a.length;d>c;c+=2)b.push(new f.Point(a[c],a[c+1]));a=b}this.points=a},f.Polygon.prototype.clone=function(){for(var a=[],b=0;bb!=i>b&&(h-f)*(b-g)/(i-g)+f>a;j&&(c=!c)}return c},f.Polygon.prototype.constructor=f.Polygon,f.Circle=function(a,b,c){this.x=a||0,this.y=b||0,this.radius=c||0},f.Circle.prototype.clone=function(){return new f.Circle(this.x,this.y,this.radius)},f.Circle.prototype.contains=function(a,b){if(this.radius<=0)return!1;var c=this.x-a,d=this.y-b,e=this.radius*this.radius;return c*=c,d*=d,e>=c+d},f.Circle.prototype.constructor=f.Circle,f.Ellipse=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Ellipse.prototype.clone=function(){return new f.Ellipse(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=(a-this.x)/this.width-.5,d=(b-this.y)/this.height-.5;return c*=c,d*=d,.25>c+d},f.Ellipse.getBounds=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.constructor=f.Ellipse,c(),f.mat3={},f.mat3.create=function(){var a=new f.Matrix(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat3.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat4={},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat3.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=b[0],n=b[1],o=b[2],p=b[3],q=b[4],r=b[5],s=b[6],t=b[7],u=b[8];return c[0]=m*d+n*g+o*j,c[1]=m*e+n*h+o*k,c[2]=m*f+n*i+o*l,c[3]=p*d+q*g+r*j,c[4]=p*e+q*h+r*k,c[5]=p*f+q*i+r*l,c[6]=s*d+t*g+u*j,c[7]=s*e+t*h+u*k,c[8]=s*f+t*i+u*l,c},f.mat3.clone=function(a){var b=new f.Matrix(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},f.mat3.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[5];return a[1]=a[3],a[2]=a[6],a[3]=c,a[5]=a[7],a[6]=d,a[7]=e,a}return b[0]=a[0],b[1]=a[3],b[2]=a[6],b[3]=a[1],b[4]=a[4],b[5]=a[7],b[6]=a[2],b[7]=a[5],b[8]=a[8],b},f.mat3.toMat4=function(a,b){return b||(b=f.mat4.create()),b[15]=1,b[14]=0,b[13]=0,b[12]=0,b[11]=0,b[10]=a[8],b[9]=a[7],b[8]=a[6],b[7]=0,b[6]=a[5],b[5]=a[4],b[4]=a[3],b[3]=0,b[2]=a[2],b[1]=a[1],b[0]=a[0],b},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat4.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[3],f=a[6],g=a[7],h=a[11];return a[1]=a[4],a[2]=a[8],a[3]=a[12],a[4]=c,a[6]=a[9],a[7]=a[13],a[8]=d,a[9]=f,a[11]=a[14],a[12]=e,a[13]=g,a[14]=h,a}return b[0]=a[0],b[1]=a[4],b[2]=a[8],b[3]=a[12],b[4]=a[1],b[5]=a[5],b[6]=a[9],b[7]=a[13],b[8]=a[2],b[9]=a[6],b[10]=a[10],b[11]=a[14],b[12]=a[3],b[13]=a[7],b[14]=a[11],b[15]=a[15],b},f.mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=b[0],u=b[1],v=b[2],w=b[3];return c[0]=t*d+u*h+v*l+w*p,c[1]=t*e+u*i+v*m+w*q,c[2]=t*f+u*j+v*n+w*r,c[3]=t*g+u*k+v*o+w*s,t=b[4],u=b[5],v=b[6],w=b[7],c[4]=t*d+u*h+v*l+w*p,c[5]=t*e+u*i+v*m+w*q,c[6]=t*f+u*j+v*n+w*r,c[7]=t*g+u*k+v*o+w*s,t=b[8],u=b[9],v=b[10],w=b[11],c[8]=t*d+u*h+v*l+w*p,c[9]=t*e+u*i+v*m+w*q,c[10]=t*f+u*j+v*n+w*r,c[11]=t*g+u*k+v*o+w*s,t=b[12],u=b[13],v=b[14],w=b[15],c[12]=t*d+u*h+v*l+w*p,c[13]=t*e+u*i+v*m+w*q,c[14]=t*f+u*j+v*n+w*r,c[15]=t*g+u*k+v*o+w*s,c},f.DisplayObject=function(){this.last=this,this.first=this,this.position=new f.Point,this.scale=new f.Point(1,1),this.pivot=new f.Point(0,0),this.rotation=0,this.alpha=1,this.visible=!0,this.hitArea=null,this.buttonMode=!1,this.renderable=!1,this.parent=null,this.stage=null,this.worldAlpha=1,this._interactive=!1,this.worldTransform=f.mat3.create(),this.localTransform=f.mat3.create(),this.color=[],this.dynamic=!0,this._sr=0,this._cr=1,this.filterArea=new f.Rectangle(0,0,1,1)},f.DisplayObject.prototype.constructor=f.DisplayObject,f.DisplayObject.prototype.setInteractive=function(a){this.interactive=a},Object.defineProperty(f.DisplayObject.prototype,"interactive",{get:function(){return this._interactive},set:function(a){this._interactive=a,this.stage&&(this.stage.dirty=!0)}}),Object.defineProperty(f.DisplayObject.prototype,"mask",{get:function(){return this._mask},set:function(a){a?this._mask?(a.start=this._mask.start,a.end=this._mask.end):(this.addFilter(a),a.renderable=!1):(this.removeFilter(this._mask),this._mask.renderable=!0),this._mask=a}}),Object.defineProperty(f.DisplayObject.prototype,"filters",{get:function(){return this._filters},set:function(a){if(a){this._filters&&this.removeFilter(this._filters),this.addFilter(a);for(var b=[],c=0;c=0&&b<=this.children.length))throw new Error(a+" The index "+b+" supplied is out of bounds "+this.children.length);if(void 0!=a.parent&&a.parent.removeChild(a),a.parent=this,this.stage){var c=a;do c.interactive&&(this.stage.dirty=!0),c.stage=this.stage,c=c._iNext;while(c)}var d,e,f=a.first,g=a.last;if(b==this.children.length){e=this.last;for(var h=this,i=this.last;h;)h.last==i&&(h.last=a.last),h=h.parent}else e=0==b?this:this.children[b-1].last;d=e._iNext,d&&(d._iPrev=g,g._iNext=d),f._iPrev=e,e._iNext=f,this.children.splice(b,0,a),this.__renderGroup&&(a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a),this.__renderGroup.addDisplayObjectAndChildren(a))},f.DisplayObjectContainer.prototype.swapChildren=function(){},f.DisplayObjectContainer.prototype.getChildAt=function(a){if(a>=0&&aa;a++)this.children[a].updateTransform()}},f.blendModes={},f.blendModes.NORMAL=0,f.blendModes.SCREEN=1,f.Sprite=function(a){f.DisplayObjectContainer.call(this),this.anchor=new f.Point,this.texture=a,this.blendMode=f.blendModes.NORMAL,this._width=0,this._height=0,a.baseTexture.hasLoaded?this.updateFrame=!0:(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Sprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Sprite.prototype.constructor=f.Sprite,Object.defineProperty(f.Sprite.prototype,"width",{get:function(){return this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(f.Sprite.prototype,"height",{get:function(){return this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),f.Sprite.prototype.setTexture=function(a){this.texture.baseTexture!=a.baseTexture?(this.textureChange=!0,this.texture=a,this.__renderGroup&&this.__renderGroup.updateTexture(this)):this.texture=a,this.updateFrame=!0},f.Sprite.prototype.onTextureUpdate=function(){this._width&&(this.scale.x=this._width/this.texture.frame.width),this._height&&(this.scale.y=this._height/this.texture.frame.height),this.updateFrame=!0},f.Sprite.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache"+this);return new f.Sprite(b)},f.Sprite.fromImage=function(a){var b=f.Texture.fromImage(a);return new f.Sprite(b)},f.MovieClip=function(a){f.Sprite.call(this,a[0]),this.textures=a,this.animationSpeed=1,this.loop=!0,this.onComplete=null,this.currentFrame=0,this.playing=!1},f.MovieClip.prototype=Object.create(f.Sprite.prototype),f.MovieClip.prototype.constructor=f.MovieClip,Object.defineProperty(f.MovieClip.prototype,"totalFrames",{get:function(){return this.textures.length}}),f.MovieClip.prototype.stop=function(){this.playing=!1},f.MovieClip.prototype.play=function(){this.playing=!0},f.MovieClip.prototype.gotoAndStop=function(a){this.playing=!1,this.currentFrame=a;var b=0|this.currentFrame+.5;this.setTexture(this.textures[b%this.textures.length])},f.MovieClip.prototype.gotoAndPlay=function(a){this.currentFrame=a,this.playing=!0},f.MovieClip.prototype.updateTransform=function(){if(f.Sprite.prototype.updateTransform.call(this),this.playing){this.currentFrame+=this.animationSpeed;var a=0|this.currentFrame+.5;this.loop||a=this.textures.length&&(this.gotoAndStop(this.textures.length-1),this.onComplete&&this.onComplete())}},f.FilterBlock=function(){this.visible=!0,this.renderable=!0},f.Text=function(a,b){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),f.Sprite.call(this,f.Texture.fromCanvas(this.canvas)),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.Text.prototype=Object.create(f.Sprite.prototype),f.Text.prototype.constructor=f.Text,f.Text.prototype.setStyle=function(a){a=a||{},a.font=a.font||"bold 20pt Arial",a.fill=a.fill||"black",a.align=a.align||"left",a.stroke=a.stroke||"black",a.strokeThickness=a.strokeThickness||0,a.wordWrap=a.wordWrap||!1,a.wordWrapWidth=a.wordWrapWidth||100,this.style=a,this.dirty=!0},f.Text.prototype.setText=function(a){this.text=a.toString()||" ",this.dirty=!0},f.Text.prototype.updateText=function(){this.context.font=this.style.font;var a=this.text;this.style.wordWrap&&(a=this.wordWrap(this.text));for(var b=a.split(/(?:\r\n|\r|\n)/),c=[],d=0,e=0;ee?f:arguments.callee(a,b,f,d,e):arguments.callee(a,b,c,f,e)},c=function(a,c,d){if(a.measureText(c).width<=d||c.length<1)return c;var e=b(a,c,0,c.length,d);return c.substring(0,e)+"\n"+arguments.callee(a,c.substring(e),d)},d="",e=a.split("\n"),f=0;f=2?parseInt(b[b.length-2],10):f.BitmapText.fonts[this.fontName].size,this.dirty=!0},f.BitmapText.prototype.updateText=function(){for(var a=f.BitmapText.fonts[this.fontName],b=new f.Point,c=null,d=[],e=0,g=[],h=0,i=this.fontSize/a.size,j=0;j=j;j++){var n=0;"right"==this.style.align?n=e-g[j]:"center"==this.style.align&&(n=(e-g[j])/2),m.push(n)}for(j=0;j0;)this.removeChild(this.getChildAt(0));this.updateText(),this.dirty=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.BitmapText.fonts={},f.InteractionManager=function(a){this.stage=a,this.mouse=new f.InteractionData,this.touchs={},this.tempPoint=new f.Point,this.mouseoverEnabled=!0,this.pool=[],this.interactiveItems=[],this.interactionDOMElement=null,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseOut=this.onMouseOut.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.last=0},f.InteractionManager.prototype.constructor=f.InteractionManager,f.InteractionManager.prototype.collectInteractiveSprite=function(a,b){for(var c=a.children,d=c.length,e=d-1;e>=0;e--){var f=c[e];f.interactive?(b.interactiveChildren=!0,this.interactiveItems.push(f),f.children.length>0&&this.collectInteractiveSprite(f,f)):(f.__iParent=null,f.children.length>0&&this.collectInteractiveSprite(f,b))}},f.InteractionManager.prototype.setTarget=function(a){this.target=a,null===this.interactionDOMElement&&this.setTargetDomElement(a.view),document.body.addEventListener("mouseup",this.onMouseUp,!0)},f.InteractionManager.prototype.setTargetDomElement=function(a){null!==this.interactionDOMElement&&(this.interactionDOMElement.style["-ms-content-zooming"]="",this.interactionDOMElement.style["-ms-touch-action"]="",this.interactionDOMElement.removeEventListener("mousemove",this.onMouseMove,!0),this.interactionDOMElement.removeEventListener("mousedown",this.onMouseDown,!0),this.interactionDOMElement.removeEventListener("mouseout",this.onMouseOut,!0),this.interactionDOMElement.removeEventListener("touchstart",this.onTouchStart,!0),this.interactionDOMElement.removeEventListener("touchend",this.onTouchEnd,!0),this.interactionDOMElement.removeEventListener("touchmove",this.onTouchMove,!0)),window.navigator.msPointerEnabled&&(a.style["-ms-content-zooming"]="none",a.style["-ms-touch-action"]="none"),this.interactionDOMElement=a,a.addEventListener("mousemove",this.onMouseMove,!0),a.addEventListener("mousedown",this.onMouseDown,!0),a.addEventListener("mouseout",this.onMouseOut,!0),a.addEventListener("touchstart",this.onTouchStart,!0),a.addEventListener("touchend",this.onTouchEnd,!0),a.addEventListener("touchmove",this.onTouchMove,!0)},f.InteractionManager.prototype.update=function(){if(this.target){var a=Date.now(),b=a-this.last;if(b=30*b/1e3,!(1>b)){if(this.last=a,this.dirty){this.dirty=!1;for(var c=this.interactiveItems.length,d=0;c>d;d++)this.interactiveItems[d].interactiveChildren=!1;this.interactiveItems=[],this.stage.interactive&&this.interactiveItems.push(this.stage),this.collectInteractiveSprite(this.stage,this.stage)}var e=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var d=0;e>d;d++){var f=this.interactiveItems[d];(f.mouseover||f.mouseout||f.buttonMode)&&(f.__hit=this.hitTest(f,this.mouse),this.mouse.target=f,f.__hit?(f.buttonMode&&(this.interactionDOMElement.style.cursor="pointer"),f.__isOver||(f.mouseover&&f.mouseover(this.mouse),f.__isOver=!0)):f.__isOver&&(f.mouseout&&f.mouseout(this.mouse),f.__isOver=!1))}}}},f.InteractionManager.prototype.onMouseMove=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactionDOMElement.getBoundingClientRect();this.mouse.global.x=(a.clientX-b.left)*(this.target.width/b.width),this.mouse.global.y=(a.clientY-b.top)*(this.target.height/b.height);var c=this.interactiveItems.length;this.mouse.global;for(var d=0;c>d;d++){var e=this.interactiveItems[d];e.mousemove&&e.mousemove(this.mouse)}},f.InteractionManager.prototype.onMouseDown=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactiveItems.length;this.mouse.global,this.stage;for(var c=0;b>c;c++){var d=this.interactiveItems[c];if((d.mousedown||d.click)&&(d.__mouseIsDown=!0,d.__hit=this.hitTest(d,this.mouse),d.__hit&&(d.mousedown&&d.mousedown(this.mouse),d.__isDown=!0,!d.interactiveChildren)))break}},f.InteractionManager.prototype.onMouseOut=function(){var a=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var b=0;a>b;b++){var c=this.interactiveItems[b];c.__isOver&&(this.mouse.target=c,c.mouseout&&c.mouseout(this.mouse),c.__isOver=!1)}},f.InteractionManager.prototype.onMouseUp=function(a){this.mouse.originalEvent=a||window.event,this.mouse.global;for(var b=this.interactiveItems.length,c=!1,d=0;b>d;d++){var e=this.interactiveItems[d];(e.mouseup||e.mouseupoutside||e.click)&&(e.__hit=this.hitTest(e,this.mouse),e.__hit&&!c?(e.mouseup&&e.mouseup(this.mouse),e.__isDown&&e.click&&e.click(this.mouse),e.interactiveChildren||(c=!0)):e.__isDown&&e.mouseupoutside&&e.mouseupoutside(this.mouse),e.__isDown=!1)}},f.InteractionManager.prototype.hitTest=function(a,b){var c=b.global;if(a.vcount!==f.visibleCount)return!1;var d=a instanceof f.Sprite,e=a.worldTransform,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=1/(g*k+h*-j),n=k*m*c.x+-h*m*c.y+(l*h-i*k)*m,o=g*m*c.y+-j*m*c.x+(-l*g+i*j)*m;if(b.target=a,a.hitArea&&a.hitArea.contains)return a.hitArea.contains(n,o)?(b.target=a,!0):!1;if(d){var p,q=a.texture.frame.width,r=a.texture.frame.height,s=-q*a.anchor.x;if(n>s&&s+q>n&&(p=-r*a.anchor.y,o>p&&p+r>o))return b.target=a,!0}for(var t=a.children.length,u=0;t>u;u++){var v=a.children[u],w=this.hitTest(v,b);if(w)return b.target=a,!0}return!1},f.InteractionManager.prototype.onTouchMove=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;dd;d++){var h=this.interactiveItems[d];h.touchmove&&h.touchmove(f)}},f.InteractionManager.prototype.onTouchStart=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i];if((j.touchstart||j.tap)&&(j.__hit=this.hitTest(j,g),j.__hit&&(j.touchstart&&j.touchstart(g),j.__isDown=!0,j.__touchData=g,!j.interactiveChildren)))break}}},f.InteractionManager.prototype.onTouchEnd=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i],k=j.__touchData;j.__hit=this.hitTest(j,f),k==f&&(f.originalEvent=a||window.event,(j.touchend||j.tap)&&(j.__hit&&!g?(j.touchend&&j.touchend(f),j.__isDown&&j.tap&&j.tap(f),j.interactiveChildren||(g=!0)):j.__isDown&&j.touchendoutside&&j.touchendoutside(f),j.__isDown=!1),j.__touchData=null)}this.pool.push(f),this.touchs[e.identifier]=null}},f.InteractionData=function(){this.global=new f.Point,this.local=new f.Point,this.target,this.originalEvent},f.InteractionData.prototype.getLocalPosition=function(a){var b=a.worldTransform,c=this.global,d=b[0],e=b[1],g=b[2],h=b[3],i=b[4],j=b[5],k=1/(d*i+e*-h);return new f.Point(i*k*c.x+-e*k*c.y+(j*e-g*i)*k,d*k*c.y+-h*k*c.x+(-j*d+g*h)*k)},f.InteractionData.prototype.constructor=f.InteractionData,f.Stage=function(a){f.DisplayObjectContainer.call(this),this.worldTransform=f.mat3.create(),this.interactive=!0,this.interactionManager=new f.InteractionManager(this),this.dirty=!0,this.__childrenAdded=[],this.__childrenRemoved=[],this.stage=this,this.stage.hitArea=new f.Rectangle(0,0,1e5,1e5),this.setBackgroundColor(a),this.worldVisible=!0},f.Stage.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Stage.prototype.constructor=f.Stage,f.Stage.prototype.setInteractionDelegate=function(a){this.interactionManager.setTargetDomElement(a)},f.Stage.prototype.updateTransform=function(){this.worldAlpha=1,this.vcount=f.visibleCount;for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform();this.dirty&&(this.dirty=!1,this.interactionManager.dirty=!0),this.interactive&&this.interactionManager.update()},f.Stage.prototype.setBackgroundColor=function(a){this.backgroundColor=a||0,this.backgroundColorSplit=d(this.backgroundColor);var b=this.backgroundColor.toString(16);b="000000".substr(0,6-b.length)+b,this.backgroundColorString="#"+b},f.Stage.prototype.getMousePosition=function(){return this.interactionManager.mouse.global};for(var h=0,i=["ms","moz","webkit","o"],j=0;j>>>>>>>>"),console.log("_");var b=0,c=a.first;for(console.log(c);c._iNext;)if(b++,c=c._iNext,console.log(c),b>100){console.log("BREAK");break}},f.EventTarget=function(){var a={};this.addEventListener=this.on=function(b,c){void 0===a[b]&&(a[b]=[]),-1===a[b].indexOf(c)&&a[b].push(c)},this.dispatchEvent=this.emit=function(b){if(a[b.type]&&a[b.type].length)for(var c=0,d=a[b.type].length;d>c;c++)a[b.type][c](b)},this.removeEventListener=this.off=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)}},f.autoDetectRenderer=function(a,b,c,d,e){a||(a=800),b||(b=600);var g=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}();if(g){var h=-1!=navigator.userAgent.toLowerCase().indexOf("msie");g=!h}return g?new f.WebGLRenderer(a,b,c,d,e):new f.CanvasRenderer(a,b,c,d)},f.PolyK={},f.PolyK.Triangulate=function(a){var b=!0,c=a.length>>1;if(3>c)return[];for(var d=[],e=[],g=0;c>g;g++)e.push(g);for(var g=0,h=c;h>3;){var i=e[(g+0)%h],j=e[(g+1)%h],k=e[(g+2)%h],l=a[2*i],m=a[2*i+1],n=a[2*j],o=a[2*j+1],p=a[2*k],q=a[2*k+1],r=!1;if(f.PolyK._convex(l,m,n,o,p,q,b)){r=!0;for(var s=0;h>s;s++){var t=e[s];if(t!=i&&t!=j&&t!=k&&f.PolyK._PointInTriangle(a[2*t],a[2*t+1],l,m,n,o,p,q)){r=!1;break}}}if(r)d.push(i,j,k),e.splice((g+1)%h,1),h--,g=0;else if(g++>3*h){if(!b)return console.log("PIXI Warning: shape too complex to fill"),[];var d=[];e=[];for(var g=0;c>g;g++)e.push(g);g=0,h=c,b=!1}}return d.push(e[0],e[1],e[2]),d},f.PolyK._PointInTriangle=function(a,b,c,d,e,f,g,h){var i=g-c,j=h-d,k=e-c,l=f-d,m=a-c,n=b-d,o=i*i+j*j,p=i*k+j*l,q=i*m+j*n,r=k*k+l*l,s=k*m+l*n,t=1/(o*r-p*p),u=(r*q-p*s)*t,v=(o*s-p*q)*t;return u>=0&&v>=0&&1>u+v},f.PolyK._convex=function(a,b,c,d,e,f,g){return(b-d)*(e-c)+(c-a)*(f-d)>=0==g},f.initDefaultShaders=function(){f.primitiveShader=new f.PrimitiveShader,f.primitiveShader.init(),f.stripShader=new f.StripShader,f.stripShader.init(),f.defaultShader=new f.PixiShader,f.defaultShader.init();var a=f.gl,b=f.defaultShader.program;a.useProgram(b),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.primitiveShader.program),a.disableVertexAttribArray(f.defaultShader.aVertexPosition),a.disableVertexAttribArray(f.defaultShader.colorAttribute),a.disableVertexAttribArray(f.defaultShader.aTextureCoord),a.enableVertexAttribArray(f.primitiveShader.aVertexPosition),a.enableVertexAttribArray(f.primitiveShader.colorAttribute)},f.deactivatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program),a.disableVertexAttribArray(f.primitiveShader.aVertexPosition),a.disableVertexAttribArray(f.primitiveShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activateStripShader=function(){var a=f.gl;a.useProgram(f.stripShader.program)},f.deactivateStripShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program)},f.CompileVertexShader=function(a,b){return f._CompileShader(a,b,a.VERTEX_SHADER)},f.CompileFragmentShader=function(a,b){return f._CompileShader(a,b,a.FRAGMENT_SHADER)},f._CompileShader=function(a,b,c){var d=b.join("\n"),e=a.createShader(c);return a.shaderSource(e,d),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)?e:(console.log(a.getShaderInfoLog(e)),null)},f.compileProgram=function(a,b){var c=f.gl,d=f.CompileFragmentShader(c,b),e=f.CompileVertexShader(c,a),g=c.createProgram();return c.attachShader(g,e),c.attachShader(g,d),c.linkProgram(g),c.getProgramParameter(g,c.LINK_STATUS)||console.log("Could not initialise shaders"),g},f.PixiShader=function(){this.program,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;","}"]},f.PixiShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc||f.PixiShader.defaultVertexSrc,this.fragmentSrc),b=f.gl; -b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord");for(var c in this.uniforms)a[c]=b.getUniformLocation(a,c);this.program=a},f.PixiShader.prototype.syncUniforms=function(){var a=f.gl;for(var b in this.uniforms){var c=this.uniforms[b].type;if("f"==c&&a.uniform1f(this.program[b],this.uniforms[b].value),"f2"==c)a.uniform2f(this.program[b],this.uniforms[b].value.x,this.uniforms[b].value.y);else if("f4"==c)a.uniform4fv(this.program[b],this.uniforms[b].value);else if("mat4"==c)a.uniformMatrix4fv(this.program[b],!1,this.uniforms[b].value);else if("sampler2D"==c){var d=this.uniforms[b].value;a.activeTexture(a.TEXTURE1),a.bindTexture(a.TEXTURE_2D,d.baseTexture._glTexture),a.uniform1i(this.program[b],1)}}},f.PixiShader.defaultVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","varying float vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"],f.StripShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying float vColor;","uniform float alpha;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));","gl_FragColor = gl_FragColor * alpha;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","varying vec2 vTextureCoord;","varying vec2 offsetVector;","varying float vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"]},f.StripShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.PrimitiveShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","gl_FragColor = vColor;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec4 aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform float alpha;","varying vec4 vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","vColor = aColor * alpha;","}"]},f.PrimitiveShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.WebGLGraphics=function(){},f.WebGLGraphics.renderGraphics=function(a,b){var c=f.gl;a._webGL||(a._webGL={points:[],indices:[],lastIndex:0,buffer:c.createBuffer(),indexBuffer:c.createBuffer()}),a.dirty&&(a.dirty=!1,a.clearDirty&&(a.clearDirty=!1,a._webGL.lastIndex=0,a._webGL.points=[],a._webGL.indices=[]),f.WebGLGraphics.updateGraphics(a)),f.activatePrimitiveShader();var d=f.mat3.clone(a.worldTransform);f.mat3.transpose(d),c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA),c.uniformMatrix3fv(f.primitiveShader.translationMatrix,!1,d),c.uniform2f(f.primitiveShader.projectionVector,b.x,-b.y),c.uniform2f(f.primitiveShader.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(f.primitiveShader.alpha,a.worldAlpha),c.bindBuffer(c.ARRAY_BUFFER,a._webGL.buffer),c.vertexAttribPointer(f.primitiveShader.aVertexPosition,2,c.FLOAT,!1,24,0),c.vertexAttribPointer(f.primitiveShader.colorAttribute,4,c.FLOAT,!1,24,8),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),c.drawElements(c.TRIANGLE_STRIP,a._webGL.indices.length,c.UNSIGNED_SHORT,0),f.deactivatePrimitiveShader()},f.WebGLGraphics.updateGraphics=function(a){for(var b=a._webGL.lastIndex;b3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){if(a.lineWidth%2)for(var e=0;ee;e++)k=c[2*(e-1)],l=c[2*(e-1)+1],m=c[2*e],n=c[2*e+1],o=c[2*(e+1)],p=c[2*(e+1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,s=-(n-p),t=m-o,E=Math.sqrt(s*s+t*t),s/=E,t/=E,s*=K,t*=K,w=-r+l-(-r+n),x=-q+m-(-q+k),y=(-q+k)*(-r+n)-(-q+m)*(-r+l),z=-t+p-(-t+n),A=-s+m-(-s+o),B=(-s+o)*(-t+n)-(-s+m)*(-t+p),C=w*A-z*x,Math.abs(C)<.1?(C+=10.1,F.push(m-q,n-r,N,O,P,M),F.push(m+q,n+r,N,O,P,M)):(px=(x*B-A*y)/C,py=(z*y-w*B)/C,D=(px-m)*(px-m)+(py-n)+(py-n),D>19600?(u=q-s,v=r-t,E=Math.sqrt(u*u+v*v),u/=E,v/=E,u*=K,v*=K,F.push(m-u,n-v),F.push(N,O,P,M),F.push(m+u,n+v),F.push(N,O,P,M),F.push(m-u,n-v),F.push(N,O,P,M),I++):(F.push(px,py),F.push(N,O,P,M),F.push(m-(px-m),n-(py-n)),F.push(N,O,P,M)));k=c[2*(H-2)],l=c[2*(H-2)+1],m=c[2*(H-1)],n=c[2*(H-1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,F.push(m-q,n-r),F.push(N,O,P,M),F.push(m+q,n+r),F.push(N,O,P,M),G.push(J);for(var e=0;I>e;e++)G.push(J++);G.push(J-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},flip=!1;var l=[],m=0;f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;if(a.open)a.data instanceof Array?this.filterManager.pushFilter(a):(m++,l.push(a),c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.INCR),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP));else if(a.data instanceof Array)this.filterManager.popFilter();else{var d=l.pop(a);d&&(c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.DECR),f.WebGLGraphics.renderGraphics(d.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)),c.disable(c.STENCIL_TEST)}},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(){this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;h3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){if(a.lineWidth%2)for(var e=0;ee;e++)k=c[2*(e-1)],l=c[2*(e-1)+1],m=c[2*e],n=c[2*e+1],o=c[2*(e+1)],p=c[2*(e+1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,s=-(n-p),t=m-o,E=Math.sqrt(s*s+t*t),s/=E,t/=E,s*=K,t*=K,w=-r+l-(-r+n),x=-q+m-(-q+k),y=(-q+k)*(-r+n)-(-q+m)*(-r+l),z=-t+p-(-t+n),A=-s+m-(-s+o),B=(-s+o)*(-t+n)-(-s+m)*(-t+p),C=w*A-z*x,Math.abs(C)<.1?(C+=10.1,F.push(m-q,n-r,N,O,P,M),F.push(m+q,n+r,N,O,P,M)):(px=(x*B-A*y)/C,py=(z*y-w*B)/C,D=(px-m)*(px-m)+(py-n)+(py-n),D>19600?(u=q-s,v=r-t,E=Math.sqrt(u*u+v*v),u/=E,v/=E,u*=K,v*=K,F.push(m-u,n-v),F.push(N,O,P,M),F.push(m+u,n+v),F.push(N,O,P,M),F.push(m-u,n-v),F.push(N,O,P,M),I++):(F.push(px,py),F.push(N,O,P,M),F.push(m-(px-m),n-(py-n)),F.push(N,O,P,M)));k=c[2*(H-2)],l=c[2*(H-2)+1],m=c[2*(H-1)],n=c[2*(H-1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,F.push(m-q,n-r),F.push(N,O,P,M),F.push(m+q,n+r),F.push(N,O,P,M),G.push(J);for(var e=0;I>e;e++)G.push(J++);G.push(J-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},flip=!1;var l=[],m=0;f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;if(a.open)a.data instanceof Array?this.filterManager.pushFilter(a):(m++,l.push(a),c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.INCR),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP));else if(a.data instanceof Array)this.filterManager.popFilter();else{var d=l.pop(a);d&&(c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.DECR),f.WebGLGraphics.renderGraphics(d.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)),c.disable(c.STENCIL_TEST)}},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(){this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;hs?s:E,E=E>t?t:E,E=E>u?u:E,E=E>v?v:E,F=F>w?w:F,F=F>x?x:F,F=F>y?y:F,F=F>z?z:F,C=s>C?s:C,C=t>C?t:C,C=u>C?u:C,C=v>C?v:C,D=w>D?w:D,D=x>D?x:D,D=y>D?y:D,D=z>D?z:D),l=!1,A=A._iNext}while(A!=B);a.filterArea.x=E,a.filterArea.y=F,a.filterArea.width=C-E,a.filterArea.height=D-F},f.FilterTexture=function(a,b){var c=f.gl;this.frameBuffer=c.createFramebuffer(),this.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,this.texture),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.bindFramebuffer(c.FRAMEBUFFER,this.framebuffer),c.bindFramebuffer(c.FRAMEBUFFER,this.frameBuffer),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,this.texture,0),this.resize(a,b)},f.FilterTexture.prototype.resize=function(a,b){this.width=a,this.height=b;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a,b,0,c.RGBA,c.UNSIGNED_BYTE,null)},f.CanvasRenderer=function(a,b,c,d){this.transparent=d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.context=this.view.getContext("2d"),this.refresh=!0,this.view.width=this.width,this.view.height=this.height,this.count=0},f.CanvasRenderer.prototype.constructor=f.CanvasRenderer,f.CanvasRenderer.prototype.render=function(a){f.texturesToUpdate=[],f.texturesToDestroy=[],f.visibleCount++,a.updateTransform(),this.view.style.backgroundColor==a.backgroundColorString||this.transparent||(this.view.style.backgroundColor=a.backgroundColorString),this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.width,this.height),this.renderDisplayObject(a),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0&&(f.Texture.frameUpdates=[])},f.CanvasRenderer.prototype.resize=function(a,b){this.width=a,this.height=b,this.view.width=a,this.view.height=b},f.CanvasRenderer.prototype.renderDisplayObject=function(a){var b,c=this.context;c.globalCompositeOperation="source-over";var d=a.last._iNext;a=a.first;do if(b=a.worldTransform,a.visible)if(a.renderable){if(a instanceof f.Sprite){var e=a.texture.frame;e&&e.width&&e.height&&(c.globalAlpha=a.worldAlpha,c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),c.drawImage(a.texture.baseTexture.source,e.x,e.y,e.width,e.height,a.anchor.x*-e.width,a.anchor.y*-e.height,e.width,e.height))}else if(a instanceof f.Strip)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderStrip(a);else if(a instanceof f.TilingSprite)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderTilingSprite(a);else if(a instanceof f.CustomRenderable)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),a.renderCanvas(this);else if(a instanceof f.Graphics)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),f.CanvasGraphics.renderGraphics(a,c);else if(a instanceof f.FilterBlock&&a.data instanceof f.Graphics){var g=a.data;if(a.open){c.save();var h=g.alpha,i=g.worldTransform;c.setTransform(i[0],i[3],i[1],i[4],i[2],i[5]),g.worldAlpha=.5,c.worldAlpha=0,f.CanvasGraphics.renderGraphicsMask(g,c),c.clip(),g.worldAlpha=h}else c.restore()}a=a._iNext}else a=a._iNext;else a=a.last._iNext;while(a!=d)},f.CanvasRenderer.prototype.renderStripFlat=function(a){var b=this.context,c=a.verticies;a.uvs;var d=c.length/2;this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},f.CanvasRenderer.prototype.renderTilingSprite=function(a){var b=this.context;b.globalAlpha=a.worldAlpha,a.__tilePattern||(a.__tilePattern=b.createPattern(a.texture.baseTexture.source,"repeat")),b.beginPath();var c=a.tilePosition,d=a.tileScale;b.scale(d.x,d.y),b.translate(c.x,c.y),b.fillStyle=a.__tilePattern,b.fillRect(-c.x,-c.y,a.width/d.x,a.height/d.y),b.scale(1/d.x,1/d.y),b.translate(-c.x,-c.y),b.closePath()},f.CanvasRenderer.prototype.renderStrip=function(a){var b=this.context,c=a.verticies,d=a.uvs,e=c.length/2;this.count++;for(var f=1;e-2>f;f++){var g=2*f,h=c[g],i=c[g+2],j=c[g+4],k=c[g+1],l=c[g+3],m=c[g+5],n=d[g]*a.texture.width,o=d[g+2]*a.texture.width,p=d[g+4]*a.texture.width,q=d[g+1]*a.texture.height,r=d[g+3]*a.texture.height,s=d[g+5]*a.texture.height;b.save(),b.beginPath(),b.moveTo(h,k),b.lineTo(i,l),b.lineTo(j,m),b.closePath(),b.clip();var t=n*r+q*p+o*s-r*p-q*o-n*s,u=h*r+q*j+i*s-r*j-q*i-h*s,v=n*i+h*p+o*j-i*p-h*o-n*j,w=n*r*j+q*i*p+h*o*s-h*r*p-q*o*j-n*i*s,x=k*r+q*m+l*s-r*m-q*l-k*s,y=n*l+k*p+o*m-l*p-k*o-n*m,z=n*r*m+q*l*p+k*o*s-k*r*p-q*o*m-n*l*s;b.transform(u/t,x/t,v/t,y/t,w/t,z/t),b.drawImage(a.texture.baseTexture.source,0,0),b.restore()}},f.CanvasGraphics=function(){},f.CanvasGraphics.renderGraphics=function(a,b){for(var c=a.worldAlpha,d=0;d1&&(c=1,console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var d=0;1>d;d++){var e=a.graphicsData[d],g=e.points;if(e.type==f.Graphics.POLY){b.beginPath(),b.moveTo(g[0],g[1]);for(var h=1;hb?b:d,e=b+m>e?b+m:e,g=g>c?b:g,h=c+n>h?c+n:h}else if(k===f.Graphics.CIRC||k===f.Graphics.ELIP){b=a.x,c=a.y;var o=a.radius+l/2;d=d>b-o?b-o:d,e=b+o>e?b+o:e,g=g>c-o?c-o:g,h=c+o>h?c+o:h}else for(var p=0;pb-l?b-l:d,e=b+l>e?b+l:e,g=g>c-l?c-l:g,h=c+l>h?c+l:h}this.bounds=new f.Rectangle(d,g,e-d,h-g)}},f.Graphics.POLY=0,f.Graphics.RECT=1,f.Graphics.CIRC=2,f.Graphics.ELIP=3,f.Strip=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.blendMode=f.blendModes.NORMAL;try{this.uvs=new Float32Array([0,1,1,1,1,0,0,1]),this.verticies=new Float32Array([0,0,0,0,0,0,0,0,0]),this.colors=new Float32Array([1,1,1,1]),this.indices=new Uint16Array([0,1,2,3])}catch(d){this.uvs=[0,1,1,1,1,0,0,1],this.verticies=[0,0,0,0,0,0,0,0,0],this.colors=[1,1,1,1],this.indices=[0,1,2,3]}this.width=b,this.height=c,a.baseTexture.hasLoaded?(this.width=this.texture.frame.width,this.height=this.texture.frame.height,this.updateFrame=!0):(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Strip.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Strip.prototype.constructor=f.Strip,f.Strip.prototype.setTexture=function(a){this.texture=a,this.width=a.frame.width,this.height=a.frame.height,this.updateFrame=!0},f.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Rope=function(a,b){f.Strip.call(this,a),this.points=b;try{this.verticies=new Float32Array(4*b.length),this.uvs=new Float32Array(4*b.length),this.colors=new Float32Array(2*b.length),this.indices=new Uint16Array(2*b.length)}catch(c){this.verticies=verticies,this.uvs=uvs,this.colors=colors,this.indices=indices}this.refresh()},f.Rope.prototype=Object.create(f.Strip.prototype),f.Rope.prototype.constructor=f.Rope,f.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=this.indices,d=this.colors,e=a[0],f=a[0];this.count-=.2,b[0]=0,b[1]=1,b[2]=0,b[3]=1,d[0]=1,d[1]=1,c[0]=0,c[1]=1;for(var g=a.length,h=1;g>h;h++){var f=a[h],i=4*h,j=h/(g-1);h%2?(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1):(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1),i=2*h,d[i]=1,d[i+1]=1,i=2*h,c[i]=i,c[i+1]=i+1,e=f}}},f.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var b,c=this.verticies,d=a[0],e={x:0,y:0},g=a[0];this.count-=.2,c[0]=g.x+e.x,c[1]=g.y+e.y,c[2]=g.x-e.x,c[3]=g.y-e.y;for(var h=a.length,i=1;h>i;i++){var g=a[i],j=4*i;b=i1&&(k=1);var l=Math.sqrt(e.x*e.x+e.y*e.y),m=this.texture.height/2;e.x/=l,e.y/=l,e.x*=m,e.y*=m,c[j]=g.x+e.x,c[j+1]=g.y+e.y,c[j+2]=g.x-e.x,c[j+3]=g.y-e.y,d=g}f.DisplayObjectContainer.prototype.updateTransform.call(this)}},f.Rope.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.width=b,this.height=c,this.tileScale=new f.Point(1,1),this.tilePosition=new f.Point(0,0),this.renderable=!0,this.blendMode=f.blendModes.NORMAL},f.TilingSprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.TilingSprite.prototype.constructor=f.TilingSprite,f.TilingSprite.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Spine=function(a){if(f.DisplayObjectContainer.call(this),this.spineData=f.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new n.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new n.AnimationStateData(this.spineData),this.state=new n.AnimationState(this.stateData),this.slotContainers=[];for(var b=0,c=this.skeleton.drawOrder.length;c>b;b++){var d=this.skeleton.drawOrder[b],e=d.attachment,g=new f.DisplayObjectContainer;if(this.slotContainers.push(g),this.addChild(g),e instanceof n.RegionAttachment){var h=e.rendererObject.name,i=this.createSprite(d,e.rendererObject);d.currentSprite=i,d.currentSpriteName=h,g.addChild(i)}}},f.Spine.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Spine.prototype.constructor=f.Spine,f.Spine.prototype.updateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var b=this.skeleton.drawOrder,c=0,d=b.length;d>c;c++){var e=b[c],g=e.attachment,h=this.slotContainers[c];if(g instanceof n.RegionAttachment){if(g.rendererObject&&(!e.currentSpriteName||e.currentSpriteName!=g.name)){var i=g.rendererObject.name;if(void 0!==e.currentSprite&&(e.currentSprite.visible=!1),e.sprites=e.sprites||{},void 0!==e.sprites[i])e.sprites[i].visible=!0;else{var j=this.createSprite(e,g.rendererObject);h.addChild(j)}e.currentSprite=e.sprites[i],e.currentSpriteName=i}h.visible=!0;var k=e.bone;h.position.x=k.worldX+g.x*k.m00+g.y*k.m01,h.position.y=k.worldY+g.x*k.m10+g.y*k.m11,h.scale.x=k.worldScaleX,h.scale.y=k.worldScaleY,h.rotation=-(e.bone.worldRotation*Math.PI/180)}else h.visible=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.Spine.prototype.createSprite=function(a,b){var c=f.TextureCache[b.name]?b.name:b.name+".png",d=new f.Sprite(f.Texture.fromFrame(c));return d.scale=b.scale,d.rotation=b.rotation,d.anchor.x=d.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[b.name]=d,d};var n={};n.BoneData=function(a,b){this.name=a,this.parent=b},n.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1},n.SlotData=function(a,b){this.name=a,this.boneData=b},n.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null},n.Bone=function(a,b){this.data=a,this.parent=b,this.setToSetupPose()},n.Bone.yDown=!1,n.Bone.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,updateWorldTransform:function(a,b){var c=this.parent;null!=c?(this.worldX=this.x*c.m00+this.y*c.m01+c.worldX,this.worldY=this.x*c.m10+this.y*c.m11+c.worldY,this.worldScaleX=c.worldScaleX*this.scaleX,this.worldScaleY=c.worldScaleY*this.scaleY,this.worldRotation=c.worldRotation+this.rotation):(this.worldX=this.x,this.worldY=this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotation);var d=this.worldRotation*Math.PI/180,e=Math.cos(d),f=Math.sin(d);this.m00=e*this.worldScaleX,this.m10=f*this.worldScaleX,this.m01=-f*this.worldScaleY,this.m11=e*this.worldScaleY,a&&(this.m00=-this.m00,this.m01=-this.m01),b&&(this.m10=-this.m10,this.m11=-this.m11),n.Bone.yDown&&(this.m10=-this.m10,this.m11=-this.m11)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY}},n.Slot=function(a,b,c){this.data=a,this.skeleton=b,this.bone=c,this.setToSetupPose()},n.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,setAttachment:function(a){this.attachment=a,this._attachmentTime=this.skeleton.time},setAttachmentTime:function(a){this._attachmentTime=this.skeleton.time-a},getAttachmentTime:function(){return this.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},n.Skin=function(a){this.name=a,this.attachments={}},n.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},n.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},n.Animation.prototype={apply:function(a,b,c){c&&0!=this.duration&&(b%=this.duration);for(var d=this.timelines,e=0,f=d.length;f>e;e++)d[e].apply(a,b,1)},mix:function(a,b,c,d){c&&0!=this.duration&&(b%=this.duration);for(var e=this.timelines,f=0,g=e.length;g>f;f++)e[f].apply(a,b,d)}},n.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(0==e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},n.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},n.Curves=function(a){this.curves=[],this.curves.length=6*(a-1)},n.Curves.prototype={setLinear:function(a){this.curves[6*a]=0},setStepped:function(a){this.curves[6*a]=-1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=6*a,r=this.curves;r[q]=b*i+m*j+o*h,r[q+1]=c*i+n*j+p*h,r[q+2]=m*k+o*l,r[q+3]=n*k+p*l,r[q+4]=o*l,r[q+5]=p*l},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=6*a,d=this.curves,e=d[c];if(!e)return b;if(-1==e)return 0;for(var f=d[c+1],g=d[c+2],h=d[c+3],i=d[c+4],j=d[c+5],k=e,l=f,m=8;;){if(k>=b){var n=k-e,o=l-f;return o+(l-o)*(b-n)/(k-n)}if(0==m)break;m--,e+=g,f+=h,g+=i,h+=j,k+=e,l+=f}return l+(1-l)*(b-k)/(1-k)}},n.RotateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=2*a},n.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-2]){for(var f=e.data.rotation+d[d.length-1]-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;return e.rotation+=f*c,void 0}var g=n.binarySearch(d,b,2),h=d[g-1],i=d[g],j=1-(b-i)/(d[g-2]-i);j=this.curves.getCurvePercent(g/2-1,j);for(var f=d[g+1]-h;f>180;)f-=360;for(;-180>f;)f+=360;for(f=e.data.rotation+(h+f*j)-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;e.rotation+=f*c}}},n.TranslateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.x+=(e.data.x+d[d.length-2]-e.x)*c,e.y+=(e.data.y+d[d.length-1]-e.y)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.x+=(e.data.x+g+(d[f+1]-g)*j-e.x)*c,e.y+=(e.data.y+h+(d[f+2]-h)*j-e.y)*c}}},n.ScaleTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.scaleX+=(e.data.scaleX-1+d[d.length-2]-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+d[d.length-1]-e.scaleY)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.scaleX+=(e.data.scaleX-1+g+(d[f+1]-g)*j-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+h+(d[f+2]-h)*j-e.scaleY)*c}}},n.ColorTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=5*a},n.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(c,d){c*=5,this.frames[c]=d,this.frames[c+1]=r,this.frames[c+2]=g,this.frames[c+3]=b,this.frames[c+4]=a},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-5]){var f=d.length-1;return e.r=d[f-3],e.g=d[f-2],e.b=d[f-1],e.a=d[f],void 0}var g=n.binarySearch(d,b,5),h=d[g-4],i=d[g-3],j=d[g-2],k=d[g-1],l=d[g],m=1-(b-l)/(d[g-5]-l);m=this.curves.getCurvePercent(g/5-1,m);var o=h+(d[g+1]-h)*m,p=i+(d[g+2]-i)*m,q=j+(d[g+3]-j)*m,r=k+(d[g+4]-k)*m;1>c?(e.r+=(o-e.r)*c,e.g+=(p-e.g)*c,e.b+=(q-e.b)*c,e.a+=(r-e.a)*c):(e.r=o,e.g=p,e.b=q,e.a=r)}}},n.AttachmentTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},n.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b){var c=this.frames;if(!(b=c[c.length-1]?c.length-1:n.binarySearch(c,b,1)-1;var e=this.attachmentNames[d];a.slots[this.slotIndex].setAttachment(e?a.getAttachmentBySlotIndex(this.slotIndex,e):null)}}},n.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.animations=[]},n.SkeletonData.prototype={defaultSkin:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},n.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,c=a.bones.length;c>b;b++){var d=a.bones[b],e=d.parent?this.bones[a.bones.indexOf(d.parent)]:null;this.bones.push(new n.Bone(d,e))}this.slots=[],this.drawOrder=[];for(var b=0,c=a.slots.length;c>b;b++){var f=a.slots[b],g=this.bones[a.bones.indexOf(f.boneData)],h=new n.Slot(f,this,g);this.slots.push(h),this.drawOrder.push(h)}},n.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateWorldTransform:function(){for(var a=this.flipX,b=this.flipY,c=this.bones,d=0,e=c.length;e>d;d++)c[d].updateWorldTransform(a,b)},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose()},setSlotsToSetupPose:function(){for(var a=this.slots,b=0,c=a.length;c>b;b++)a[b].setToSetupPose(b)},getRootBone:function(){return 0==this.bones.length?null:this.bones[0]},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a);if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){this.skin&&a&&a._attachAll(this,this.skin),this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.size;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachment(d,b),null==g))throw"Attachment not found: "+b+", for slot: "+a;return f.setAttachment(g),void 0}}throw"Slot not found: "+a},update:function(a){time+=a}},n.AttachmentType={region:0},n.RegionAttachment=function(){this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},n.RegionAttachment.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,c=-this.width/2*this.scaleX+this.regionOffsetX*a,d=-this.height/2*this.scaleY+this.regionOffsetY*b,e=c+this.regionWidth*a,f=d+this.regionHeight*b,g=this.rotation*Math.PI/180,h=Math.cos(g),i=Math.sin(g),j=c*h+this.x,k=c*i,l=d*h+this.y,m=d*i,n=e*h+this.x,o=e*i,p=f*h+this.y,q=f*i,r=this.offset;r[0]=j-m,r[1]=l+k,r[2]=j-q,r[3]=p+k,r[4]=n-q,r[5]=p+o,r[6]=n-m,r[7]=l+o},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},n.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},n.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=this.animationToMixTime[a.name+":"+b.name];return c?c:this.defaultMix}},n.AnimationState=function(a){this.data=a,this.queue=[]},n.AnimationState.prototype={current:null,previous:null,currentTime:0,previousTime:0,currentLoop:!1,previousLoop:!1,mixTime:0,mixDuration:0,update:function(a){if(this.currentTime+=a,this.previousTime+=a,this.mixTime+=a,this.queue.length>0){var b=this.queue[0];this.currentTime>=b.delay&&(this._setAnimation(b.animation,b.loop),this.queue.shift())}},apply:function(a){if(this.current)if(this.previous){this.previous.apply(a,this.previousTime,this.previousLoop);var b=this.mixTime/this.mixDuration;b>=1&&(b=1,this.previous=null),this.current.mix(a,this.currentTime,this.currentLoop,b)}else this.current.apply(a,this.currentTime,this.currentLoop)},clearAnimation:function(){this.previous=null,this.current=null,this.queue.length=0},_setAnimation:function(a,b){this.previous=null,a&&this.current&&(this.mixDuration=this.data.getMix(this.current,a),this.mixDuration>0&&(this.mixTime=0,this.previous=this.current,this.previousTime=this.currentTime,this.previousLoop=this.currentLoop)),this.current=a,this.currentLoop=b,this.currentTime=0},setAnimationByName:function(a,b){var c=this.data.skeletonData.findAnimation(a);if(!c)throw"Animation not found: "+a;this.setAnimation(c,b)},setAnimation:function(a,b){this.queue.length=0,this._setAnimation(a,b)},addAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;this.addAnimation(d,b,c)},addAnimation:function(a,b,c){var d={};if(d.animation=a,d.loop=b,!c||0>=c){var e=0==this.queue.length?this.current:this.queue[this.queue.length-1].animation;c=null!=e?e.duration-this.data.getMix(e,a)+(c||0):0}d.delay=c,this.queue.push(d)},isComplete:function(){return!this.current||this.currentTime>=this.current.duration}},n.SkeletonJson=function(a){this.attachmentLoader=a},n.SkeletonJson.prototype={scale:1,readSkeletonData:function(a){for(var b=new n.SkeletonData,c=a.bones,d=0,e=c.length;e>d;d++){var f=c[d],g=null;if(f.parent&&(g=b.findBone(f.parent),!g))throw"Parent bone not found: "+f.parent;var h=new n.BoneData(f.name,g);h.length=(f.length||0)*this.scale,h.x=(f.x||0)*this.scale,h.y=(f.y||0)*this.scale,h.rotation=f.rotation||0,h.scaleX=f.scaleX||1,h.scaleY=f.scaleY||1,b.bones.push(h)}for(var i=a.slots,d=0,e=i.length;e>d;d++){var j=i[d],h=b.findBone(j.bone);if(!h)throw"Slot bone not found: "+j.bone; var k=new n.SlotData(j.name,h),l=j.color;l&&(k.r=n.SkeletonJson.toColor(l,0),k.g=n.SkeletonJson.toColor(l,1),k.b=n.SkeletonJson.toColor(l,2),k.a=n.SkeletonJson.toColor(l,3)),k.attachmentName=j.attachment,b.slots.push(k)}var m=a.skins;for(var o in m)if(m.hasOwnProperty(o)){var p=m[o],q=new n.Skin(o);for(var r in p)if(p.hasOwnProperty(r)){var s=b.findSlotIndex(r),t=p[r];for(var u in t)if(t.hasOwnProperty(u)){var v=this.readAttachment(q,u,t[u]);null!=v&&q.addAttachment(s,u,v)}}b.skins.push(q),"default"==q.name&&(b.defaultSkin=q)}var w=a.animations;for(var x in w)w.hasOwnProperty(x)&&this.readAnimation(x,w[x],b);return b},readAttachment:function(a,b,c){b=c.name||b;var d=n.AttachmentType[c.type||"region"];if(d==n.AttachmentType.region){var e=new n.RegionAttachment;return e.x=(c.x||0)*this.scale,e.y=(c.y||0)*this.scale,e.scaleX=c.scaleX||1,e.scaleY=c.scaleY||1,e.rotation=c.rotation||0,e.width=(c.width||32)*this.scale,e.height=(c.height||32)*this.scale,e.updateOffset(),e.rendererObject={},e.rendererObject.name=b,e.rendererObject.scale={},e.rendererObject.scale.x=e.scaleX,e.rendererObject.scale.y=e.scaleY,e.rendererObject.rotation=-e.rotation*Math.PI/180,e}throw"Unknown attachment type: "+d},readAnimation:function(a,b,c){var d=[],e=0,f=b.bones;for(var g in f)if(f.hasOwnProperty(g)){var h=c.findBoneIndex(g);if(-1==h)throw"Bone not found: "+g;var i=f[g];for(var j in i)if(i.hasOwnProperty(j)){var k=i[j];if("rotate"==j){var l=new n.RotateTimeline(k.length);l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m,q.time,q.angle),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[2*l.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var l,r=1;"scale"==j?l=new n.ScaleTimeline(k.length):(l=new n.TranslateTimeline(k.length),r=this.scale),l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;l.setFrame(m,q.time,s,t),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[3*l.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var l=new n.ColorTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=n.SkeletonJson.toColor(y,0),A=n.SkeletonJson.toColor(y,1),B=n.SkeletonJson.toColor(y,2),C=n.SkeletonJson.toColor(y,3);l.setFrame(m,q.time,z,A,B,C),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[5*l.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var l=new n.AttachmentTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m++,q.time,q.name)}d.push(l),e=Math.max(e,l.frames[l.getFrameCount()-1])}}}c.animations.push(new n.Animation(a,d,e))}},n.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},n.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},n.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new n.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new n.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new n.AtlasPage,e.name=f,e.format=n.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=n.Atlas.TextureFilter[d[0]],e.magFilter=n.Atlas.TextureFilter[d[1]];var l=c.readValue();e.uWrap=n.Atlas.TextureWrap.clampToEdge,e.vWrap=n.Atlas.TextureWrap.clampToEdge,"x"==l?e.uWrap=n.Atlas.TextureWrap.repeat:"y"==l?e.vWrap=n.Atlas.TextureWrap.repeat:"xy"==l&&(e.uWrap=e.vWrap=n.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},n.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},n.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},n.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},n.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},n.AtlasPage=function(){},n.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},n.AtlasRegion=function(){},n.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},n.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},n.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},n.AtlasAttachmentLoader=function(a){this.atlas=a},n.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case n.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new n.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},n.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;h Date: Sun, 3 Nov 2013 19:26:40 +0000 Subject: [PATCH 70/96] Fixed Issue #313 --- bin/pixi.dev.js | 2 + bin/pixi.dev.js.map | 2 +- bin/pixi.js | 6 +- .../example 13 - Graphics/indexLineTest.html | 102 +++--------------- src/pixi/renderers/canvas/CanvasGraphics.js | 2 + 5 files changed, 21 insertions(+), 93 deletions(-) diff --git a/bin/pixi.dev.js b/bin/pixi.dev.js index 56b7360..99663d3 100644 --- a/bin/pixi.dev.js +++ b/bin/pixi.dev.js @@ -7609,6 +7609,8 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) var worldAlpha = graphics.worldAlpha; var len = graphics.graphicsData.length; + if(len === 0)return; + if(len > 1) { len = 1; diff --git a/bin/pixi.dev.js.map b/bin/pixi.dev.js.map index 154b544..70dd638 100644 --- a/bin/pixi.dev.js.map +++ b/bin/pixi.dev.js.map @@ -65,6 +65,6 @@ "src/pixi/Outro.js" ], "names": [], - "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sB;AC5jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnhBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpgCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACpgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACn7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACpKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,c", + "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sB;AC5jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnhBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpgCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACpgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACn7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACpKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,c", "sourceRoot": "../" } \ No newline at end of file diff --git a/bin/pixi.js b/bin/pixi.js index 5485500..685c19d 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -11,6 +11,6 @@ */ !function(){function c(){return f.Matrix="undefined"!=typeof Float32Array?Float32Array:Array,f.Matrix}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}var e=this,f=f||{};f.Point=function(a,b){this.x=a||0,this.y=b||0},f.Point.prototype.clone=function(){return new f.Point(this.x,this.y)},f.Point.prototype.constructor=f.Point,f.Rectangle=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Rectangle.prototype.clone=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Rectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},f.Rectangle.prototype.constructor=f.Rectangle,f.Polygon=function(a){if(a instanceof Array||(a=Array.prototype.slice.call(arguments)),"number"==typeof a[0]){for(var b=[],c=0,d=a.length;d>c;c+=2)b.push(new f.Point(a[c],a[c+1]));a=b}this.points=a},f.Polygon.prototype.clone=function(){for(var a=[],b=0;bb!=i>b&&(h-f)*(b-g)/(i-g)+f>a;j&&(c=!c)}return c},f.Polygon.prototype.constructor=f.Polygon,f.Circle=function(a,b,c){this.x=a||0,this.y=b||0,this.radius=c||0},f.Circle.prototype.clone=function(){return new f.Circle(this.x,this.y,this.radius)},f.Circle.prototype.contains=function(a,b){if(this.radius<=0)return!1;var c=this.x-a,d=this.y-b,e=this.radius*this.radius;return c*=c,d*=d,e>=c+d},f.Circle.prototype.constructor=f.Circle,f.Ellipse=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Ellipse.prototype.clone=function(){return new f.Ellipse(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=(a-this.x)/this.width-.5,d=(b-this.y)/this.height-.5;return c*=c,d*=d,.25>c+d},f.Ellipse.getBounds=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.constructor=f.Ellipse,c(),f.mat3={},f.mat3.create=function(){var a=new f.Matrix(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat3.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat4={},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat3.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=b[0],n=b[1],o=b[2],p=b[3],q=b[4],r=b[5],s=b[6],t=b[7],u=b[8];return c[0]=m*d+n*g+o*j,c[1]=m*e+n*h+o*k,c[2]=m*f+n*i+o*l,c[3]=p*d+q*g+r*j,c[4]=p*e+q*h+r*k,c[5]=p*f+q*i+r*l,c[6]=s*d+t*g+u*j,c[7]=s*e+t*h+u*k,c[8]=s*f+t*i+u*l,c},f.mat3.clone=function(a){var b=new f.Matrix(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},f.mat3.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[5];return a[1]=a[3],a[2]=a[6],a[3]=c,a[5]=a[7],a[6]=d,a[7]=e,a}return b[0]=a[0],b[1]=a[3],b[2]=a[6],b[3]=a[1],b[4]=a[4],b[5]=a[7],b[6]=a[2],b[7]=a[5],b[8]=a[8],b},f.mat3.toMat4=function(a,b){return b||(b=f.mat4.create()),b[15]=1,b[14]=0,b[13]=0,b[12]=0,b[11]=0,b[10]=a[8],b[9]=a[7],b[8]=a[6],b[7]=0,b[6]=a[5],b[5]=a[4],b[4]=a[3],b[3]=0,b[2]=a[2],b[1]=a[1],b[0]=a[0],b},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat4.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[3],f=a[6],g=a[7],h=a[11];return a[1]=a[4],a[2]=a[8],a[3]=a[12],a[4]=c,a[6]=a[9],a[7]=a[13],a[8]=d,a[9]=f,a[11]=a[14],a[12]=e,a[13]=g,a[14]=h,a}return b[0]=a[0],b[1]=a[4],b[2]=a[8],b[3]=a[12],b[4]=a[1],b[5]=a[5],b[6]=a[9],b[7]=a[13],b[8]=a[2],b[9]=a[6],b[10]=a[10],b[11]=a[14],b[12]=a[3],b[13]=a[7],b[14]=a[11],b[15]=a[15],b},f.mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=b[0],u=b[1],v=b[2],w=b[3];return c[0]=t*d+u*h+v*l+w*p,c[1]=t*e+u*i+v*m+w*q,c[2]=t*f+u*j+v*n+w*r,c[3]=t*g+u*k+v*o+w*s,t=b[4],u=b[5],v=b[6],w=b[7],c[4]=t*d+u*h+v*l+w*p,c[5]=t*e+u*i+v*m+w*q,c[6]=t*f+u*j+v*n+w*r,c[7]=t*g+u*k+v*o+w*s,t=b[8],u=b[9],v=b[10],w=b[11],c[8]=t*d+u*h+v*l+w*p,c[9]=t*e+u*i+v*m+w*q,c[10]=t*f+u*j+v*n+w*r,c[11]=t*g+u*k+v*o+w*s,t=b[12],u=b[13],v=b[14],w=b[15],c[12]=t*d+u*h+v*l+w*p,c[13]=t*e+u*i+v*m+w*q,c[14]=t*f+u*j+v*n+w*r,c[15]=t*g+u*k+v*o+w*s,c},f.DisplayObject=function(){this.last=this,this.first=this,this.position=new f.Point,this.scale=new f.Point(1,1),this.pivot=new f.Point(0,0),this.rotation=0,this.alpha=1,this.visible=!0,this.hitArea=null,this.buttonMode=!1,this.renderable=!1,this.parent=null,this.stage=null,this.worldAlpha=1,this._interactive=!1,this.worldTransform=f.mat3.create(),this.localTransform=f.mat3.create(),this.color=[],this.dynamic=!0,this._sr=0,this._cr=1,this.filterArea=new f.Rectangle(0,0,1,1)},f.DisplayObject.prototype.constructor=f.DisplayObject,f.DisplayObject.prototype.setInteractive=function(a){this.interactive=a},Object.defineProperty(f.DisplayObject.prototype,"interactive",{get:function(){return this._interactive},set:function(a){this._interactive=a,this.stage&&(this.stage.dirty=!0)}}),Object.defineProperty(f.DisplayObject.prototype,"mask",{get:function(){return this._mask},set:function(a){a?this._mask?(a.start=this._mask.start,a.end=this._mask.end):(this.addFilter(a),a.renderable=!1):(this.removeFilter(this._mask),this._mask.renderable=!0),this._mask=a}}),Object.defineProperty(f.DisplayObject.prototype,"filters",{get:function(){return this._filters},set:function(a){if(a){this._filters&&this.removeFilter(this._filters),this.addFilter(a);for(var b=[],c=0;c=0&&b<=this.children.length))throw new Error(a+" The index "+b+" supplied is out of bounds "+this.children.length);if(void 0!=a.parent&&a.parent.removeChild(a),a.parent=this,this.stage){var c=a;do c.interactive&&(this.stage.dirty=!0),c.stage=this.stage,c=c._iNext;while(c)}var d,e,f=a.first,g=a.last;if(b==this.children.length){e=this.last;for(var h=this,i=this.last;h;)h.last==i&&(h.last=a.last),h=h.parent}else e=0==b?this:this.children[b-1].last;d=e._iNext,d&&(d._iPrev=g,g._iNext=d),f._iPrev=e,e._iNext=f,this.children.splice(b,0,a),this.__renderGroup&&(a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a),this.__renderGroup.addDisplayObjectAndChildren(a))},f.DisplayObjectContainer.prototype.swapChildren=function(){},f.DisplayObjectContainer.prototype.getChildAt=function(a){if(a>=0&&aa;a++)this.children[a].updateTransform()}},f.blendModes={},f.blendModes.NORMAL=0,f.blendModes.SCREEN=1,f.Sprite=function(a){f.DisplayObjectContainer.call(this),this.anchor=new f.Point,this.texture=a,this.blendMode=f.blendModes.NORMAL,this._width=0,this._height=0,a.baseTexture.hasLoaded?this.updateFrame=!0:(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Sprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Sprite.prototype.constructor=f.Sprite,Object.defineProperty(f.Sprite.prototype,"width",{get:function(){return this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(f.Sprite.prototype,"height",{get:function(){return this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),f.Sprite.prototype.setTexture=function(a){this.texture.baseTexture!=a.baseTexture?(this.textureChange=!0,this.texture=a,this.__renderGroup&&this.__renderGroup.updateTexture(this)):this.texture=a,this.updateFrame=!0},f.Sprite.prototype.onTextureUpdate=function(){this._width&&(this.scale.x=this._width/this.texture.frame.width),this._height&&(this.scale.y=this._height/this.texture.frame.height),this.updateFrame=!0},f.Sprite.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache"+this);return new f.Sprite(b)},f.Sprite.fromImage=function(a){var b=f.Texture.fromImage(a);return new f.Sprite(b)},f.MovieClip=function(a){f.Sprite.call(this,a[0]),this.textures=a,this.animationSpeed=1,this.loop=!0,this.onComplete=null,this.currentFrame=0,this.playing=!1},f.MovieClip.prototype=Object.create(f.Sprite.prototype),f.MovieClip.prototype.constructor=f.MovieClip,Object.defineProperty(f.MovieClip.prototype,"totalFrames",{get:function(){return this.textures.length}}),f.MovieClip.prototype.stop=function(){this.playing=!1},f.MovieClip.prototype.play=function(){this.playing=!0},f.MovieClip.prototype.gotoAndStop=function(a){this.playing=!1,this.currentFrame=a;var b=0|this.currentFrame+.5;this.setTexture(this.textures[b%this.textures.length])},f.MovieClip.prototype.gotoAndPlay=function(a){this.currentFrame=a,this.playing=!0},f.MovieClip.prototype.updateTransform=function(){if(f.Sprite.prototype.updateTransform.call(this),this.playing){this.currentFrame+=this.animationSpeed;var a=0|this.currentFrame+.5;this.loop||a=this.textures.length&&(this.gotoAndStop(this.textures.length-1),this.onComplete&&this.onComplete())}},f.FilterBlock=function(){this.visible=!0,this.renderable=!0},f.Text=function(a,b){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),f.Sprite.call(this,f.Texture.fromCanvas(this.canvas)),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.Text.prototype=Object.create(f.Sprite.prototype),f.Text.prototype.constructor=f.Text,f.Text.prototype.setStyle=function(a){a=a||{},a.font=a.font||"bold 20pt Arial",a.fill=a.fill||"black",a.align=a.align||"left",a.stroke=a.stroke||"black",a.strokeThickness=a.strokeThickness||0,a.wordWrap=a.wordWrap||!1,a.wordWrapWidth=a.wordWrapWidth||100,this.style=a,this.dirty=!0},f.Text.prototype.setText=function(a){this.text=a.toString()||" ",this.dirty=!0},f.Text.prototype.updateText=function(){this.context.font=this.style.font;var a=this.text;this.style.wordWrap&&(a=this.wordWrap(this.text));for(var b=a.split(/(?:\r\n|\r|\n)/),c=[],d=0,e=0;ee?f:arguments.callee(a,b,f,d,e):arguments.callee(a,b,c,f,e)},c=function(a,c,d){if(a.measureText(c).width<=d||c.length<1)return c;var e=b(a,c,0,c.length,d);return c.substring(0,e)+"\n"+arguments.callee(a,c.substring(e),d)},d="",e=a.split("\n"),f=0;f=2?parseInt(b[b.length-2],10):f.BitmapText.fonts[this.fontName].size,this.dirty=!0},f.BitmapText.prototype.updateText=function(){for(var a=f.BitmapText.fonts[this.fontName],b=new f.Point,c=null,d=[],e=0,g=[],h=0,i=this.fontSize/a.size,j=0;j=j;j++){var n=0;"right"==this.style.align?n=e-g[j]:"center"==this.style.align&&(n=(e-g[j])/2),m.push(n)}for(j=0;j0;)this.removeChild(this.getChildAt(0));this.updateText(),this.dirty=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.BitmapText.fonts={},f.InteractionManager=function(a){this.stage=a,this.mouse=new f.InteractionData,this.touchs={},this.tempPoint=new f.Point,this.mouseoverEnabled=!0,this.pool=[],this.interactiveItems=[],this.interactionDOMElement=null,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseOut=this.onMouseOut.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.last=0},f.InteractionManager.prototype.constructor=f.InteractionManager,f.InteractionManager.prototype.collectInteractiveSprite=function(a,b){for(var c=a.children,d=c.length,e=d-1;e>=0;e--){var f=c[e];f.interactive?(b.interactiveChildren=!0,this.interactiveItems.push(f),f.children.length>0&&this.collectInteractiveSprite(f,f)):(f.__iParent=null,f.children.length>0&&this.collectInteractiveSprite(f,b))}},f.InteractionManager.prototype.setTarget=function(a){this.target=a,null===this.interactionDOMElement&&this.setTargetDomElement(a.view),document.body.addEventListener("mouseup",this.onMouseUp,!0)},f.InteractionManager.prototype.setTargetDomElement=function(a){null!==this.interactionDOMElement&&(this.interactionDOMElement.style["-ms-content-zooming"]="",this.interactionDOMElement.style["-ms-touch-action"]="",this.interactionDOMElement.removeEventListener("mousemove",this.onMouseMove,!0),this.interactionDOMElement.removeEventListener("mousedown",this.onMouseDown,!0),this.interactionDOMElement.removeEventListener("mouseout",this.onMouseOut,!0),this.interactionDOMElement.removeEventListener("touchstart",this.onTouchStart,!0),this.interactionDOMElement.removeEventListener("touchend",this.onTouchEnd,!0),this.interactionDOMElement.removeEventListener("touchmove",this.onTouchMove,!0)),window.navigator.msPointerEnabled&&(a.style["-ms-content-zooming"]="none",a.style["-ms-touch-action"]="none"),this.interactionDOMElement=a,a.addEventListener("mousemove",this.onMouseMove,!0),a.addEventListener("mousedown",this.onMouseDown,!0),a.addEventListener("mouseout",this.onMouseOut,!0),a.addEventListener("touchstart",this.onTouchStart,!0),a.addEventListener("touchend",this.onTouchEnd,!0),a.addEventListener("touchmove",this.onTouchMove,!0)},f.InteractionManager.prototype.update=function(){if(this.target){var a=Date.now(),b=a-this.last;if(b=30*b/1e3,!(1>b)){if(this.last=a,this.dirty){this.dirty=!1;for(var c=this.interactiveItems.length,d=0;c>d;d++)this.interactiveItems[d].interactiveChildren=!1;this.interactiveItems=[],this.stage.interactive&&this.interactiveItems.push(this.stage),this.collectInteractiveSprite(this.stage,this.stage)}var e=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var d=0;e>d;d++){var f=this.interactiveItems[d];(f.mouseover||f.mouseout||f.buttonMode)&&(f.__hit=this.hitTest(f,this.mouse),this.mouse.target=f,f.__hit?(f.buttonMode&&(this.interactionDOMElement.style.cursor="pointer"),f.__isOver||(f.mouseover&&f.mouseover(this.mouse),f.__isOver=!0)):f.__isOver&&(f.mouseout&&f.mouseout(this.mouse),f.__isOver=!1))}}}},f.InteractionManager.prototype.onMouseMove=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactionDOMElement.getBoundingClientRect();this.mouse.global.x=(a.clientX-b.left)*(this.target.width/b.width),this.mouse.global.y=(a.clientY-b.top)*(this.target.height/b.height);var c=this.interactiveItems.length;this.mouse.global;for(var d=0;c>d;d++){var e=this.interactiveItems[d];e.mousemove&&e.mousemove(this.mouse)}},f.InteractionManager.prototype.onMouseDown=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactiveItems.length;this.mouse.global,this.stage;for(var c=0;b>c;c++){var d=this.interactiveItems[c];if((d.mousedown||d.click)&&(d.__mouseIsDown=!0,d.__hit=this.hitTest(d,this.mouse),d.__hit&&(d.mousedown&&d.mousedown(this.mouse),d.__isDown=!0,!d.interactiveChildren)))break}},f.InteractionManager.prototype.onMouseOut=function(){var a=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var b=0;a>b;b++){var c=this.interactiveItems[b];c.__isOver&&(this.mouse.target=c,c.mouseout&&c.mouseout(this.mouse),c.__isOver=!1)}},f.InteractionManager.prototype.onMouseUp=function(a){this.mouse.originalEvent=a||window.event,this.mouse.global;for(var b=this.interactiveItems.length,c=!1,d=0;b>d;d++){var e=this.interactiveItems[d];(e.mouseup||e.mouseupoutside||e.click)&&(e.__hit=this.hitTest(e,this.mouse),e.__hit&&!c?(e.mouseup&&e.mouseup(this.mouse),e.__isDown&&e.click&&e.click(this.mouse),e.interactiveChildren||(c=!0)):e.__isDown&&e.mouseupoutside&&e.mouseupoutside(this.mouse),e.__isDown=!1)}},f.InteractionManager.prototype.hitTest=function(a,b){var c=b.global;if(a.vcount!==f.visibleCount)return!1;var d=a instanceof f.Sprite,e=a.worldTransform,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=1/(g*k+h*-j),n=k*m*c.x+-h*m*c.y+(l*h-i*k)*m,o=g*m*c.y+-j*m*c.x+(-l*g+i*j)*m;if(b.target=a,a.hitArea&&a.hitArea.contains)return a.hitArea.contains(n,o)?(b.target=a,!0):!1;if(d){var p,q=a.texture.frame.width,r=a.texture.frame.height,s=-q*a.anchor.x;if(n>s&&s+q>n&&(p=-r*a.anchor.y,o>p&&p+r>o))return b.target=a,!0}for(var t=a.children.length,u=0;t>u;u++){var v=a.children[u],w=this.hitTest(v,b);if(w)return b.target=a,!0}return!1},f.InteractionManager.prototype.onTouchMove=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;dd;d++){var h=this.interactiveItems[d];h.touchmove&&h.touchmove(f)}},f.InteractionManager.prototype.onTouchStart=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i];if((j.touchstart||j.tap)&&(j.__hit=this.hitTest(j,g),j.__hit&&(j.touchstart&&j.touchstart(g),j.__isDown=!0,j.__touchData=g,!j.interactiveChildren)))break}}},f.InteractionManager.prototype.onTouchEnd=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i],k=j.__touchData;j.__hit=this.hitTest(j,f),k==f&&(f.originalEvent=a||window.event,(j.touchend||j.tap)&&(j.__hit&&!g?(j.touchend&&j.touchend(f),j.__isDown&&j.tap&&j.tap(f),j.interactiveChildren||(g=!0)):j.__isDown&&j.touchendoutside&&j.touchendoutside(f),j.__isDown=!1),j.__touchData=null)}this.pool.push(f),this.touchs[e.identifier]=null}},f.InteractionData=function(){this.global=new f.Point,this.local=new f.Point,this.target,this.originalEvent},f.InteractionData.prototype.getLocalPosition=function(a){var b=a.worldTransform,c=this.global,d=b[0],e=b[1],g=b[2],h=b[3],i=b[4],j=b[5],k=1/(d*i+e*-h);return new f.Point(i*k*c.x+-e*k*c.y+(j*e-g*i)*k,d*k*c.y+-h*k*c.x+(-j*d+g*h)*k)},f.InteractionData.prototype.constructor=f.InteractionData,f.Stage=function(a){f.DisplayObjectContainer.call(this),this.worldTransform=f.mat3.create(),this.interactive=!0,this.interactionManager=new f.InteractionManager(this),this.dirty=!0,this.__childrenAdded=[],this.__childrenRemoved=[],this.stage=this,this.stage.hitArea=new f.Rectangle(0,0,1e5,1e5),this.setBackgroundColor(a),this.worldVisible=!0},f.Stage.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Stage.prototype.constructor=f.Stage,f.Stage.prototype.setInteractionDelegate=function(a){this.interactionManager.setTargetDomElement(a)},f.Stage.prototype.updateTransform=function(){this.worldAlpha=1,this.vcount=f.visibleCount;for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform();this.dirty&&(this.dirty=!1,this.interactionManager.dirty=!0),this.interactive&&this.interactionManager.update()},f.Stage.prototype.setBackgroundColor=function(a){this.backgroundColor=a||0,this.backgroundColorSplit=d(this.backgroundColor);var b=this.backgroundColor.toString(16);b="000000".substr(0,6-b.length)+b,this.backgroundColorString="#"+b},f.Stage.prototype.getMousePosition=function(){return this.interactionManager.mouse.global};for(var h=0,i=["ms","moz","webkit","o"],j=0;j>>>>>>>>"),console.log("_");var b=0,c=a.first;for(console.log(c);c._iNext;)if(b++,c=c._iNext,console.log(c),b>100){console.log("BREAK");break}},f.EventTarget=function(){var a={};this.addEventListener=this.on=function(b,c){void 0===a[b]&&(a[b]=[]),-1===a[b].indexOf(c)&&a[b].push(c)},this.dispatchEvent=this.emit=function(b){if(a[b.type]&&a[b.type].length)for(var c=0,d=a[b.type].length;d>c;c++)a[b.type][c](b)},this.removeEventListener=this.off=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)}},f.autoDetectRenderer=function(a,b,c,d,e){a||(a=800),b||(b=600);var g=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}();if(g){var h=-1!=navigator.userAgent.toLowerCase().indexOf("msie");g=!h}return g?new f.WebGLRenderer(a,b,c,d,e):new f.CanvasRenderer(a,b,c,d)},f.PolyK={},f.PolyK.Triangulate=function(a){var b=!0,c=a.length>>1;if(3>c)return[];for(var d=[],e=[],g=0;c>g;g++)e.push(g);for(var g=0,h=c;h>3;){var i=e[(g+0)%h],j=e[(g+1)%h],k=e[(g+2)%h],l=a[2*i],m=a[2*i+1],n=a[2*j],o=a[2*j+1],p=a[2*k],q=a[2*k+1],r=!1;if(f.PolyK._convex(l,m,n,o,p,q,b)){r=!0;for(var s=0;h>s;s++){var t=e[s];if(t!=i&&t!=j&&t!=k&&f.PolyK._PointInTriangle(a[2*t],a[2*t+1],l,m,n,o,p,q)){r=!1;break}}}if(r)d.push(i,j,k),e.splice((g+1)%h,1),h--,g=0;else if(g++>3*h){if(!b)return console.log("PIXI Warning: shape too complex to fill"),[];var d=[];e=[];for(var g=0;c>g;g++)e.push(g);g=0,h=c,b=!1}}return d.push(e[0],e[1],e[2]),d},f.PolyK._PointInTriangle=function(a,b,c,d,e,f,g,h){var i=g-c,j=h-d,k=e-c,l=f-d,m=a-c,n=b-d,o=i*i+j*j,p=i*k+j*l,q=i*m+j*n,r=k*k+l*l,s=k*m+l*n,t=1/(o*r-p*p),u=(r*q-p*s)*t,v=(o*s-p*q)*t;return u>=0&&v>=0&&1>u+v},f.PolyK._convex=function(a,b,c,d,e,f,g){return(b-d)*(e-c)+(c-a)*(f-d)>=0==g},f.initDefaultShaders=function(){f.primitiveShader=new f.PrimitiveShader,f.primitiveShader.init(),f.stripShader=new f.StripShader,f.stripShader.init(),f.defaultShader=new f.PixiShader,f.defaultShader.init();var a=f.gl,b=f.defaultShader.program;a.useProgram(b),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.primitiveShader.program),a.disableVertexAttribArray(f.defaultShader.aVertexPosition),a.disableVertexAttribArray(f.defaultShader.colorAttribute),a.disableVertexAttribArray(f.defaultShader.aTextureCoord),a.enableVertexAttribArray(f.primitiveShader.aVertexPosition),a.enableVertexAttribArray(f.primitiveShader.colorAttribute)},f.deactivatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program),a.disableVertexAttribArray(f.primitiveShader.aVertexPosition),a.disableVertexAttribArray(f.primitiveShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activateStripShader=function(){var a=f.gl;a.useProgram(f.stripShader.program)},f.deactivateStripShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program)},f.CompileVertexShader=function(a,b){return f._CompileShader(a,b,a.VERTEX_SHADER)},f.CompileFragmentShader=function(a,b){return f._CompileShader(a,b,a.FRAGMENT_SHADER)},f._CompileShader=function(a,b,c){var d=b.join("\n"),e=a.createShader(c);return a.shaderSource(e,d),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)?e:(console.log(a.getShaderInfoLog(e)),null)},f.compileProgram=function(a,b){var c=f.gl,d=f.CompileFragmentShader(c,b),e=f.CompileVertexShader(c,a),g=c.createProgram();return c.attachShader(g,e),c.attachShader(g,d),c.linkProgram(g),c.getProgramParameter(g,c.LINK_STATUS)||console.log("Could not initialise shaders"),g},f.PixiShader=function(){this.program,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;","}"]},f.PixiShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc||f.PixiShader.defaultVertexSrc,this.fragmentSrc),b=f.gl; b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord");for(var c in this.uniforms)this.uniforms[c].uniformLocation=b.getUniformLocation(a,c);this.program=a},f.PixiShader.prototype.syncUniforms=function(){var a=f.gl;for(var b in this.uniforms){var c=this.uniforms[b].type;if("f"==c&&a.uniform1f(this.uniforms[b].uniformLocation,this.uniforms[b].value),"f2"==c)a.uniform2f(this.uniforms[b].uniformLocation,this.uniforms[b].value.x,this.uniforms[b].value.y);else if("f4"==c)a.uniform4fv(this.uniforms[b].uniformLocation,this.uniforms[b].value);else if("mat4"==c)a.uniformMatrix4fv(this.uniforms[b].uniformLocation,!1,this.uniforms[b].value);else if("sampler2D"==c){var d=this.uniforms[b].value;a.activeTexture(a.TEXTURE1),a.bindTexture(a.TEXTURE_2D,d.baseTexture._glTexture),a.uniform1i(this.uniforms[b].uniformLocation,1)}}},f.PixiShader.defaultVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","varying float vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"],f.StripShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying float vColor;","uniform float alpha;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));","gl_FragColor = gl_FragColor * alpha;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","varying vec2 vTextureCoord;","varying vec2 offsetVector;","varying float vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"]},f.StripShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.PrimitiveShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","gl_FragColor = vColor;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec4 aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform float alpha;","varying vec4 vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","vColor = aColor * alpha;","}"]},f.PrimitiveShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.WebGLGraphics=function(){},f.WebGLGraphics.renderGraphics=function(a,b){var c=f.gl;a._webGL||(a._webGL={points:[],indices:[],lastIndex:0,buffer:c.createBuffer(),indexBuffer:c.createBuffer()}),a.dirty&&(a.dirty=!1,a.clearDirty&&(a.clearDirty=!1,a._webGL.lastIndex=0,a._webGL.points=[],a._webGL.indices=[]),f.WebGLGraphics.updateGraphics(a)),f.activatePrimitiveShader();var d=f.mat3.clone(a.worldTransform);f.mat3.transpose(d),c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA),c.uniformMatrix3fv(f.primitiveShader.translationMatrix,!1,d),c.uniform2f(f.primitiveShader.projectionVector,b.x,-b.y),c.uniform2f(f.primitiveShader.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(f.primitiveShader.alpha,a.worldAlpha),c.bindBuffer(c.ARRAY_BUFFER,a._webGL.buffer),c.vertexAttribPointer(f.primitiveShader.aVertexPosition,2,c.FLOAT,!1,24,0),c.vertexAttribPointer(f.primitiveShader.colorAttribute,4,c.FLOAT,!1,24,8),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),c.drawElements(c.TRIANGLE_STRIP,a._webGL.indices.length,c.UNSIGNED_SHORT,0),f.deactivatePrimitiveShader()},f.WebGLGraphics.updateGraphics=function(a){for(var b=a._webGL.lastIndex;b3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){if(a.lineWidth%2)for(var e=0;ee;e++)k=c[2*(e-1)],l=c[2*(e-1)+1],m=c[2*e],n=c[2*e+1],o=c[2*(e+1)],p=c[2*(e+1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,s=-(n-p),t=m-o,E=Math.sqrt(s*s+t*t),s/=E,t/=E,s*=K,t*=K,w=-r+l-(-r+n),x=-q+m-(-q+k),y=(-q+k)*(-r+n)-(-q+m)*(-r+l),z=-t+p-(-t+n),A=-s+m-(-s+o),B=(-s+o)*(-t+n)-(-s+m)*(-t+p),C=w*A-z*x,Math.abs(C)<.1?(C+=10.1,F.push(m-q,n-r,N,O,P,M),F.push(m+q,n+r,N,O,P,M)):(px=(x*B-A*y)/C,py=(z*y-w*B)/C,D=(px-m)*(px-m)+(py-n)+(py-n),D>19600?(u=q-s,v=r-t,E=Math.sqrt(u*u+v*v),u/=E,v/=E,u*=K,v*=K,F.push(m-u,n-v),F.push(N,O,P,M),F.push(m+u,n+v),F.push(N,O,P,M),F.push(m-u,n-v),F.push(N,O,P,M),I++):(F.push(px,py),F.push(N,O,P,M),F.push(m-(px-m),n-(py-n)),F.push(N,O,P,M)));k=c[2*(H-2)],l=c[2*(H-2)+1],m=c[2*(H-1)],n=c[2*(H-1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,F.push(m-q,n-r),F.push(N,O,P,M),F.push(m+q,n+r),F.push(N,O,P,M),G.push(J);for(var e=0;I>e;e++)G.push(J++);G.push(J-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},flip=!1;var l=[],m=0;f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;if(a.open)a.data instanceof Array?this.filterManager.pushFilter(a):(m++,l.push(a),c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.INCR),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP));else if(a.data instanceof Array)this.filterManager.popFilter();else{var d=l.pop(a);d&&(c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.DECR),f.WebGLGraphics.renderGraphics(d.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)),c.disable(c.STENCIL_TEST)}},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(){this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;hs?s:E,E=E>t?t:E,E=E>u?u:E,E=E>v?v:E,F=F>w?w:F,F=F>x?x:F,F=F>y?y:F,F=F>z?z:F,C=s>C?s:C,C=t>C?t:C,C=u>C?u:C,C=v>C?v:C,D=w>D?w:D,D=x>D?x:D,D=y>D?y:D,D=z>D?z:D),l=!1,A=A._iNext}while(A!=B);a.filterArea.x=E,a.filterArea.y=F,a.filterArea.width=C-E,a.filterArea.height=D-F},f.FilterTexture=function(a,b){var c=f.gl;this.frameBuffer=c.createFramebuffer(),this.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,this.texture),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.bindFramebuffer(c.FRAMEBUFFER,this.framebuffer),c.bindFramebuffer(c.FRAMEBUFFER,this.frameBuffer),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,this.texture,0),this.resize(a,b)},f.FilterTexture.prototype.resize=function(a,b){this.width=a,this.height=b;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a,b,0,c.RGBA,c.UNSIGNED_BYTE,null)},f.CanvasRenderer=function(a,b,c,d){this.transparent=d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.context=this.view.getContext("2d"),this.refresh=!0,this.view.width=this.width,this.view.height=this.height,this.count=0},f.CanvasRenderer.prototype.constructor=f.CanvasRenderer,f.CanvasRenderer.prototype.render=function(a){f.texturesToUpdate=[],f.texturesToDestroy=[],f.visibleCount++,a.updateTransform(),this.view.style.backgroundColor==a.backgroundColorString||this.transparent||(this.view.style.backgroundColor=a.backgroundColorString),this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.width,this.height),this.renderDisplayObject(a),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0&&(f.Texture.frameUpdates=[])},f.CanvasRenderer.prototype.resize=function(a,b){this.width=a,this.height=b,this.view.width=a,this.view.height=b},f.CanvasRenderer.prototype.renderDisplayObject=function(a){var b,c=this.context;c.globalCompositeOperation="source-over";var d=a.last._iNext;a=a.first;do if(b=a.worldTransform,a.visible)if(a.renderable){if(a instanceof f.Sprite){var e=a.texture.frame;e&&e.width&&e.height&&(c.globalAlpha=a.worldAlpha,c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),c.drawImage(a.texture.baseTexture.source,e.x,e.y,e.width,e.height,a.anchor.x*-e.width,a.anchor.y*-e.height,e.width,e.height))}else if(a instanceof f.Strip)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderStrip(a);else if(a instanceof f.TilingSprite)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderTilingSprite(a);else if(a instanceof f.CustomRenderable)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),a.renderCanvas(this);else if(a instanceof f.Graphics)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),f.CanvasGraphics.renderGraphics(a,c);else if(a instanceof f.FilterBlock&&a.data instanceof f.Graphics){var g=a.data;if(a.open){c.save();var h=g.alpha,i=g.worldTransform;c.setTransform(i[0],i[3],i[1],i[4],i[2],i[5]),g.worldAlpha=.5,c.worldAlpha=0,f.CanvasGraphics.renderGraphicsMask(g,c),c.clip(),g.worldAlpha=h}else c.restore()}a=a._iNext}else a=a._iNext;else a=a.last._iNext;while(a!=d)},f.CanvasRenderer.prototype.renderStripFlat=function(a){var b=this.context,c=a.verticies;a.uvs;var d=c.length/2;this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},f.CanvasRenderer.prototype.renderTilingSprite=function(a){var b=this.context;b.globalAlpha=a.worldAlpha,a.__tilePattern||(a.__tilePattern=b.createPattern(a.texture.baseTexture.source,"repeat")),b.beginPath();var c=a.tilePosition,d=a.tileScale;b.scale(d.x,d.y),b.translate(c.x,c.y),b.fillStyle=a.__tilePattern,b.fillRect(-c.x,-c.y,a.width/d.x,a.height/d.y),b.scale(1/d.x,1/d.y),b.translate(-c.x,-c.y),b.closePath()},f.CanvasRenderer.prototype.renderStrip=function(a){var b=this.context,c=a.verticies,d=a.uvs,e=c.length/2;this.count++;for(var f=1;e-2>f;f++){var g=2*f,h=c[g],i=c[g+2],j=c[g+4],k=c[g+1],l=c[g+3],m=c[g+5],n=d[g]*a.texture.width,o=d[g+2]*a.texture.width,p=d[g+4]*a.texture.width,q=d[g+1]*a.texture.height,r=d[g+3]*a.texture.height,s=d[g+5]*a.texture.height;b.save(),b.beginPath(),b.moveTo(h,k),b.lineTo(i,l),b.lineTo(j,m),b.closePath(),b.clip();var t=n*r+q*p+o*s-r*p-q*o-n*s,u=h*r+q*j+i*s-r*j-q*i-h*s,v=n*i+h*p+o*j-i*p-h*o-n*j,w=n*r*j+q*i*p+h*o*s-h*r*p-q*o*j-n*i*s,x=k*r+q*m+l*s-r*m-q*l-k*s,y=n*l+k*p+o*m-l*p-k*o-n*m,z=n*r*m+q*l*p+k*o*s-k*r*p-q*o*m-n*l*s;b.transform(u/t,x/t,v/t,y/t,w/t,z/t),b.drawImage(a.texture.baseTexture.source,0,0),b.restore()}},f.CanvasGraphics=function(){},f.CanvasGraphics.renderGraphics=function(a,b){for(var c=a.worldAlpha,d=0;d1&&(c=1,console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var d=0;1>d;d++){var e=a.graphicsData[d],g=e.points;if(e.type==f.Graphics.POLY){b.beginPath(),b.moveTo(g[0],g[1]);for(var h=1;hb?b:d,e=b+m>e?b+m:e,g=g>c?b:g,h=c+n>h?c+n:h}else if(k===f.Graphics.CIRC||k===f.Graphics.ELIP){b=a.x,c=a.y;var o=a.radius+l/2;d=d>b-o?b-o:d,e=b+o>e?b+o:e,g=g>c-o?c-o:g,h=c+o>h?c+o:h}else for(var p=0;pb-l?b-l:d,e=b+l>e?b+l:e,g=g>c-l?c-l:g,h=c+l>h?c+l:h}this.bounds=new f.Rectangle(d,g,e-d,h-g)}},f.Graphics.POLY=0,f.Graphics.RECT=1,f.Graphics.CIRC=2,f.Graphics.ELIP=3,f.Strip=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.blendMode=f.blendModes.NORMAL;try{this.uvs=new Float32Array([0,1,1,1,1,0,0,1]),this.verticies=new Float32Array([0,0,0,0,0,0,0,0,0]),this.colors=new Float32Array([1,1,1,1]),this.indices=new Uint16Array([0,1,2,3])}catch(d){this.uvs=[0,1,1,1,1,0,0,1],this.verticies=[0,0,0,0,0,0,0,0,0],this.colors=[1,1,1,1],this.indices=[0,1,2,3]}this.width=b,this.height=c,a.baseTexture.hasLoaded?(this.width=this.texture.frame.width,this.height=this.texture.frame.height,this.updateFrame=!0):(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Strip.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Strip.prototype.constructor=f.Strip,f.Strip.prototype.setTexture=function(a){this.texture=a,this.width=a.frame.width,this.height=a.frame.height,this.updateFrame=!0},f.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Rope=function(a,b){f.Strip.call(this,a),this.points=b;try{this.verticies=new Float32Array(4*b.length),this.uvs=new Float32Array(4*b.length),this.colors=new Float32Array(2*b.length),this.indices=new Uint16Array(2*b.length)}catch(c){this.verticies=verticies,this.uvs=uvs,this.colors=colors,this.indices=indices}this.refresh()},f.Rope.prototype=Object.create(f.Strip.prototype),f.Rope.prototype.constructor=f.Rope,f.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=this.indices,d=this.colors,e=a[0],f=a[0];this.count-=.2,b[0]=0,b[1]=1,b[2]=0,b[3]=1,d[0]=1,d[1]=1,c[0]=0,c[1]=1;for(var g=a.length,h=1;g>h;h++){var f=a[h],i=4*h,j=h/(g-1);h%2?(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1):(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1),i=2*h,d[i]=1,d[i+1]=1,i=2*h,c[i]=i,c[i+1]=i+1,e=f}}},f.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var b,c=this.verticies,d=a[0],e={x:0,y:0},g=a[0];this.count-=.2,c[0]=g.x+e.x,c[1]=g.y+e.y,c[2]=g.x-e.x,c[3]=g.y-e.y;for(var h=a.length,i=1;h>i;i++){var g=a[i],j=4*i;b=i1&&(k=1);var l=Math.sqrt(e.x*e.x+e.y*e.y),m=this.texture.height/2;e.x/=l,e.y/=l,e.x*=m,e.y*=m,c[j]=g.x+e.x,c[j+1]=g.y+e.y,c[j+2]=g.x-e.x,c[j+3]=g.y-e.y,d=g}f.DisplayObjectContainer.prototype.updateTransform.call(this)}},f.Rope.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.width=b,this.height=c,this.tileScale=new f.Point(1,1),this.tilePosition=new f.Point(0,0),this.renderable=!0,this.blendMode=f.blendModes.NORMAL},f.TilingSprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.TilingSprite.prototype.constructor=f.TilingSprite,f.TilingSprite.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Spine=function(a){if(f.DisplayObjectContainer.call(this),this.spineData=f.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new n.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new n.AnimationStateData(this.spineData),this.state=new n.AnimationState(this.stateData),this.slotContainers=[];for(var b=0,c=this.skeleton.drawOrder.length;c>b;b++){var d=this.skeleton.drawOrder[b],e=d.attachment,g=new f.DisplayObjectContainer;if(this.slotContainers.push(g),this.addChild(g),e instanceof n.RegionAttachment){var h=e.rendererObject.name,i=this.createSprite(d,e.rendererObject);d.currentSprite=i,d.currentSpriteName=h,g.addChild(i)}}},f.Spine.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Spine.prototype.constructor=f.Spine,f.Spine.prototype.updateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var b=this.skeleton.drawOrder,c=0,d=b.length;d>c;c++){var e=b[c],g=e.attachment,h=this.slotContainers[c];if(g instanceof n.RegionAttachment){if(g.rendererObject&&(!e.currentSpriteName||e.currentSpriteName!=g.name)){var i=g.rendererObject.name;if(void 0!==e.currentSprite&&(e.currentSprite.visible=!1),e.sprites=e.sprites||{},void 0!==e.sprites[i])e.sprites[i].visible=!0;else{var j=this.createSprite(e,g.rendererObject);h.addChild(j)}e.currentSprite=e.sprites[i],e.currentSpriteName=i}h.visible=!0;var k=e.bone;h.position.x=k.worldX+g.x*k.m00+g.y*k.m01,h.position.y=k.worldY+g.x*k.m10+g.y*k.m11,h.scale.x=k.worldScaleX,h.scale.y=k.worldScaleY,h.rotation=-(e.bone.worldRotation*Math.PI/180)}else h.visible=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.Spine.prototype.createSprite=function(a,b){var c=f.TextureCache[b.name]?b.name:b.name+".png",d=new f.Sprite(f.Texture.fromFrame(c));return d.scale=b.scale,d.rotation=b.rotation,d.anchor.x=d.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[b.name]=d,d};var n={};n.BoneData=function(a,b){this.name=a,this.parent=b},n.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1},n.SlotData=function(a,b){this.name=a,this.boneData=b},n.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null},n.Bone=function(a,b){this.data=a,this.parent=b,this.setToSetupPose()},n.Bone.yDown=!1,n.Bone.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,updateWorldTransform:function(a,b){var c=this.parent;null!=c?(this.worldX=this.x*c.m00+this.y*c.m01+c.worldX,this.worldY=this.x*c.m10+this.y*c.m11+c.worldY,this.worldScaleX=c.worldScaleX*this.scaleX,this.worldScaleY=c.worldScaleY*this.scaleY,this.worldRotation=c.worldRotation+this.rotation):(this.worldX=this.x,this.worldY=this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotation);var d=this.worldRotation*Math.PI/180,e=Math.cos(d),f=Math.sin(d);this.m00=e*this.worldScaleX,this.m10=f*this.worldScaleX,this.m01=-f*this.worldScaleY,this.m11=e*this.worldScaleY,a&&(this.m00=-this.m00,this.m01=-this.m01),b&&(this.m10=-this.m10,this.m11=-this.m11),n.Bone.yDown&&(this.m10=-this.m10,this.m11=-this.m11)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY}},n.Slot=function(a,b,c){this.data=a,this.skeleton=b,this.bone=c,this.setToSetupPose()},n.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,setAttachment:function(a){this.attachment=a,this._attachmentTime=this.skeleton.time},setAttachmentTime:function(a){this._attachmentTime=this.skeleton.time-a},getAttachmentTime:function(){return this.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},n.Skin=function(a){this.name=a,this.attachments={}},n.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},n.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},n.Animation.prototype={apply:function(a,b,c){c&&0!=this.duration&&(b%=this.duration);for(var d=this.timelines,e=0,f=d.length;f>e;e++)d[e].apply(a,b,1)},mix:function(a,b,c,d){c&&0!=this.duration&&(b%=this.duration);for(var e=this.timelines,f=0,g=e.length;g>f;f++)e[f].apply(a,b,d)}},n.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(0==e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},n.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},n.Curves=function(a){this.curves=[],this.curves.length=6*(a-1)},n.Curves.prototype={setLinear:function(a){this.curves[6*a]=0},setStepped:function(a){this.curves[6*a]=-1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=6*a,r=this.curves;r[q]=b*i+m*j+o*h,r[q+1]=c*i+n*j+p*h,r[q+2]=m*k+o*l,r[q+3]=n*k+p*l,r[q+4]=o*l,r[q+5]=p*l},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=6*a,d=this.curves,e=d[c];if(!e)return b;if(-1==e)return 0;for(var f=d[c+1],g=d[c+2],h=d[c+3],i=d[c+4],j=d[c+5],k=e,l=f,m=8;;){if(k>=b){var n=k-e,o=l-f;return o+(l-o)*(b-n)/(k-n)}if(0==m)break;m--,e+=g,f+=h,g+=i,h+=j,k+=e,l+=f}return l+(1-l)*(b-k)/(1-k)}},n.RotateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=2*a},n.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-2]){for(var f=e.data.rotation+d[d.length-1]-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;return e.rotation+=f*c,void 0}var g=n.binarySearch(d,b,2),h=d[g-1],i=d[g],j=1-(b-i)/(d[g-2]-i);j=this.curves.getCurvePercent(g/2-1,j);for(var f=d[g+1]-h;f>180;)f-=360;for(;-180>f;)f+=360;for(f=e.data.rotation+(h+f*j)-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;e.rotation+=f*c}}},n.TranslateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.x+=(e.data.x+d[d.length-2]-e.x)*c,e.y+=(e.data.y+d[d.length-1]-e.y)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.x+=(e.data.x+g+(d[f+1]-g)*j-e.x)*c,e.y+=(e.data.y+h+(d[f+2]-h)*j-e.y)*c}}},n.ScaleTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.scaleX+=(e.data.scaleX-1+d[d.length-2]-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+d[d.length-1]-e.scaleY)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.scaleX+=(e.data.scaleX-1+g+(d[f+1]-g)*j-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+h+(d[f+2]-h)*j-e.scaleY)*c}}},n.ColorTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=5*a},n.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(c,d){c*=5,this.frames[c]=d,this.frames[c+1]=r,this.frames[c+2]=g,this.frames[c+3]=b,this.frames[c+4]=a},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-5]){var f=d.length-1;return e.r=d[f-3],e.g=d[f-2],e.b=d[f-1],e.a=d[f],void 0}var g=n.binarySearch(d,b,5),h=d[g-4],i=d[g-3],j=d[g-2],k=d[g-1],l=d[g],m=1-(b-l)/(d[g-5]-l);m=this.curves.getCurvePercent(g/5-1,m);var o=h+(d[g+1]-h)*m,p=i+(d[g+2]-i)*m,q=j+(d[g+3]-j)*m,r=k+(d[g+4]-k)*m;1>c?(e.r+=(o-e.r)*c,e.g+=(p-e.g)*c,e.b+=(q-e.b)*c,e.a+=(r-e.a)*c):(e.r=o,e.g=p,e.b=q,e.a=r)}}},n.AttachmentTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},n.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b){var c=this.frames;if(!(b=c[c.length-1]?c.length-1:n.binarySearch(c,b,1)-1;var e=this.attachmentNames[d];a.slots[this.slotIndex].setAttachment(e?a.getAttachmentBySlotIndex(this.slotIndex,e):null)}}},n.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.animations=[]},n.SkeletonData.prototype={defaultSkin:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},n.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,c=a.bones.length;c>b;b++){var d=a.bones[b],e=d.parent?this.bones[a.bones.indexOf(d.parent)]:null;this.bones.push(new n.Bone(d,e))}this.slots=[],this.drawOrder=[];for(var b=0,c=a.slots.length;c>b;b++){var f=a.slots[b],g=this.bones[a.bones.indexOf(f.boneData)],h=new n.Slot(f,this,g);this.slots.push(h),this.drawOrder.push(h)}},n.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateWorldTransform:function(){for(var a=this.flipX,b=this.flipY,c=this.bones,d=0,e=c.length;e>d;d++)c[d].updateWorldTransform(a,b)},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose()},setSlotsToSetupPose:function(){for(var a=this.slots,b=0,c=a.length;c>b;b++)a[b].setToSetupPose(b)},getRootBone:function(){return 0==this.bones.length?null:this.bones[0]},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a);if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){this.skin&&a&&a._attachAll(this,this.skin),this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.size;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachment(d,b),null==g))throw"Attachment not found: "+b+", for slot: "+a;return f.setAttachment(g),void 0}}throw"Slot not found: "+a},update:function(a){time+=a}},n.AttachmentType={region:0},n.RegionAttachment=function(){this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},n.RegionAttachment.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,c=-this.width/2*this.scaleX+this.regionOffsetX*a,d=-this.height/2*this.scaleY+this.regionOffsetY*b,e=c+this.regionWidth*a,f=d+this.regionHeight*b,g=this.rotation*Math.PI/180,h=Math.cos(g),i=Math.sin(g),j=c*h+this.x,k=c*i,l=d*h+this.y,m=d*i,n=e*h+this.x,o=e*i,p=f*h+this.y,q=f*i,r=this.offset;r[0]=j-m,r[1]=l+k,r[2]=j-q,r[3]=p+k,r[4]=n-q,r[5]=p+o,r[6]=n-m,r[7]=l+o},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},n.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},n.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=this.animationToMixTime[a.name+":"+b.name];return c?c:this.defaultMix}},n.AnimationState=function(a){this.data=a,this.queue=[]},n.AnimationState.prototype={current:null,previous:null,currentTime:0,previousTime:0,currentLoop:!1,previousLoop:!1,mixTime:0,mixDuration:0,update:function(a){if(this.currentTime+=a,this.previousTime+=a,this.mixTime+=a,this.queue.length>0){var b=this.queue[0];this.currentTime>=b.delay&&(this._setAnimation(b.animation,b.loop),this.queue.shift())}},apply:function(a){if(this.current)if(this.previous){this.previous.apply(a,this.previousTime,this.previousLoop);var b=this.mixTime/this.mixDuration;b>=1&&(b=1,this.previous=null),this.current.mix(a,this.currentTime,this.currentLoop,b)}else this.current.apply(a,this.currentTime,this.currentLoop)},clearAnimation:function(){this.previous=null,this.current=null,this.queue.length=0},_setAnimation:function(a,b){this.previous=null,a&&this.current&&(this.mixDuration=this.data.getMix(this.current,a),this.mixDuration>0&&(this.mixTime=0,this.previous=this.current,this.previousTime=this.currentTime,this.previousLoop=this.currentLoop)),this.current=a,this.currentLoop=b,this.currentTime=0},setAnimationByName:function(a,b){var c=this.data.skeletonData.findAnimation(a);if(!c)throw"Animation not found: "+a;this.setAnimation(c,b)},setAnimation:function(a,b){this.queue.length=0,this._setAnimation(a,b)},addAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;this.addAnimation(d,b,c)},addAnimation:function(a,b,c){var d={};if(d.animation=a,d.loop=b,!c||0>=c){var e=0==this.queue.length?this.current:this.queue[this.queue.length-1].animation;c=null!=e?e.duration-this.data.getMix(e,a)+(c||0):0}d.delay=c,this.queue.push(d)},isComplete:function(){return!this.current||this.currentTime>=this.current.duration}},n.SkeletonJson=function(a){this.attachmentLoader=a},n.SkeletonJson.prototype={scale:1,readSkeletonData:function(a){for(var b=new n.SkeletonData,c=a.bones,d=0,e=c.length;e>d;d++){var f=c[d],g=null;if(f.parent&&(g=b.findBone(f.parent),!g))throw"Parent bone not found: "+f.parent;var h=new n.BoneData(f.name,g);h.length=(f.length||0)*this.scale,h.x=(f.x||0)*this.scale,h.y=(f.y||0)*this.scale,h.rotation=f.rotation||0,h.scaleX=f.scaleX||1,h.scaleY=f.scaleY||1,b.bones.push(h)}for(var i=a.slots,d=0,e=i.length;e>d;d++){var j=i[d],h=b.findBone(j.bone);if(!h)throw"Slot bone not found: "+j.bone; -var k=new n.SlotData(j.name,h),l=j.color;l&&(k.r=n.SkeletonJson.toColor(l,0),k.g=n.SkeletonJson.toColor(l,1),k.b=n.SkeletonJson.toColor(l,2),k.a=n.SkeletonJson.toColor(l,3)),k.attachmentName=j.attachment,b.slots.push(k)}var m=a.skins;for(var o in m)if(m.hasOwnProperty(o)){var p=m[o],q=new n.Skin(o);for(var r in p)if(p.hasOwnProperty(r)){var s=b.findSlotIndex(r),t=p[r];for(var u in t)if(t.hasOwnProperty(u)){var v=this.readAttachment(q,u,t[u]);null!=v&&q.addAttachment(s,u,v)}}b.skins.push(q),"default"==q.name&&(b.defaultSkin=q)}var w=a.animations;for(var x in w)w.hasOwnProperty(x)&&this.readAnimation(x,w[x],b);return b},readAttachment:function(a,b,c){b=c.name||b;var d=n.AttachmentType[c.type||"region"];if(d==n.AttachmentType.region){var e=new n.RegionAttachment;return e.x=(c.x||0)*this.scale,e.y=(c.y||0)*this.scale,e.scaleX=c.scaleX||1,e.scaleY=c.scaleY||1,e.rotation=c.rotation||0,e.width=(c.width||32)*this.scale,e.height=(c.height||32)*this.scale,e.updateOffset(),e.rendererObject={},e.rendererObject.name=b,e.rendererObject.scale={},e.rendererObject.scale.x=e.scaleX,e.rendererObject.scale.y=e.scaleY,e.rendererObject.rotation=-e.rotation*Math.PI/180,e}throw"Unknown attachment type: "+d},readAnimation:function(a,b,c){var d=[],e=0,f=b.bones;for(var g in f)if(f.hasOwnProperty(g)){var h=c.findBoneIndex(g);if(-1==h)throw"Bone not found: "+g;var i=f[g];for(var j in i)if(i.hasOwnProperty(j)){var k=i[j];if("rotate"==j){var l=new n.RotateTimeline(k.length);l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m,q.time,q.angle),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[2*l.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var l,r=1;"scale"==j?l=new n.ScaleTimeline(k.length):(l=new n.TranslateTimeline(k.length),r=this.scale),l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;l.setFrame(m,q.time,s,t),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[3*l.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var l=new n.ColorTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=n.SkeletonJson.toColor(y,0),A=n.SkeletonJson.toColor(y,1),B=n.SkeletonJson.toColor(y,2),C=n.SkeletonJson.toColor(y,3);l.setFrame(m,q.time,z,A,B,C),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[5*l.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var l=new n.AttachmentTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m++,q.time,q.name)}d.push(l),e=Math.max(e,l.frames[l.getFrameCount()-1])}}}c.animations.push(new n.Animation(a,d,e))}},n.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},n.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},n.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new n.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new n.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new n.AtlasPage,e.name=f,e.format=n.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=n.Atlas.TextureFilter[d[0]],e.magFilter=n.Atlas.TextureFilter[d[1]];var l=c.readValue();e.uWrap=n.Atlas.TextureWrap.clampToEdge,e.vWrap=n.Atlas.TextureWrap.clampToEdge,"x"==l?e.uWrap=n.Atlas.TextureWrap.repeat:"y"==l?e.vWrap=n.Atlas.TextureWrap.repeat:"xy"==l&&(e.uWrap=e.vWrap=n.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},n.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},n.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},n.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},n.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},n.AtlasPage=function(){},n.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},n.AtlasRegion=function(){},n.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},n.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},n.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},n.AtlasAttachmentLoader=function(a){this.atlas=a},n.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case n.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new n.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},n.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;hs?s:E,E=E>t?t:E,E=E>u?u:E,E=E>v?v:E,F=F>w?w:F,F=F>x?x:F,F=F>y?y:F,F=F>z?z:F,C=s>C?s:C,C=t>C?t:C,C=u>C?u:C,C=v>C?v:C,D=w>D?w:D,D=x>D?x:D,D=y>D?y:D,D=z>D?z:D),l=!1,A=A._iNext}while(A!=B);a.filterArea.x=E,a.filterArea.y=F,a.filterArea.width=C-E,a.filterArea.height=D-F},f.FilterTexture=function(a,b){var c=f.gl;this.frameBuffer=c.createFramebuffer(),this.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,this.texture),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.bindFramebuffer(c.FRAMEBUFFER,this.framebuffer),c.bindFramebuffer(c.FRAMEBUFFER,this.frameBuffer),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,this.texture,0),this.resize(a,b)},f.FilterTexture.prototype.resize=function(a,b){this.width=a,this.height=b;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a,b,0,c.RGBA,c.UNSIGNED_BYTE,null)},f.CanvasRenderer=function(a,b,c,d){this.transparent=d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.context=this.view.getContext("2d"),this.refresh=!0,this.view.width=this.width,this.view.height=this.height,this.count=0},f.CanvasRenderer.prototype.constructor=f.CanvasRenderer,f.CanvasRenderer.prototype.render=function(a){f.texturesToUpdate=[],f.texturesToDestroy=[],f.visibleCount++,a.updateTransform(),this.view.style.backgroundColor==a.backgroundColorString||this.transparent||(this.view.style.backgroundColor=a.backgroundColorString),this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.width,this.height),this.renderDisplayObject(a),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0&&(f.Texture.frameUpdates=[])},f.CanvasRenderer.prototype.resize=function(a,b){this.width=a,this.height=b,this.view.width=a,this.view.height=b},f.CanvasRenderer.prototype.renderDisplayObject=function(a){var b,c=this.context;c.globalCompositeOperation="source-over";var d=a.last._iNext;a=a.first;do if(b=a.worldTransform,a.visible)if(a.renderable){if(a instanceof f.Sprite){var e=a.texture.frame;e&&e.width&&e.height&&(c.globalAlpha=a.worldAlpha,c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),c.drawImage(a.texture.baseTexture.source,e.x,e.y,e.width,e.height,a.anchor.x*-e.width,a.anchor.y*-e.height,e.width,e.height))}else if(a instanceof f.Strip)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderStrip(a);else if(a instanceof f.TilingSprite)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderTilingSprite(a);else if(a instanceof f.CustomRenderable)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),a.renderCanvas(this);else if(a instanceof f.Graphics)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),f.CanvasGraphics.renderGraphics(a,c);else if(a instanceof f.FilterBlock&&a.data instanceof f.Graphics){var g=a.data;if(a.open){c.save();var h=g.alpha,i=g.worldTransform;c.setTransform(i[0],i[3],i[1],i[4],i[2],i[5]),g.worldAlpha=.5,c.worldAlpha=0,f.CanvasGraphics.renderGraphicsMask(g,c),c.clip(),g.worldAlpha=h}else c.restore()}a=a._iNext}else a=a._iNext;else a=a.last._iNext;while(a!=d)},f.CanvasRenderer.prototype.renderStripFlat=function(a){var b=this.context,c=a.verticies;a.uvs;var d=c.length/2;this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},f.CanvasRenderer.prototype.renderTilingSprite=function(a){var b=this.context;b.globalAlpha=a.worldAlpha,a.__tilePattern||(a.__tilePattern=b.createPattern(a.texture.baseTexture.source,"repeat")),b.beginPath();var c=a.tilePosition,d=a.tileScale;b.scale(d.x,d.y),b.translate(c.x,c.y),b.fillStyle=a.__tilePattern,b.fillRect(-c.x,-c.y,a.width/d.x,a.height/d.y),b.scale(1/d.x,1/d.y),b.translate(-c.x,-c.y),b.closePath()},f.CanvasRenderer.prototype.renderStrip=function(a){var b=this.context,c=a.verticies,d=a.uvs,e=c.length/2;this.count++;for(var f=1;e-2>f;f++){var g=2*f,h=c[g],i=c[g+2],j=c[g+4],k=c[g+1],l=c[g+3],m=c[g+5],n=d[g]*a.texture.width,o=d[g+2]*a.texture.width,p=d[g+4]*a.texture.width,q=d[g+1]*a.texture.height,r=d[g+3]*a.texture.height,s=d[g+5]*a.texture.height;b.save(),b.beginPath(),b.moveTo(h,k),b.lineTo(i,l),b.lineTo(j,m),b.closePath(),b.clip();var t=n*r+q*p+o*s-r*p-q*o-n*s,u=h*r+q*j+i*s-r*j-q*i-h*s,v=n*i+h*p+o*j-i*p-h*o-n*j,w=n*r*j+q*i*p+h*o*s-h*r*p-q*o*j-n*i*s,x=k*r+q*m+l*s-r*m-q*l-k*s,y=n*l+k*p+o*m-l*p-k*o-n*m,z=n*r*m+q*l*p+k*o*s-k*r*p-q*o*m-n*l*s;b.transform(u/t,x/t,v/t,y/t,w/t,z/t),b.drawImage(a.texture.baseTexture.source,0,0),b.restore()}},f.CanvasGraphics=function(){},f.CanvasGraphics.renderGraphics=function(a,b){for(var c=a.worldAlpha,d=0;d1&&(c=1,console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var d=0;1>d;d++){var e=a.graphicsData[d],g=e.points;if(e.type==f.Graphics.POLY){b.beginPath(),b.moveTo(g[0],g[1]);for(var h=1;hb?b:d,e=b+m>e?b+m:e,g=g>c?b:g,h=c+n>h?c+n:h}else if(k===f.Graphics.CIRC||k===f.Graphics.ELIP){b=a.x,c=a.y;var o=a.radius+l/2;d=d>b-o?b-o:d,e=b+o>e?b+o:e,g=g>c-o?c-o:g,h=c+o>h?c+o:h}else for(var p=0;pb-l?b-l:d,e=b+l>e?b+l:e,g=g>c-l?c-l:g,h=c+l>h?c+l:h}this.bounds=new f.Rectangle(d,g,e-d,h-g)}},f.Graphics.POLY=0,f.Graphics.RECT=1,f.Graphics.CIRC=2,f.Graphics.ELIP=3,f.Strip=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.blendMode=f.blendModes.NORMAL;try{this.uvs=new Float32Array([0,1,1,1,1,0,0,1]),this.verticies=new Float32Array([0,0,0,0,0,0,0,0,0]),this.colors=new Float32Array([1,1,1,1]),this.indices=new Uint16Array([0,1,2,3])}catch(d){this.uvs=[0,1,1,1,1,0,0,1],this.verticies=[0,0,0,0,0,0,0,0,0],this.colors=[1,1,1,1],this.indices=[0,1,2,3]}this.width=b,this.height=c,a.baseTexture.hasLoaded?(this.width=this.texture.frame.width,this.height=this.texture.frame.height,this.updateFrame=!0):(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Strip.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Strip.prototype.constructor=f.Strip,f.Strip.prototype.setTexture=function(a){this.texture=a,this.width=a.frame.width,this.height=a.frame.height,this.updateFrame=!0},f.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Rope=function(a,b){f.Strip.call(this,a),this.points=b;try{this.verticies=new Float32Array(4*b.length),this.uvs=new Float32Array(4*b.length),this.colors=new Float32Array(2*b.length),this.indices=new Uint16Array(2*b.length)}catch(c){this.verticies=verticies,this.uvs=uvs,this.colors=colors,this.indices=indices}this.refresh()},f.Rope.prototype=Object.create(f.Strip.prototype),f.Rope.prototype.constructor=f.Rope,f.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=this.indices,d=this.colors,e=a[0],f=a[0];this.count-=.2,b[0]=0,b[1]=1,b[2]=0,b[3]=1,d[0]=1,d[1]=1,c[0]=0,c[1]=1;for(var g=a.length,h=1;g>h;h++){var f=a[h],i=4*h,j=h/(g-1);h%2?(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1):(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1),i=2*h,d[i]=1,d[i+1]=1,i=2*h,c[i]=i,c[i+1]=i+1,e=f}}},f.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var b,c=this.verticies,d=a[0],e={x:0,y:0},g=a[0];this.count-=.2,c[0]=g.x+e.x,c[1]=g.y+e.y,c[2]=g.x-e.x,c[3]=g.y-e.y;for(var h=a.length,i=1;h>i;i++){var g=a[i],j=4*i;b=i1&&(k=1);var l=Math.sqrt(e.x*e.x+e.y*e.y),m=this.texture.height/2;e.x/=l,e.y/=l,e.x*=m,e.y*=m,c[j]=g.x+e.x,c[j+1]=g.y+e.y,c[j+2]=g.x-e.x,c[j+3]=g.y-e.y,d=g}f.DisplayObjectContainer.prototype.updateTransform.call(this)}},f.Rope.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.width=b,this.height=c,this.tileScale=new f.Point(1,1),this.tilePosition=new f.Point(0,0),this.renderable=!0,this.blendMode=f.blendModes.NORMAL},f.TilingSprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.TilingSprite.prototype.constructor=f.TilingSprite,f.TilingSprite.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Spine=function(a){if(f.DisplayObjectContainer.call(this),this.spineData=f.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new n.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new n.AnimationStateData(this.spineData),this.state=new n.AnimationState(this.stateData),this.slotContainers=[];for(var b=0,c=this.skeleton.drawOrder.length;c>b;b++){var d=this.skeleton.drawOrder[b],e=d.attachment,g=new f.DisplayObjectContainer;if(this.slotContainers.push(g),this.addChild(g),e instanceof n.RegionAttachment){var h=e.rendererObject.name,i=this.createSprite(d,e.rendererObject);d.currentSprite=i,d.currentSpriteName=h,g.addChild(i)}}},f.Spine.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Spine.prototype.constructor=f.Spine,f.Spine.prototype.updateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var b=this.skeleton.drawOrder,c=0,d=b.length;d>c;c++){var e=b[c],g=e.attachment,h=this.slotContainers[c];if(g instanceof n.RegionAttachment){if(g.rendererObject&&(!e.currentSpriteName||e.currentSpriteName!=g.name)){var i=g.rendererObject.name;if(void 0!==e.currentSprite&&(e.currentSprite.visible=!1),e.sprites=e.sprites||{},void 0!==e.sprites[i])e.sprites[i].visible=!0;else{var j=this.createSprite(e,g.rendererObject);h.addChild(j)}e.currentSprite=e.sprites[i],e.currentSpriteName=i}h.visible=!0;var k=e.bone;h.position.x=k.worldX+g.x*k.m00+g.y*k.m01,h.position.y=k.worldY+g.x*k.m10+g.y*k.m11,h.scale.x=k.worldScaleX,h.scale.y=k.worldScaleY,h.rotation=-(e.bone.worldRotation*Math.PI/180)}else h.visible=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.Spine.prototype.createSprite=function(a,b){var c=f.TextureCache[b.name]?b.name:b.name+".png",d=new f.Sprite(f.Texture.fromFrame(c));return d.scale=b.scale,d.rotation=b.rotation,d.anchor.x=d.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[b.name]=d,d};var n={};n.BoneData=function(a,b){this.name=a,this.parent=b},n.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1},n.SlotData=function(a,b){this.name=a,this.boneData=b},n.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null},n.Bone=function(a,b){this.data=a,this.parent=b,this.setToSetupPose()},n.Bone.yDown=!1,n.Bone.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,updateWorldTransform:function(a,b){var c=this.parent;null!=c?(this.worldX=this.x*c.m00+this.y*c.m01+c.worldX,this.worldY=this.x*c.m10+this.y*c.m11+c.worldY,this.worldScaleX=c.worldScaleX*this.scaleX,this.worldScaleY=c.worldScaleY*this.scaleY,this.worldRotation=c.worldRotation+this.rotation):(this.worldX=this.x,this.worldY=this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotation);var d=this.worldRotation*Math.PI/180,e=Math.cos(d),f=Math.sin(d);this.m00=e*this.worldScaleX,this.m10=f*this.worldScaleX,this.m01=-f*this.worldScaleY,this.m11=e*this.worldScaleY,a&&(this.m00=-this.m00,this.m01=-this.m01),b&&(this.m10=-this.m10,this.m11=-this.m11),n.Bone.yDown&&(this.m10=-this.m10,this.m11=-this.m11)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY}},n.Slot=function(a,b,c){this.data=a,this.skeleton=b,this.bone=c,this.setToSetupPose()},n.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,setAttachment:function(a){this.attachment=a,this._attachmentTime=this.skeleton.time},setAttachmentTime:function(a){this._attachmentTime=this.skeleton.time-a},getAttachmentTime:function(){return this.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},n.Skin=function(a){this.name=a,this.attachments={}},n.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},n.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},n.Animation.prototype={apply:function(a,b,c){c&&0!=this.duration&&(b%=this.duration);for(var d=this.timelines,e=0,f=d.length;f>e;e++)d[e].apply(a,b,1)},mix:function(a,b,c,d){c&&0!=this.duration&&(b%=this.duration);for(var e=this.timelines,f=0,g=e.length;g>f;f++)e[f].apply(a,b,d)}},n.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(0==e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},n.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},n.Curves=function(a){this.curves=[],this.curves.length=6*(a-1)},n.Curves.prototype={setLinear:function(a){this.curves[6*a]=0},setStepped:function(a){this.curves[6*a]=-1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=6*a,r=this.curves;r[q]=b*i+m*j+o*h,r[q+1]=c*i+n*j+p*h,r[q+2]=m*k+o*l,r[q+3]=n*k+p*l,r[q+4]=o*l,r[q+5]=p*l},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=6*a,d=this.curves,e=d[c];if(!e)return b;if(-1==e)return 0;for(var f=d[c+1],g=d[c+2],h=d[c+3],i=d[c+4],j=d[c+5],k=e,l=f,m=8;;){if(k>=b){var n=k-e,o=l-f;return o+(l-o)*(b-n)/(k-n)}if(0==m)break;m--,e+=g,f+=h,g+=i,h+=j,k+=e,l+=f}return l+(1-l)*(b-k)/(1-k)}},n.RotateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=2*a},n.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-2]){for(var f=e.data.rotation+d[d.length-1]-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;return e.rotation+=f*c,void 0}var g=n.binarySearch(d,b,2),h=d[g-1],i=d[g],j=1-(b-i)/(d[g-2]-i);j=this.curves.getCurvePercent(g/2-1,j);for(var f=d[g+1]-h;f>180;)f-=360;for(;-180>f;)f+=360;for(f=e.data.rotation+(h+f*j)-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;e.rotation+=f*c}}},n.TranslateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.x+=(e.data.x+d[d.length-2]-e.x)*c,e.y+=(e.data.y+d[d.length-1]-e.y)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.x+=(e.data.x+g+(d[f+1]-g)*j-e.x)*c,e.y+=(e.data.y+h+(d[f+2]-h)*j-e.y)*c}}},n.ScaleTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.scaleX+=(e.data.scaleX-1+d[d.length-2]-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+d[d.length-1]-e.scaleY)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.scaleX+=(e.data.scaleX-1+g+(d[f+1]-g)*j-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+h+(d[f+2]-h)*j-e.scaleY)*c}}},n.ColorTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=5*a},n.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(c,d){c*=5,this.frames[c]=d,this.frames[c+1]=r,this.frames[c+2]=g,this.frames[c+3]=b,this.frames[c+4]=a},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-5]){var f=d.length-1;return e.r=d[f-3],e.g=d[f-2],e.b=d[f-1],e.a=d[f],void 0}var g=n.binarySearch(d,b,5),h=d[g-4],i=d[g-3],j=d[g-2],k=d[g-1],l=d[g],m=1-(b-l)/(d[g-5]-l);m=this.curves.getCurvePercent(g/5-1,m);var o=h+(d[g+1]-h)*m,p=i+(d[g+2]-i)*m,q=j+(d[g+3]-j)*m,r=k+(d[g+4]-k)*m;1>c?(e.r+=(o-e.r)*c,e.g+=(p-e.g)*c,e.b+=(q-e.b)*c,e.a+=(r-e.a)*c):(e.r=o,e.g=p,e.b=q,e.a=r)}}},n.AttachmentTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},n.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b){var c=this.frames;if(!(b=c[c.length-1]?c.length-1:n.binarySearch(c,b,1)-1;var e=this.attachmentNames[d];a.slots[this.slotIndex].setAttachment(e?a.getAttachmentBySlotIndex(this.slotIndex,e):null)}}},n.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.animations=[]},n.SkeletonData.prototype={defaultSkin:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},n.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,c=a.bones.length;c>b;b++){var d=a.bones[b],e=d.parent?this.bones[a.bones.indexOf(d.parent)]:null;this.bones.push(new n.Bone(d,e))}this.slots=[],this.drawOrder=[];for(var b=0,c=a.slots.length;c>b;b++){var f=a.slots[b],g=this.bones[a.bones.indexOf(f.boneData)],h=new n.Slot(f,this,g);this.slots.push(h),this.drawOrder.push(h)}},n.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateWorldTransform:function(){for(var a=this.flipX,b=this.flipY,c=this.bones,d=0,e=c.length;e>d;d++)c[d].updateWorldTransform(a,b)},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose()},setSlotsToSetupPose:function(){for(var a=this.slots,b=0,c=a.length;c>b;b++)a[b].setToSetupPose(b)},getRootBone:function(){return 0==this.bones.length?null:this.bones[0]},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a);if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){this.skin&&a&&a._attachAll(this,this.skin),this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.size;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachment(d,b),null==g))throw"Attachment not found: "+b+", for slot: "+a;return f.setAttachment(g),void 0}}throw"Slot not found: "+a},update:function(a){time+=a}},n.AttachmentType={region:0},n.RegionAttachment=function(){this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},n.RegionAttachment.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,c=-this.width/2*this.scaleX+this.regionOffsetX*a,d=-this.height/2*this.scaleY+this.regionOffsetY*b,e=c+this.regionWidth*a,f=d+this.regionHeight*b,g=this.rotation*Math.PI/180,h=Math.cos(g),i=Math.sin(g),j=c*h+this.x,k=c*i,l=d*h+this.y,m=d*i,n=e*h+this.x,o=e*i,p=f*h+this.y,q=f*i,r=this.offset;r[0]=j-m,r[1]=l+k,r[2]=j-q,r[3]=p+k,r[4]=n-q,r[5]=p+o,r[6]=n-m,r[7]=l+o},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},n.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},n.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=this.animationToMixTime[a.name+":"+b.name];return c?c:this.defaultMix}},n.AnimationState=function(a){this.data=a,this.queue=[]},n.AnimationState.prototype={current:null,previous:null,currentTime:0,previousTime:0,currentLoop:!1,previousLoop:!1,mixTime:0,mixDuration:0,update:function(a){if(this.currentTime+=a,this.previousTime+=a,this.mixTime+=a,this.queue.length>0){var b=this.queue[0];this.currentTime>=b.delay&&(this._setAnimation(b.animation,b.loop),this.queue.shift())}},apply:function(a){if(this.current)if(this.previous){this.previous.apply(a,this.previousTime,this.previousLoop);var b=this.mixTime/this.mixDuration;b>=1&&(b=1,this.previous=null),this.current.mix(a,this.currentTime,this.currentLoop,b)}else this.current.apply(a,this.currentTime,this.currentLoop)},clearAnimation:function(){this.previous=null,this.current=null,this.queue.length=0},_setAnimation:function(a,b){this.previous=null,a&&this.current&&(this.mixDuration=this.data.getMix(this.current,a),this.mixDuration>0&&(this.mixTime=0,this.previous=this.current,this.previousTime=this.currentTime,this.previousLoop=this.currentLoop)),this.current=a,this.currentLoop=b,this.currentTime=0},setAnimationByName:function(a,b){var c=this.data.skeletonData.findAnimation(a);if(!c)throw"Animation not found: "+a;this.setAnimation(c,b)},setAnimation:function(a,b){this.queue.length=0,this._setAnimation(a,b)},addAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;this.addAnimation(d,b,c)},addAnimation:function(a,b,c){var d={};if(d.animation=a,d.loop=b,!c||0>=c){var e=0==this.queue.length?this.current:this.queue[this.queue.length-1].animation;c=null!=e?e.duration-this.data.getMix(e,a)+(c||0):0}d.delay=c,this.queue.push(d)},isComplete:function(){return!this.current||this.currentTime>=this.current.duration}},n.SkeletonJson=function(a){this.attachmentLoader=a},n.SkeletonJson.prototype={scale:1,readSkeletonData:function(a){for(var b=new n.SkeletonData,c=a.bones,d=0,e=c.length;e>d;d++){var f=c[d],g=null;if(f.parent&&(g=b.findBone(f.parent),!g))throw"Parent bone not found: "+f.parent;var h=new n.BoneData(f.name,g);h.length=(f.length||0)*this.scale,h.x=(f.x||0)*this.scale,h.y=(f.y||0)*this.scale,h.rotation=f.rotation||0,h.scaleX=f.scaleX||1,h.scaleY=f.scaleY||1,b.bones.push(h)}for(var i=a.slots,d=0,e=i.length;e>d;d++){var j=i[d],h=b.findBone(j.bone); +if(!h)throw"Slot bone not found: "+j.bone;var k=new n.SlotData(j.name,h),l=j.color;l&&(k.r=n.SkeletonJson.toColor(l,0),k.g=n.SkeletonJson.toColor(l,1),k.b=n.SkeletonJson.toColor(l,2),k.a=n.SkeletonJson.toColor(l,3)),k.attachmentName=j.attachment,b.slots.push(k)}var m=a.skins;for(var o in m)if(m.hasOwnProperty(o)){var p=m[o],q=new n.Skin(o);for(var r in p)if(p.hasOwnProperty(r)){var s=b.findSlotIndex(r),t=p[r];for(var u in t)if(t.hasOwnProperty(u)){var v=this.readAttachment(q,u,t[u]);null!=v&&q.addAttachment(s,u,v)}}b.skins.push(q),"default"==q.name&&(b.defaultSkin=q)}var w=a.animations;for(var x in w)w.hasOwnProperty(x)&&this.readAnimation(x,w[x],b);return b},readAttachment:function(a,b,c){b=c.name||b;var d=n.AttachmentType[c.type||"region"];if(d==n.AttachmentType.region){var e=new n.RegionAttachment;return e.x=(c.x||0)*this.scale,e.y=(c.y||0)*this.scale,e.scaleX=c.scaleX||1,e.scaleY=c.scaleY||1,e.rotation=c.rotation||0,e.width=(c.width||32)*this.scale,e.height=(c.height||32)*this.scale,e.updateOffset(),e.rendererObject={},e.rendererObject.name=b,e.rendererObject.scale={},e.rendererObject.scale.x=e.scaleX,e.rendererObject.scale.y=e.scaleY,e.rendererObject.rotation=-e.rotation*Math.PI/180,e}throw"Unknown attachment type: "+d},readAnimation:function(a,b,c){var d=[],e=0,f=b.bones;for(var g in f)if(f.hasOwnProperty(g)){var h=c.findBoneIndex(g);if(-1==h)throw"Bone not found: "+g;var i=f[g];for(var j in i)if(i.hasOwnProperty(j)){var k=i[j];if("rotate"==j){var l=new n.RotateTimeline(k.length);l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m,q.time,q.angle),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[2*l.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var l,r=1;"scale"==j?l=new n.ScaleTimeline(k.length):(l=new n.TranslateTimeline(k.length),r=this.scale),l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;l.setFrame(m,q.time,s,t),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[3*l.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var l=new n.ColorTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=n.SkeletonJson.toColor(y,0),A=n.SkeletonJson.toColor(y,1),B=n.SkeletonJson.toColor(y,2),C=n.SkeletonJson.toColor(y,3);l.setFrame(m,q.time,z,A,B,C),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[5*l.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var l=new n.AttachmentTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m++,q.time,q.name)}d.push(l),e=Math.max(e,l.frames[l.getFrameCount()-1])}}}c.animations.push(new n.Animation(a,d,e))}},n.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},n.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},n.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new n.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new n.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new n.AtlasPage,e.name=f,e.format=n.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=n.Atlas.TextureFilter[d[0]],e.magFilter=n.Atlas.TextureFilter[d[1]];var l=c.readValue();e.uWrap=n.Atlas.TextureWrap.clampToEdge,e.vWrap=n.Atlas.TextureWrap.clampToEdge,"x"==l?e.uWrap=n.Atlas.TextureWrap.repeat:"y"==l?e.vWrap=n.Atlas.TextureWrap.repeat:"xy"==l&&(e.uWrap=e.vWrap=n.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},n.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},n.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},n.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},n.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},n.AtlasPage=function(){},n.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},n.AtlasRegion=function(){},n.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},n.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},n.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},n.AtlasAttachmentLoader=function(a){this.atlas=a},n.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case n.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new n.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},n.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;h 1) { len = 1; From 0796f9d53de62aa1b1cb17f325d2492b45bfa6bf Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Mon, 4 Nov 2013 16:49:12 +0000 Subject: [PATCH 71/96] Update README.md --- README.md | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index c62ef86..9f5601a 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,10 @@ any breakthroughs will be posted up there too! - [Flash vs HTML]() - [Bunny Demo]() + +- [Storm Brewing]() + +- [Filters Demo]() - [Render Texture Demo]() @@ -53,7 +57,6 @@ last 2 examples and allowing us to share the source code :) ### Road Map ### * Create a Typescript definition file for Pixi.js -* Implement Filters (currently being worked on by @GoodBoyDigital) * Implement Flash animation to pixi * Update Loader so that it support XHR2 if it is available * Improve the Documentation of the Project @@ -107,15 +110,7 @@ It also copies the non-minified version to the examples. - Spine support - Primitive Drawing - Masking - -### Coming soon ### - -- Filters ( wip : [storm brewing]() ) - - -### Coming later ### - -- Awesome Post processing effects +- Filters ### Usage ### From 2bc359e7d5fd6c8ac31013a6f75b808c4c938cf0 Mon Sep 17 00:00:00 2001 From: Stephen Whitmore Date: Mon, 4 Nov 2013 16:00:26 -0500 Subject: [PATCH 72/96] Fixes #386; adds word wrapping to Pixi.TEXT. This wraps lines of text using a simple greedy algorithm that optimizes for fewest lines given an arbitrary horizontal bound. --- src/pixi/text/Text.js | 66 ++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/src/pixi/text/Text.js b/src/pixi/text/Text.js index 5ca6bbe..df1d12d 100644 --- a/src/pixi/text/Text.js +++ b/src/pixi/text/Text.js @@ -214,7 +214,8 @@ PIXI.Text.prototype.determineFontHeight = function(fontStyle) }; /** - * A Text Object will apply wordwrap + * Applies newlines to a string to have it optimally fit into the horizontal + * bounds set by the Text object's wordWrapWidth property. * * @method wordWrap * @param text {String} @@ -222,48 +223,37 @@ PIXI.Text.prototype.determineFontHeight = function(fontStyle) */ PIXI.Text.prototype.wordWrap = function(text) { - // search good wrap position - var searchWrapPos = function(ctx, text, start, end, wrapWidth) - { - var p = Math.floor((end-start) / 2) + start; - if(p == start) { - return 1; - } - - if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) - { - if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) - { - return p; - } - else - { - return arguments.callee(ctx, text, p, end, wrapWidth); - } - } - else - { - return arguments.callee(ctx, text, start, p, wrapWidth); - } - }; - - var lineWrap = function(ctx, text, wrapWidth) - { - if(ctx.measureText(text).width <= wrapWidth || text.length < 1) - { - return text; - } - var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); - return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); - }; - + // Greedy wrapping algorithm that will wrap words as the line grows longer + // than its horizontal bounds. var result = ""; var lines = text.split("\n"); for (var i = 0; i < lines.length; i++) { - result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; + var spaceLeft = this.style.wordWrapWidth; + var words = lines[i].split(" "); + for (var j = 0; j < words.length; j++) + { + var wordWidth = this.context.measureText(words[j]).width; + var wordWidthWithSpace = wordWidth + this.context.measureText(" ").width; + if(wordWidthWithSpace > spaceLeft) + { + // Skip printing the newline if it's the first word of the line that is + // greater than the word wrap width. + if(j > 0) + { + result += "\n"; + } + result += words[j] + " "; + spaceLeft = this.style.wordWrapWidth - wordWidth; + } + else + { + spaceLeft -= wordWidthWithSpace; + result += words[j] + " "; + } + } + result += "\n"; } - return result; }; From 4204ada63e6848d92f6569e3e0a78d9cfef44ca0 Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Tue, 5 Nov 2013 19:51:39 +0000 Subject: [PATCH 73/96] Added 2 filters fix filter bug Fixed filter bug where filters not wotkring on transparent renderer Added CrossHatchFilter Added RGBSplitFilter Updated Example 15 --- Gruntfile.js | 2 + bin/pixi.dev.js | 205 +++-- bin/pixi.dev.js.map | 4 +- bin/pixi.js | 8 +- .../example 13 - Graphics/indexLineTest.html | 96 ++- examples/example 15 - Filters/indexAll.html | 62 +- pixi.sublime-workspace | 724 ++++++++---------- src/pixi/filters/CrossHatchFilter.js | 69 ++ src/pixi/filters/RGBSplitFilter.js | 50 ++ .../renderers/webgl/WebGLFilterManager.js | 6 +- src/pixi/renderers/webgl/WebGLRenderGroup.js | 8 +- src/pixi/renderers/webgl/WebGLRenderer.js | 4 +- 12 files changed, 747 insertions(+), 491 deletions(-) create mode 100644 src/pixi/filters/CrossHatchFilter.js create mode 100644 src/pixi/filters/RGBSplitFilter.js diff --git a/Gruntfile.js b/Gruntfile.js index 3ec1587..cc634ab 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -71,6 +71,8 @@ module.exports = function(grunt) { '<%= dirs.src %>/filters/TwistFilter.js', '<%= dirs.src %>/filters/ColorStepFilter.js', '<%= dirs.src %>/filters/DotScreenFilter.js', + '<%= dirs.src %>/filters/CrossHatchFilter.js', + '<%= dirs.src %>/filters/RGBSplitFilter.js', '<%= dirs.src %>/Outro.js' ], banner = [ diff --git a/bin/pixi.dev.js b/bin/pixi.dev.js index 99663d3..21b0257 100644 --- a/bin/pixi.dev.js +++ b/bin/pixi.dev.js @@ -2200,7 +2200,8 @@ PIXI.Text.prototype.determineFontHeight = function(fontStyle) }; /** - * A Text Object will apply wordwrap + * Applies newlines to a string to have it optimally fit into the horizontal + * bounds set by the Text object's wordWrapWidth property. * * @method wordWrap * @param text {String} @@ -2208,48 +2209,37 @@ PIXI.Text.prototype.determineFontHeight = function(fontStyle) */ PIXI.Text.prototype.wordWrap = function(text) { - // search good wrap position - var searchWrapPos = function(ctx, text, start, end, wrapWidth) - { - var p = Math.floor((end-start) / 2) + start; - if(p == start) { - return 1; - } - - if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) - { - if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) - { - return p; - } - else - { - return arguments.callee(ctx, text, p, end, wrapWidth); - } - } - else - { - return arguments.callee(ctx, text, start, p, wrapWidth); - } - }; - - var lineWrap = function(ctx, text, wrapWidth) - { - if(ctx.measureText(text).width <= wrapWidth || text.length < 1) - { - return text; - } - var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); - return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); - }; - + // Greedy wrapping algorithm that will wrap words as the line grows longer + // than its horizontal bounds. var result = ""; var lines = text.split("\n"); for (var i = 0; i < lines.length; i++) { - result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; + var spaceLeft = this.style.wordWrapWidth; + var words = lines[i].split(" "); + for (var j = 0; j < words.length; j++) + { + var wordWidth = this.context.measureText(words[j]).width; + var wordWidthWithSpace = wordWidth + this.context.measureText(" ").width; + if(wordWidthWithSpace > spaceLeft) + { + // Skip printing the newline if it's the first word of the line that is + // greater than the word wrap width. + if(j > 0) + { + result += "\n"; + } + result += words[j] + " "; + spaceLeft = this.style.wordWrapWidth - wordWidth; + } + else + { + spaceLeft -= wordWidthWithSpace; + result += words[j] + " "; + } + } + result += "\n"; } - return result; }; @@ -4674,8 +4664,8 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) //PIXI.pushShader(PIXI.defaultShader); - this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); - + this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl, this.transparent); + // this.stageRenderGroup. = this.transparent } // constructor @@ -5534,16 +5524,18 @@ PIXI.WebGLBatch.prototype.render = function(start, end) * @contructor * @param gl {WebGLContext} An instance of the webGL context */ -PIXI.WebGLRenderGroup = function(gl) +PIXI.WebGLRenderGroup = function(gl, transparent) { this.gl = gl; this.root; this.backgroundColor; + this.transparent = transparent == undefined ? true : transparent; + this.batchs = []; this.toRemove = []; - - this.filterManager = new PIXI.WebGLFilterManager(); + console.log(this.transparent) + this.filterManager = new PIXI.WebGLFilterManager(this.transparent); } // constructor @@ -6552,8 +6544,10 @@ PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) */ -PIXI.WebGLFilterManager = function() +PIXI.WebGLFilterManager = function(transparent) { + this.transparent = transparent; + this.filterStack = []; this.texturePool = []; @@ -6744,7 +6738,7 @@ PIXI.WebGLFilterManager.prototype.popFilter = function() // time to render the filters texture to the previous scene if(this.filterStack.length === 0) { - gl.colorMask(true, true, true, this.buffer); + gl.colorMask(true, true, true, this.transparent); } else { @@ -12156,6 +12150,127 @@ Object.defineProperty(PIXI.DotScreenFilter.prototype, 'angle', { this.uniforms.angle.value = value; } }); +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + + +PIXI.CrossHatchFilter = function() +{ + PIXI.AbstractFilter.call( this ); + + this.passes = [this]; + + // set the uniforms + this.uniforms = { + blur: {type: 'f', value: 1/512}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float blur;", + "uniform sampler2D uSampler;", + "void main(void) {", + + + " float lum = length(texture2D(uSampler, vTextureCoord.xy).rgb);", + " ", + " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);", + " ", + " if (lum < 1.00) {", + " if (mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0) {", + " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);", + " }", + " }", + " ", + " if (lum < 0.75) {", + " if (mod(gl_FragCoord.x - gl_FragCoord.y, 10.0) == 0.0) {", + " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);", + " }", + " }", + " ", + " if (lum < 0.50) {", + " if (mod(gl_FragCoord.x + gl_FragCoord.y - 5.0, 10.0) == 0.0) {", + " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);", + " }", + " }", + " ", + " if (lum < 0.3) {", + " if (mod(gl_FragCoord.x - gl_FragCoord.y - 5.0, 10.0) == 0.0) {", + " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);", + " }", + " }", + "}" + ]; +} + +PIXI.CrossHatchFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); +PIXI.CrossHatchFilter.prototype.constructor = PIXI.BlurYFilter; + +Object.defineProperty(PIXI.CrossHatchFilter.prototype, 'blur', { + get: function() { + return this.uniforms.blur.value / (1/7000); + }, + set: function(value) { + //this.padding = value; + this.uniforms.blur.value = (1/7000) * value; + } +}); + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + + +PIXI.RGBSplitFilter = function() +{ + PIXI.AbstractFilter.call( this ); + + this.passes = [this]; + + // set the uniforms + this.uniforms = { + red: {type: 'f2', value: {x:20, y:20}}, + green: {type: 'f2', value: {x:-20, y:20}}, + blue: {type: 'f2', value: {x:20, y:-20}}, + dimensions: {type: 'f4', value:[0,0,0,0]} + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform vec2 red;", + "uniform vec2 green;", + "uniform vec2 blue;", + "uniform vec4 dimensions;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor.r = texture2D(uSampler, vTextureCoord + red/dimensions.xy).r;", + "gl_FragColor.g = texture2D(uSampler, vTextureCoord + green/dimensions.xy).g;", + "gl_FragColor.b = texture2D(uSampler, vTextureCoord + blue/dimensions.xy).b;", + "gl_FragColor.a = texture2D(uSampler, vTextureCoord).a;", + "}" + ]; +} + +PIXI.RGBSplitFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); +PIXI.RGBSplitFilter.prototype.constructor = PIXI.RGBSplitFilter; + +Object.defineProperty(PIXI.RGBSplitFilter.prototype, 'angle', { + get: function() { + return this.uniforms.blur.value / (1/7000); + }, + set: function(value) { + //this.padding = value; + this.uniforms.blur.value = (1/7000) * value; + } +}); + /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ diff --git a/bin/pixi.dev.js.map b/bin/pixi.dev.js.map index 70dd638..21e9b16 100644 --- a/bin/pixi.dev.js.map +++ b/bin/pixi.dev.js.map @@ -62,9 +62,11 @@ "src/pixi/filters/TwistFilter.js", "src/pixi/filters/ColorStepFilter.js", "src/pixi/filters/DotScreenFilter.js", + "src/pixi/filters/CrossHatchFilter.js", + "src/pixi/filters/RGBSplitFilter.js", "src/pixi/Outro.js" ], "names": [], - "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sB;AC5jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnhBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpgCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACpgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACn7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACpKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,c", + "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sB;AC5jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnhBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtgCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACtgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACn7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACpKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,c", "sourceRoot": "../" } \ No newline at end of file diff --git a/bin/pixi.js b/bin/pixi.js index 685c19d..05394a0 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -4,13 +4,13 @@ * Copyright (c) 2012, Mat Groves * http://goodboydigital.com/ * - * Compiled: 2013-11-03 + * Compiled: 2013-11-05 * * Pixi.JS is licensed under the MIT License. * http://www.opensource.org/licenses/mit-license.php */ -!function(){function c(){return f.Matrix="undefined"!=typeof Float32Array?Float32Array:Array,f.Matrix}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}var e=this,f=f||{};f.Point=function(a,b){this.x=a||0,this.y=b||0},f.Point.prototype.clone=function(){return new f.Point(this.x,this.y)},f.Point.prototype.constructor=f.Point,f.Rectangle=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Rectangle.prototype.clone=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Rectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},f.Rectangle.prototype.constructor=f.Rectangle,f.Polygon=function(a){if(a instanceof Array||(a=Array.prototype.slice.call(arguments)),"number"==typeof a[0]){for(var b=[],c=0,d=a.length;d>c;c+=2)b.push(new f.Point(a[c],a[c+1]));a=b}this.points=a},f.Polygon.prototype.clone=function(){for(var a=[],b=0;bb!=i>b&&(h-f)*(b-g)/(i-g)+f>a;j&&(c=!c)}return c},f.Polygon.prototype.constructor=f.Polygon,f.Circle=function(a,b,c){this.x=a||0,this.y=b||0,this.radius=c||0},f.Circle.prototype.clone=function(){return new f.Circle(this.x,this.y,this.radius)},f.Circle.prototype.contains=function(a,b){if(this.radius<=0)return!1;var c=this.x-a,d=this.y-b,e=this.radius*this.radius;return c*=c,d*=d,e>=c+d},f.Circle.prototype.constructor=f.Circle,f.Ellipse=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Ellipse.prototype.clone=function(){return new f.Ellipse(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=(a-this.x)/this.width-.5,d=(b-this.y)/this.height-.5;return c*=c,d*=d,.25>c+d},f.Ellipse.getBounds=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.constructor=f.Ellipse,c(),f.mat3={},f.mat3.create=function(){var a=new f.Matrix(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat3.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat4={},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat3.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=b[0],n=b[1],o=b[2],p=b[3],q=b[4],r=b[5],s=b[6],t=b[7],u=b[8];return c[0]=m*d+n*g+o*j,c[1]=m*e+n*h+o*k,c[2]=m*f+n*i+o*l,c[3]=p*d+q*g+r*j,c[4]=p*e+q*h+r*k,c[5]=p*f+q*i+r*l,c[6]=s*d+t*g+u*j,c[7]=s*e+t*h+u*k,c[8]=s*f+t*i+u*l,c},f.mat3.clone=function(a){var b=new f.Matrix(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},f.mat3.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[5];return a[1]=a[3],a[2]=a[6],a[3]=c,a[5]=a[7],a[6]=d,a[7]=e,a}return b[0]=a[0],b[1]=a[3],b[2]=a[6],b[3]=a[1],b[4]=a[4],b[5]=a[7],b[6]=a[2],b[7]=a[5],b[8]=a[8],b},f.mat3.toMat4=function(a,b){return b||(b=f.mat4.create()),b[15]=1,b[14]=0,b[13]=0,b[12]=0,b[11]=0,b[10]=a[8],b[9]=a[7],b[8]=a[6],b[7]=0,b[6]=a[5],b[5]=a[4],b[4]=a[3],b[3]=0,b[2]=a[2],b[1]=a[1],b[0]=a[0],b},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat4.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[3],f=a[6],g=a[7],h=a[11];return a[1]=a[4],a[2]=a[8],a[3]=a[12],a[4]=c,a[6]=a[9],a[7]=a[13],a[8]=d,a[9]=f,a[11]=a[14],a[12]=e,a[13]=g,a[14]=h,a}return b[0]=a[0],b[1]=a[4],b[2]=a[8],b[3]=a[12],b[4]=a[1],b[5]=a[5],b[6]=a[9],b[7]=a[13],b[8]=a[2],b[9]=a[6],b[10]=a[10],b[11]=a[14],b[12]=a[3],b[13]=a[7],b[14]=a[11],b[15]=a[15],b},f.mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=b[0],u=b[1],v=b[2],w=b[3];return c[0]=t*d+u*h+v*l+w*p,c[1]=t*e+u*i+v*m+w*q,c[2]=t*f+u*j+v*n+w*r,c[3]=t*g+u*k+v*o+w*s,t=b[4],u=b[5],v=b[6],w=b[7],c[4]=t*d+u*h+v*l+w*p,c[5]=t*e+u*i+v*m+w*q,c[6]=t*f+u*j+v*n+w*r,c[7]=t*g+u*k+v*o+w*s,t=b[8],u=b[9],v=b[10],w=b[11],c[8]=t*d+u*h+v*l+w*p,c[9]=t*e+u*i+v*m+w*q,c[10]=t*f+u*j+v*n+w*r,c[11]=t*g+u*k+v*o+w*s,t=b[12],u=b[13],v=b[14],w=b[15],c[12]=t*d+u*h+v*l+w*p,c[13]=t*e+u*i+v*m+w*q,c[14]=t*f+u*j+v*n+w*r,c[15]=t*g+u*k+v*o+w*s,c},f.DisplayObject=function(){this.last=this,this.first=this,this.position=new f.Point,this.scale=new f.Point(1,1),this.pivot=new f.Point(0,0),this.rotation=0,this.alpha=1,this.visible=!0,this.hitArea=null,this.buttonMode=!1,this.renderable=!1,this.parent=null,this.stage=null,this.worldAlpha=1,this._interactive=!1,this.worldTransform=f.mat3.create(),this.localTransform=f.mat3.create(),this.color=[],this.dynamic=!0,this._sr=0,this._cr=1,this.filterArea=new f.Rectangle(0,0,1,1)},f.DisplayObject.prototype.constructor=f.DisplayObject,f.DisplayObject.prototype.setInteractive=function(a){this.interactive=a},Object.defineProperty(f.DisplayObject.prototype,"interactive",{get:function(){return this._interactive},set:function(a){this._interactive=a,this.stage&&(this.stage.dirty=!0)}}),Object.defineProperty(f.DisplayObject.prototype,"mask",{get:function(){return this._mask},set:function(a){a?this._mask?(a.start=this._mask.start,a.end=this._mask.end):(this.addFilter(a),a.renderable=!1):(this.removeFilter(this._mask),this._mask.renderable=!0),this._mask=a}}),Object.defineProperty(f.DisplayObject.prototype,"filters",{get:function(){return this._filters},set:function(a){if(a){this._filters&&this.removeFilter(this._filters),this.addFilter(a);for(var b=[],c=0;c=0&&b<=this.children.length))throw new Error(a+" The index "+b+" supplied is out of bounds "+this.children.length);if(void 0!=a.parent&&a.parent.removeChild(a),a.parent=this,this.stage){var c=a;do c.interactive&&(this.stage.dirty=!0),c.stage=this.stage,c=c._iNext;while(c)}var d,e,f=a.first,g=a.last;if(b==this.children.length){e=this.last;for(var h=this,i=this.last;h;)h.last==i&&(h.last=a.last),h=h.parent}else e=0==b?this:this.children[b-1].last;d=e._iNext,d&&(d._iPrev=g,g._iNext=d),f._iPrev=e,e._iNext=f,this.children.splice(b,0,a),this.__renderGroup&&(a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a),this.__renderGroup.addDisplayObjectAndChildren(a))},f.DisplayObjectContainer.prototype.swapChildren=function(){},f.DisplayObjectContainer.prototype.getChildAt=function(a){if(a>=0&&aa;a++)this.children[a].updateTransform()}},f.blendModes={},f.blendModes.NORMAL=0,f.blendModes.SCREEN=1,f.Sprite=function(a){f.DisplayObjectContainer.call(this),this.anchor=new f.Point,this.texture=a,this.blendMode=f.blendModes.NORMAL,this._width=0,this._height=0,a.baseTexture.hasLoaded?this.updateFrame=!0:(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Sprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Sprite.prototype.constructor=f.Sprite,Object.defineProperty(f.Sprite.prototype,"width",{get:function(){return this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(f.Sprite.prototype,"height",{get:function(){return this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),f.Sprite.prototype.setTexture=function(a){this.texture.baseTexture!=a.baseTexture?(this.textureChange=!0,this.texture=a,this.__renderGroup&&this.__renderGroup.updateTexture(this)):this.texture=a,this.updateFrame=!0},f.Sprite.prototype.onTextureUpdate=function(){this._width&&(this.scale.x=this._width/this.texture.frame.width),this._height&&(this.scale.y=this._height/this.texture.frame.height),this.updateFrame=!0},f.Sprite.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache"+this);return new f.Sprite(b)},f.Sprite.fromImage=function(a){var b=f.Texture.fromImage(a);return new f.Sprite(b)},f.MovieClip=function(a){f.Sprite.call(this,a[0]),this.textures=a,this.animationSpeed=1,this.loop=!0,this.onComplete=null,this.currentFrame=0,this.playing=!1},f.MovieClip.prototype=Object.create(f.Sprite.prototype),f.MovieClip.prototype.constructor=f.MovieClip,Object.defineProperty(f.MovieClip.prototype,"totalFrames",{get:function(){return this.textures.length}}),f.MovieClip.prototype.stop=function(){this.playing=!1},f.MovieClip.prototype.play=function(){this.playing=!0},f.MovieClip.prototype.gotoAndStop=function(a){this.playing=!1,this.currentFrame=a;var b=0|this.currentFrame+.5;this.setTexture(this.textures[b%this.textures.length])},f.MovieClip.prototype.gotoAndPlay=function(a){this.currentFrame=a,this.playing=!0},f.MovieClip.prototype.updateTransform=function(){if(f.Sprite.prototype.updateTransform.call(this),this.playing){this.currentFrame+=this.animationSpeed;var a=0|this.currentFrame+.5;this.loop||a=this.textures.length&&(this.gotoAndStop(this.textures.length-1),this.onComplete&&this.onComplete())}},f.FilterBlock=function(){this.visible=!0,this.renderable=!0},f.Text=function(a,b){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),f.Sprite.call(this,f.Texture.fromCanvas(this.canvas)),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.Text.prototype=Object.create(f.Sprite.prototype),f.Text.prototype.constructor=f.Text,f.Text.prototype.setStyle=function(a){a=a||{},a.font=a.font||"bold 20pt Arial",a.fill=a.fill||"black",a.align=a.align||"left",a.stroke=a.stroke||"black",a.strokeThickness=a.strokeThickness||0,a.wordWrap=a.wordWrap||!1,a.wordWrapWidth=a.wordWrapWidth||100,this.style=a,this.dirty=!0},f.Text.prototype.setText=function(a){this.text=a.toString()||" ",this.dirty=!0},f.Text.prototype.updateText=function(){this.context.font=this.style.font;var a=this.text;this.style.wordWrap&&(a=this.wordWrap(this.text));for(var b=a.split(/(?:\r\n|\r|\n)/),c=[],d=0,e=0;ee?f:arguments.callee(a,b,f,d,e):arguments.callee(a,b,c,f,e)},c=function(a,c,d){if(a.measureText(c).width<=d||c.length<1)return c;var e=b(a,c,0,c.length,d);return c.substring(0,e)+"\n"+arguments.callee(a,c.substring(e),d)},d="",e=a.split("\n"),f=0;f=2?parseInt(b[b.length-2],10):f.BitmapText.fonts[this.fontName].size,this.dirty=!0},f.BitmapText.prototype.updateText=function(){for(var a=f.BitmapText.fonts[this.fontName],b=new f.Point,c=null,d=[],e=0,g=[],h=0,i=this.fontSize/a.size,j=0;j=j;j++){var n=0;"right"==this.style.align?n=e-g[j]:"center"==this.style.align&&(n=(e-g[j])/2),m.push(n)}for(j=0;j0;)this.removeChild(this.getChildAt(0));this.updateText(),this.dirty=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.BitmapText.fonts={},f.InteractionManager=function(a){this.stage=a,this.mouse=new f.InteractionData,this.touchs={},this.tempPoint=new f.Point,this.mouseoverEnabled=!0,this.pool=[],this.interactiveItems=[],this.interactionDOMElement=null,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseOut=this.onMouseOut.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.last=0},f.InteractionManager.prototype.constructor=f.InteractionManager,f.InteractionManager.prototype.collectInteractiveSprite=function(a,b){for(var c=a.children,d=c.length,e=d-1;e>=0;e--){var f=c[e];f.interactive?(b.interactiveChildren=!0,this.interactiveItems.push(f),f.children.length>0&&this.collectInteractiveSprite(f,f)):(f.__iParent=null,f.children.length>0&&this.collectInteractiveSprite(f,b))}},f.InteractionManager.prototype.setTarget=function(a){this.target=a,null===this.interactionDOMElement&&this.setTargetDomElement(a.view),document.body.addEventListener("mouseup",this.onMouseUp,!0)},f.InteractionManager.prototype.setTargetDomElement=function(a){null!==this.interactionDOMElement&&(this.interactionDOMElement.style["-ms-content-zooming"]="",this.interactionDOMElement.style["-ms-touch-action"]="",this.interactionDOMElement.removeEventListener("mousemove",this.onMouseMove,!0),this.interactionDOMElement.removeEventListener("mousedown",this.onMouseDown,!0),this.interactionDOMElement.removeEventListener("mouseout",this.onMouseOut,!0),this.interactionDOMElement.removeEventListener("touchstart",this.onTouchStart,!0),this.interactionDOMElement.removeEventListener("touchend",this.onTouchEnd,!0),this.interactionDOMElement.removeEventListener("touchmove",this.onTouchMove,!0)),window.navigator.msPointerEnabled&&(a.style["-ms-content-zooming"]="none",a.style["-ms-touch-action"]="none"),this.interactionDOMElement=a,a.addEventListener("mousemove",this.onMouseMove,!0),a.addEventListener("mousedown",this.onMouseDown,!0),a.addEventListener("mouseout",this.onMouseOut,!0),a.addEventListener("touchstart",this.onTouchStart,!0),a.addEventListener("touchend",this.onTouchEnd,!0),a.addEventListener("touchmove",this.onTouchMove,!0)},f.InteractionManager.prototype.update=function(){if(this.target){var a=Date.now(),b=a-this.last;if(b=30*b/1e3,!(1>b)){if(this.last=a,this.dirty){this.dirty=!1;for(var c=this.interactiveItems.length,d=0;c>d;d++)this.interactiveItems[d].interactiveChildren=!1;this.interactiveItems=[],this.stage.interactive&&this.interactiveItems.push(this.stage),this.collectInteractiveSprite(this.stage,this.stage)}var e=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var d=0;e>d;d++){var f=this.interactiveItems[d];(f.mouseover||f.mouseout||f.buttonMode)&&(f.__hit=this.hitTest(f,this.mouse),this.mouse.target=f,f.__hit?(f.buttonMode&&(this.interactionDOMElement.style.cursor="pointer"),f.__isOver||(f.mouseover&&f.mouseover(this.mouse),f.__isOver=!0)):f.__isOver&&(f.mouseout&&f.mouseout(this.mouse),f.__isOver=!1))}}}},f.InteractionManager.prototype.onMouseMove=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactionDOMElement.getBoundingClientRect();this.mouse.global.x=(a.clientX-b.left)*(this.target.width/b.width),this.mouse.global.y=(a.clientY-b.top)*(this.target.height/b.height);var c=this.interactiveItems.length;this.mouse.global;for(var d=0;c>d;d++){var e=this.interactiveItems[d];e.mousemove&&e.mousemove(this.mouse)}},f.InteractionManager.prototype.onMouseDown=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactiveItems.length;this.mouse.global,this.stage;for(var c=0;b>c;c++){var d=this.interactiveItems[c];if((d.mousedown||d.click)&&(d.__mouseIsDown=!0,d.__hit=this.hitTest(d,this.mouse),d.__hit&&(d.mousedown&&d.mousedown(this.mouse),d.__isDown=!0,!d.interactiveChildren)))break}},f.InteractionManager.prototype.onMouseOut=function(){var a=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var b=0;a>b;b++){var c=this.interactiveItems[b];c.__isOver&&(this.mouse.target=c,c.mouseout&&c.mouseout(this.mouse),c.__isOver=!1)}},f.InteractionManager.prototype.onMouseUp=function(a){this.mouse.originalEvent=a||window.event,this.mouse.global;for(var b=this.interactiveItems.length,c=!1,d=0;b>d;d++){var e=this.interactiveItems[d];(e.mouseup||e.mouseupoutside||e.click)&&(e.__hit=this.hitTest(e,this.mouse),e.__hit&&!c?(e.mouseup&&e.mouseup(this.mouse),e.__isDown&&e.click&&e.click(this.mouse),e.interactiveChildren||(c=!0)):e.__isDown&&e.mouseupoutside&&e.mouseupoutside(this.mouse),e.__isDown=!1)}},f.InteractionManager.prototype.hitTest=function(a,b){var c=b.global;if(a.vcount!==f.visibleCount)return!1;var d=a instanceof f.Sprite,e=a.worldTransform,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=1/(g*k+h*-j),n=k*m*c.x+-h*m*c.y+(l*h-i*k)*m,o=g*m*c.y+-j*m*c.x+(-l*g+i*j)*m;if(b.target=a,a.hitArea&&a.hitArea.contains)return a.hitArea.contains(n,o)?(b.target=a,!0):!1;if(d){var p,q=a.texture.frame.width,r=a.texture.frame.height,s=-q*a.anchor.x;if(n>s&&s+q>n&&(p=-r*a.anchor.y,o>p&&p+r>o))return b.target=a,!0}for(var t=a.children.length,u=0;t>u;u++){var v=a.children[u],w=this.hitTest(v,b);if(w)return b.target=a,!0}return!1},f.InteractionManager.prototype.onTouchMove=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;dd;d++){var h=this.interactiveItems[d];h.touchmove&&h.touchmove(f)}},f.InteractionManager.prototype.onTouchStart=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i];if((j.touchstart||j.tap)&&(j.__hit=this.hitTest(j,g),j.__hit&&(j.touchstart&&j.touchstart(g),j.__isDown=!0,j.__touchData=g,!j.interactiveChildren)))break}}},f.InteractionManager.prototype.onTouchEnd=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i],k=j.__touchData;j.__hit=this.hitTest(j,f),k==f&&(f.originalEvent=a||window.event,(j.touchend||j.tap)&&(j.__hit&&!g?(j.touchend&&j.touchend(f),j.__isDown&&j.tap&&j.tap(f),j.interactiveChildren||(g=!0)):j.__isDown&&j.touchendoutside&&j.touchendoutside(f),j.__isDown=!1),j.__touchData=null)}this.pool.push(f),this.touchs[e.identifier]=null}},f.InteractionData=function(){this.global=new f.Point,this.local=new f.Point,this.target,this.originalEvent},f.InteractionData.prototype.getLocalPosition=function(a){var b=a.worldTransform,c=this.global,d=b[0],e=b[1],g=b[2],h=b[3],i=b[4],j=b[5],k=1/(d*i+e*-h);return new f.Point(i*k*c.x+-e*k*c.y+(j*e-g*i)*k,d*k*c.y+-h*k*c.x+(-j*d+g*h)*k)},f.InteractionData.prototype.constructor=f.InteractionData,f.Stage=function(a){f.DisplayObjectContainer.call(this),this.worldTransform=f.mat3.create(),this.interactive=!0,this.interactionManager=new f.InteractionManager(this),this.dirty=!0,this.__childrenAdded=[],this.__childrenRemoved=[],this.stage=this,this.stage.hitArea=new f.Rectangle(0,0,1e5,1e5),this.setBackgroundColor(a),this.worldVisible=!0},f.Stage.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Stage.prototype.constructor=f.Stage,f.Stage.prototype.setInteractionDelegate=function(a){this.interactionManager.setTargetDomElement(a)},f.Stage.prototype.updateTransform=function(){this.worldAlpha=1,this.vcount=f.visibleCount;for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform();this.dirty&&(this.dirty=!1,this.interactionManager.dirty=!0),this.interactive&&this.interactionManager.update()},f.Stage.prototype.setBackgroundColor=function(a){this.backgroundColor=a||0,this.backgroundColorSplit=d(this.backgroundColor);var b=this.backgroundColor.toString(16);b="000000".substr(0,6-b.length)+b,this.backgroundColorString="#"+b},f.Stage.prototype.getMousePosition=function(){return this.interactionManager.mouse.global};for(var h=0,i=["ms","moz","webkit","o"],j=0;j>>>>>>>>"),console.log("_");var b=0,c=a.first;for(console.log(c);c._iNext;)if(b++,c=c._iNext,console.log(c),b>100){console.log("BREAK");break}},f.EventTarget=function(){var a={};this.addEventListener=this.on=function(b,c){void 0===a[b]&&(a[b]=[]),-1===a[b].indexOf(c)&&a[b].push(c)},this.dispatchEvent=this.emit=function(b){if(a[b.type]&&a[b.type].length)for(var c=0,d=a[b.type].length;d>c;c++)a[b.type][c](b)},this.removeEventListener=this.off=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)}},f.autoDetectRenderer=function(a,b,c,d,e){a||(a=800),b||(b=600);var g=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}();if(g){var h=-1!=navigator.userAgent.toLowerCase().indexOf("msie");g=!h}return g?new f.WebGLRenderer(a,b,c,d,e):new f.CanvasRenderer(a,b,c,d)},f.PolyK={},f.PolyK.Triangulate=function(a){var b=!0,c=a.length>>1;if(3>c)return[];for(var d=[],e=[],g=0;c>g;g++)e.push(g);for(var g=0,h=c;h>3;){var i=e[(g+0)%h],j=e[(g+1)%h],k=e[(g+2)%h],l=a[2*i],m=a[2*i+1],n=a[2*j],o=a[2*j+1],p=a[2*k],q=a[2*k+1],r=!1;if(f.PolyK._convex(l,m,n,o,p,q,b)){r=!0;for(var s=0;h>s;s++){var t=e[s];if(t!=i&&t!=j&&t!=k&&f.PolyK._PointInTriangle(a[2*t],a[2*t+1],l,m,n,o,p,q)){r=!1;break}}}if(r)d.push(i,j,k),e.splice((g+1)%h,1),h--,g=0;else if(g++>3*h){if(!b)return console.log("PIXI Warning: shape too complex to fill"),[];var d=[];e=[];for(var g=0;c>g;g++)e.push(g);g=0,h=c,b=!1}}return d.push(e[0],e[1],e[2]),d},f.PolyK._PointInTriangle=function(a,b,c,d,e,f,g,h){var i=g-c,j=h-d,k=e-c,l=f-d,m=a-c,n=b-d,o=i*i+j*j,p=i*k+j*l,q=i*m+j*n,r=k*k+l*l,s=k*m+l*n,t=1/(o*r-p*p),u=(r*q-p*s)*t,v=(o*s-p*q)*t;return u>=0&&v>=0&&1>u+v},f.PolyK._convex=function(a,b,c,d,e,f,g){return(b-d)*(e-c)+(c-a)*(f-d)>=0==g},f.initDefaultShaders=function(){f.primitiveShader=new f.PrimitiveShader,f.primitiveShader.init(),f.stripShader=new f.StripShader,f.stripShader.init(),f.defaultShader=new f.PixiShader,f.defaultShader.init();var a=f.gl,b=f.defaultShader.program;a.useProgram(b),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.primitiveShader.program),a.disableVertexAttribArray(f.defaultShader.aVertexPosition),a.disableVertexAttribArray(f.defaultShader.colorAttribute),a.disableVertexAttribArray(f.defaultShader.aTextureCoord),a.enableVertexAttribArray(f.primitiveShader.aVertexPosition),a.enableVertexAttribArray(f.primitiveShader.colorAttribute)},f.deactivatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program),a.disableVertexAttribArray(f.primitiveShader.aVertexPosition),a.disableVertexAttribArray(f.primitiveShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activateStripShader=function(){var a=f.gl;a.useProgram(f.stripShader.program)},f.deactivateStripShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program)},f.CompileVertexShader=function(a,b){return f._CompileShader(a,b,a.VERTEX_SHADER)},f.CompileFragmentShader=function(a,b){return f._CompileShader(a,b,a.FRAGMENT_SHADER)},f._CompileShader=function(a,b,c){var d=b.join("\n"),e=a.createShader(c);return a.shaderSource(e,d),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)?e:(console.log(a.getShaderInfoLog(e)),null)},f.compileProgram=function(a,b){var c=f.gl,d=f.CompileFragmentShader(c,b),e=f.CompileVertexShader(c,a),g=c.createProgram();return c.attachShader(g,e),c.attachShader(g,d),c.linkProgram(g),c.getProgramParameter(g,c.LINK_STATUS)||console.log("Could not initialise shaders"),g},f.PixiShader=function(){this.program,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;","}"]},f.PixiShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc||f.PixiShader.defaultVertexSrc,this.fragmentSrc),b=f.gl; -b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord");for(var c in this.uniforms)this.uniforms[c].uniformLocation=b.getUniformLocation(a,c);this.program=a},f.PixiShader.prototype.syncUniforms=function(){var a=f.gl;for(var b in this.uniforms){var c=this.uniforms[b].type;if("f"==c&&a.uniform1f(this.uniforms[b].uniformLocation,this.uniforms[b].value),"f2"==c)a.uniform2f(this.uniforms[b].uniformLocation,this.uniforms[b].value.x,this.uniforms[b].value.y);else if("f4"==c)a.uniform4fv(this.uniforms[b].uniformLocation,this.uniforms[b].value);else if("mat4"==c)a.uniformMatrix4fv(this.uniforms[b].uniformLocation,!1,this.uniforms[b].value);else if("sampler2D"==c){var d=this.uniforms[b].value;a.activeTexture(a.TEXTURE1),a.bindTexture(a.TEXTURE_2D,d.baseTexture._glTexture),a.uniform1i(this.uniforms[b].uniformLocation,1)}}},f.PixiShader.defaultVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","varying float vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"],f.StripShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying float vColor;","uniform float alpha;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));","gl_FragColor = gl_FragColor * alpha;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","varying vec2 vTextureCoord;","varying vec2 offsetVector;","varying float vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"]},f.StripShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.PrimitiveShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","gl_FragColor = vColor;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec4 aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform float alpha;","varying vec4 vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","vColor = aColor * alpha;","}"]},f.PrimitiveShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.WebGLGraphics=function(){},f.WebGLGraphics.renderGraphics=function(a,b){var c=f.gl;a._webGL||(a._webGL={points:[],indices:[],lastIndex:0,buffer:c.createBuffer(),indexBuffer:c.createBuffer()}),a.dirty&&(a.dirty=!1,a.clearDirty&&(a.clearDirty=!1,a._webGL.lastIndex=0,a._webGL.points=[],a._webGL.indices=[]),f.WebGLGraphics.updateGraphics(a)),f.activatePrimitiveShader();var d=f.mat3.clone(a.worldTransform);f.mat3.transpose(d),c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA),c.uniformMatrix3fv(f.primitiveShader.translationMatrix,!1,d),c.uniform2f(f.primitiveShader.projectionVector,b.x,-b.y),c.uniform2f(f.primitiveShader.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(f.primitiveShader.alpha,a.worldAlpha),c.bindBuffer(c.ARRAY_BUFFER,a._webGL.buffer),c.vertexAttribPointer(f.primitiveShader.aVertexPosition,2,c.FLOAT,!1,24,0),c.vertexAttribPointer(f.primitiveShader.colorAttribute,4,c.FLOAT,!1,24,8),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),c.drawElements(c.TRIANGLE_STRIP,a._webGL.indices.length,c.UNSIGNED_SHORT,0),f.deactivatePrimitiveShader()},f.WebGLGraphics.updateGraphics=function(a){for(var b=a._webGL.lastIndex;b3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){if(a.lineWidth%2)for(var e=0;ee;e++)k=c[2*(e-1)],l=c[2*(e-1)+1],m=c[2*e],n=c[2*e+1],o=c[2*(e+1)],p=c[2*(e+1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,s=-(n-p),t=m-o,E=Math.sqrt(s*s+t*t),s/=E,t/=E,s*=K,t*=K,w=-r+l-(-r+n),x=-q+m-(-q+k),y=(-q+k)*(-r+n)-(-q+m)*(-r+l),z=-t+p-(-t+n),A=-s+m-(-s+o),B=(-s+o)*(-t+n)-(-s+m)*(-t+p),C=w*A-z*x,Math.abs(C)<.1?(C+=10.1,F.push(m-q,n-r,N,O,P,M),F.push(m+q,n+r,N,O,P,M)):(px=(x*B-A*y)/C,py=(z*y-w*B)/C,D=(px-m)*(px-m)+(py-n)+(py-n),D>19600?(u=q-s,v=r-t,E=Math.sqrt(u*u+v*v),u/=E,v/=E,u*=K,v*=K,F.push(m-u,n-v),F.push(N,O,P,M),F.push(m+u,n+v),F.push(N,O,P,M),F.push(m-u,n-v),F.push(N,O,P,M),I++):(F.push(px,py),F.push(N,O,P,M),F.push(m-(px-m),n-(py-n)),F.push(N,O,P,M)));k=c[2*(H-2)],l=c[2*(H-2)+1],m=c[2*(H-1)],n=c[2*(H-1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,F.push(m-q,n-r),F.push(N,O,P,M),F.push(m+q,n+r),F.push(N,O,P,M),G.push(J);for(var e=0;I>e;e++)G.push(J++);G.push(J-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},flip=!1;var l=[],m=0;f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;if(a.open)a.data instanceof Array?this.filterManager.pushFilter(a):(m++,l.push(a),c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.INCR),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP));else if(a.data instanceof Array)this.filterManager.popFilter();else{var d=l.pop(a);d&&(c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.DECR),f.WebGLGraphics.renderGraphics(d.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)),c.disable(c.STENCIL_TEST)}},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(){this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;h>16)/255,(255&a>>8)/255,(255&a)/255]}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}var e=this,f=f||{};f.Point=function(a,b){this.x=a||0,this.y=b||0},f.Point.prototype.clone=function(){return new f.Point(this.x,this.y)},f.Point.prototype.constructor=f.Point,f.Rectangle=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Rectangle.prototype.clone=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Rectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},f.Rectangle.prototype.constructor=f.Rectangle,f.Polygon=function(a){if(a instanceof Array||(a=Array.prototype.slice.call(arguments)),"number"==typeof a[0]){for(var b=[],c=0,d=a.length;d>c;c+=2)b.push(new f.Point(a[c],a[c+1]));a=b}this.points=a},f.Polygon.prototype.clone=function(){for(var a=[],b=0;bb!=i>b&&(h-f)*(b-g)/(i-g)+f>a;j&&(c=!c)}return c},f.Polygon.prototype.constructor=f.Polygon,f.Circle=function(a,b,c){this.x=a||0,this.y=b||0,this.radius=c||0},f.Circle.prototype.clone=function(){return new f.Circle(this.x,this.y,this.radius)},f.Circle.prototype.contains=function(a,b){if(this.radius<=0)return!1;var c=this.x-a,d=this.y-b,e=this.radius*this.radius;return c*=c,d*=d,e>=c+d},f.Circle.prototype.constructor=f.Circle,f.Ellipse=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Ellipse.prototype.clone=function(){return new f.Ellipse(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=(a-this.x)/this.width-.5,d=(b-this.y)/this.height-.5;return c*=c,d*=d,.25>c+d},f.Ellipse.getBounds=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.constructor=f.Ellipse,c(),f.mat3={},f.mat3.create=function(){var a=new f.Matrix(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat3.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat4={},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat3.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=b[0],n=b[1],o=b[2],p=b[3],q=b[4],r=b[5],s=b[6],t=b[7],u=b[8];return c[0]=m*d+n*g+o*j,c[1]=m*e+n*h+o*k,c[2]=m*f+n*i+o*l,c[3]=p*d+q*g+r*j,c[4]=p*e+q*h+r*k,c[5]=p*f+q*i+r*l,c[6]=s*d+t*g+u*j,c[7]=s*e+t*h+u*k,c[8]=s*f+t*i+u*l,c},f.mat3.clone=function(a){var b=new f.Matrix(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},f.mat3.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[5];return a[1]=a[3],a[2]=a[6],a[3]=c,a[5]=a[7],a[6]=d,a[7]=e,a}return b[0]=a[0],b[1]=a[3],b[2]=a[6],b[3]=a[1],b[4]=a[4],b[5]=a[7],b[6]=a[2],b[7]=a[5],b[8]=a[8],b},f.mat3.toMat4=function(a,b){return b||(b=f.mat4.create()),b[15]=1,b[14]=0,b[13]=0,b[12]=0,b[11]=0,b[10]=a[8],b[9]=a[7],b[8]=a[6],b[7]=0,b[6]=a[5],b[5]=a[4],b[4]=a[3],b[3]=0,b[2]=a[2],b[1]=a[1],b[0]=a[0],b},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat4.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[3],f=a[6],g=a[7],h=a[11];return a[1]=a[4],a[2]=a[8],a[3]=a[12],a[4]=c,a[6]=a[9],a[7]=a[13],a[8]=d,a[9]=f,a[11]=a[14],a[12]=e,a[13]=g,a[14]=h,a}return b[0]=a[0],b[1]=a[4],b[2]=a[8],b[3]=a[12],b[4]=a[1],b[5]=a[5],b[6]=a[9],b[7]=a[13],b[8]=a[2],b[9]=a[6],b[10]=a[10],b[11]=a[14],b[12]=a[3],b[13]=a[7],b[14]=a[11],b[15]=a[15],b},f.mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=b[0],u=b[1],v=b[2],w=b[3];return c[0]=t*d+u*h+v*l+w*p,c[1]=t*e+u*i+v*m+w*q,c[2]=t*f+u*j+v*n+w*r,c[3]=t*g+u*k+v*o+w*s,t=b[4],u=b[5],v=b[6],w=b[7],c[4]=t*d+u*h+v*l+w*p,c[5]=t*e+u*i+v*m+w*q,c[6]=t*f+u*j+v*n+w*r,c[7]=t*g+u*k+v*o+w*s,t=b[8],u=b[9],v=b[10],w=b[11],c[8]=t*d+u*h+v*l+w*p,c[9]=t*e+u*i+v*m+w*q,c[10]=t*f+u*j+v*n+w*r,c[11]=t*g+u*k+v*o+w*s,t=b[12],u=b[13],v=b[14],w=b[15],c[12]=t*d+u*h+v*l+w*p,c[13]=t*e+u*i+v*m+w*q,c[14]=t*f+u*j+v*n+w*r,c[15]=t*g+u*k+v*o+w*s,c},f.DisplayObject=function(){this.last=this,this.first=this,this.position=new f.Point,this.scale=new f.Point(1,1),this.pivot=new f.Point(0,0),this.rotation=0,this.alpha=1,this.visible=!0,this.hitArea=null,this.buttonMode=!1,this.renderable=!1,this.parent=null,this.stage=null,this.worldAlpha=1,this._interactive=!1,this.worldTransform=f.mat3.create(),this.localTransform=f.mat3.create(),this.color=[],this.dynamic=!0,this._sr=0,this._cr=1,this.filterArea=new f.Rectangle(0,0,1,1)},f.DisplayObject.prototype.constructor=f.DisplayObject,f.DisplayObject.prototype.setInteractive=function(a){this.interactive=a},Object.defineProperty(f.DisplayObject.prototype,"interactive",{get:function(){return this._interactive},set:function(a){this._interactive=a,this.stage&&(this.stage.dirty=!0)}}),Object.defineProperty(f.DisplayObject.prototype,"mask",{get:function(){return this._mask},set:function(a){a?this._mask?(a.start=this._mask.start,a.end=this._mask.end):(this.addFilter(a),a.renderable=!1):(this.removeFilter(this._mask),this._mask.renderable=!0),this._mask=a}}),Object.defineProperty(f.DisplayObject.prototype,"filters",{get:function(){return this._filters},set:function(a){if(a){this._filters&&this.removeFilter(this._filters),this.addFilter(a);for(var b=[],c=0;c=0&&b<=this.children.length))throw new Error(a+" The index "+b+" supplied is out of bounds "+this.children.length);if(void 0!=a.parent&&a.parent.removeChild(a),a.parent=this,this.stage){var c=a;do c.interactive&&(this.stage.dirty=!0),c.stage=this.stage,c=c._iNext;while(c)}var d,e,f=a.first,g=a.last;if(b==this.children.length){e=this.last;for(var h=this,i=this.last;h;)h.last==i&&(h.last=a.last),h=h.parent}else e=0==b?this:this.children[b-1].last;d=e._iNext,d&&(d._iPrev=g,g._iNext=d),f._iPrev=e,e._iNext=f,this.children.splice(b,0,a),this.__renderGroup&&(a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a),this.__renderGroup.addDisplayObjectAndChildren(a))},f.DisplayObjectContainer.prototype.swapChildren=function(){},f.DisplayObjectContainer.prototype.getChildAt=function(a){if(a>=0&&aa;a++)this.children[a].updateTransform()}},f.blendModes={},f.blendModes.NORMAL=0,f.blendModes.SCREEN=1,f.Sprite=function(a){f.DisplayObjectContainer.call(this),this.anchor=new f.Point,this.texture=a,this.blendMode=f.blendModes.NORMAL,this._width=0,this._height=0,a.baseTexture.hasLoaded?this.updateFrame=!0:(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Sprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Sprite.prototype.constructor=f.Sprite,Object.defineProperty(f.Sprite.prototype,"width",{get:function(){return this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(f.Sprite.prototype,"height",{get:function(){return this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),f.Sprite.prototype.setTexture=function(a){this.texture.baseTexture!=a.baseTexture?(this.textureChange=!0,this.texture=a,this.__renderGroup&&this.__renderGroup.updateTexture(this)):this.texture=a,this.updateFrame=!0},f.Sprite.prototype.onTextureUpdate=function(){this._width&&(this.scale.x=this._width/this.texture.frame.width),this._height&&(this.scale.y=this._height/this.texture.frame.height),this.updateFrame=!0},f.Sprite.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache"+this);return new f.Sprite(b)},f.Sprite.fromImage=function(a){var b=f.Texture.fromImage(a);return new f.Sprite(b)},f.MovieClip=function(a){f.Sprite.call(this,a[0]),this.textures=a,this.animationSpeed=1,this.loop=!0,this.onComplete=null,this.currentFrame=0,this.playing=!1},f.MovieClip.prototype=Object.create(f.Sprite.prototype),f.MovieClip.prototype.constructor=f.MovieClip,Object.defineProperty(f.MovieClip.prototype,"totalFrames",{get:function(){return this.textures.length}}),f.MovieClip.prototype.stop=function(){this.playing=!1},f.MovieClip.prototype.play=function(){this.playing=!0},f.MovieClip.prototype.gotoAndStop=function(a){this.playing=!1,this.currentFrame=a;var b=0|this.currentFrame+.5;this.setTexture(this.textures[b%this.textures.length])},f.MovieClip.prototype.gotoAndPlay=function(a){this.currentFrame=a,this.playing=!0},f.MovieClip.prototype.updateTransform=function(){if(f.Sprite.prototype.updateTransform.call(this),this.playing){this.currentFrame+=this.animationSpeed;var a=0|this.currentFrame+.5;this.loop||a=this.textures.length&&(this.gotoAndStop(this.textures.length-1),this.onComplete&&this.onComplete())}},f.FilterBlock=function(){this.visible=!0,this.renderable=!0},f.Text=function(a,b){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),f.Sprite.call(this,f.Texture.fromCanvas(this.canvas)),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.Text.prototype=Object.create(f.Sprite.prototype),f.Text.prototype.constructor=f.Text,f.Text.prototype.setStyle=function(a){a=a||{},a.font=a.font||"bold 20pt Arial",a.fill=a.fill||"black",a.align=a.align||"left",a.stroke=a.stroke||"black",a.strokeThickness=a.strokeThickness||0,a.wordWrap=a.wordWrap||!1,a.wordWrapWidth=a.wordWrapWidth||100,this.style=a,this.dirty=!0},f.Text.prototype.setText=function(a){this.text=a.toString()||" ",this.dirty=!0},f.Text.prototype.updateText=function(){this.context.font=this.style.font;var a=this.text;this.style.wordWrap&&(a=this.wordWrap(this.text));for(var b=a.split(/(?:\r\n|\r|\n)/),c=[],d=0,e=0;ee?(g>0&&(b+="\n"),b+=f[g]+" ",e=this.style.wordWrapWidth-h):(e-=i,b+=f[g]+" ")}b+="\n"}return b},f.Text.prototype.destroy=function(a){a&&this.texture.destroy()},f.Text.heightCache={},f.BitmapText=function(a,b){f.DisplayObjectContainer.call(this),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.BitmapText.prototype=Object.create(f.DisplayObjectContainer.prototype),f.BitmapText.prototype.constructor=f.BitmapText,f.BitmapText.prototype.setText=function(a){this.text=a||" ",this.dirty=!0},f.BitmapText.prototype.setStyle=function(a){a=a||{},a.align=a.align||"left",this.style=a;var b=a.font.split(" ");this.fontName=b[b.length-1],this.fontSize=b.length>=2?parseInt(b[b.length-2],10):f.BitmapText.fonts[this.fontName].size,this.dirty=!0},f.BitmapText.prototype.updateText=function(){for(var a=f.BitmapText.fonts[this.fontName],b=new f.Point,c=null,d=[],e=0,g=[],h=0,i=this.fontSize/a.size,j=0;j=j;j++){var n=0;"right"==this.style.align?n=e-g[j]:"center"==this.style.align&&(n=(e-g[j])/2),m.push(n)}for(j=0;j0;)this.removeChild(this.getChildAt(0));this.updateText(),this.dirty=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.BitmapText.fonts={},f.InteractionManager=function(a){this.stage=a,this.mouse=new f.InteractionData,this.touchs={},this.tempPoint=new f.Point,this.mouseoverEnabled=!0,this.pool=[],this.interactiveItems=[],this.interactionDOMElement=null,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseOut=this.onMouseOut.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.last=0},f.InteractionManager.prototype.constructor=f.InteractionManager,f.InteractionManager.prototype.collectInteractiveSprite=function(a,b){for(var c=a.children,d=c.length,e=d-1;e>=0;e--){var f=c[e];f.interactive?(b.interactiveChildren=!0,this.interactiveItems.push(f),f.children.length>0&&this.collectInteractiveSprite(f,f)):(f.__iParent=null,f.children.length>0&&this.collectInteractiveSprite(f,b))}},f.InteractionManager.prototype.setTarget=function(a){this.target=a,null===this.interactionDOMElement&&this.setTargetDomElement(a.view),document.body.addEventListener("mouseup",this.onMouseUp,!0)},f.InteractionManager.prototype.setTargetDomElement=function(a){null!==this.interactionDOMElement&&(this.interactionDOMElement.style["-ms-content-zooming"]="",this.interactionDOMElement.style["-ms-touch-action"]="",this.interactionDOMElement.removeEventListener("mousemove",this.onMouseMove,!0),this.interactionDOMElement.removeEventListener("mousedown",this.onMouseDown,!0),this.interactionDOMElement.removeEventListener("mouseout",this.onMouseOut,!0),this.interactionDOMElement.removeEventListener("touchstart",this.onTouchStart,!0),this.interactionDOMElement.removeEventListener("touchend",this.onTouchEnd,!0),this.interactionDOMElement.removeEventListener("touchmove",this.onTouchMove,!0)),window.navigator.msPointerEnabled&&(a.style["-ms-content-zooming"]="none",a.style["-ms-touch-action"]="none"),this.interactionDOMElement=a,a.addEventListener("mousemove",this.onMouseMove,!0),a.addEventListener("mousedown",this.onMouseDown,!0),a.addEventListener("mouseout",this.onMouseOut,!0),a.addEventListener("touchstart",this.onTouchStart,!0),a.addEventListener("touchend",this.onTouchEnd,!0),a.addEventListener("touchmove",this.onTouchMove,!0)},f.InteractionManager.prototype.update=function(){if(this.target){var a=Date.now(),b=a-this.last;if(b=30*b/1e3,!(1>b)){if(this.last=a,this.dirty){this.dirty=!1;for(var c=this.interactiveItems.length,d=0;c>d;d++)this.interactiveItems[d].interactiveChildren=!1;this.interactiveItems=[],this.stage.interactive&&this.interactiveItems.push(this.stage),this.collectInteractiveSprite(this.stage,this.stage)}var e=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var d=0;e>d;d++){var f=this.interactiveItems[d];(f.mouseover||f.mouseout||f.buttonMode)&&(f.__hit=this.hitTest(f,this.mouse),this.mouse.target=f,f.__hit?(f.buttonMode&&(this.interactionDOMElement.style.cursor="pointer"),f.__isOver||(f.mouseover&&f.mouseover(this.mouse),f.__isOver=!0)):f.__isOver&&(f.mouseout&&f.mouseout(this.mouse),f.__isOver=!1))}}}},f.InteractionManager.prototype.onMouseMove=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactionDOMElement.getBoundingClientRect();this.mouse.global.x=(a.clientX-b.left)*(this.target.width/b.width),this.mouse.global.y=(a.clientY-b.top)*(this.target.height/b.height);var c=this.interactiveItems.length;this.mouse.global;for(var d=0;c>d;d++){var e=this.interactiveItems[d];e.mousemove&&e.mousemove(this.mouse)}},f.InteractionManager.prototype.onMouseDown=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactiveItems.length;this.mouse.global,this.stage;for(var c=0;b>c;c++){var d=this.interactiveItems[c];if((d.mousedown||d.click)&&(d.__mouseIsDown=!0,d.__hit=this.hitTest(d,this.mouse),d.__hit&&(d.mousedown&&d.mousedown(this.mouse),d.__isDown=!0,!d.interactiveChildren)))break}},f.InteractionManager.prototype.onMouseOut=function(){var a=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var b=0;a>b;b++){var c=this.interactiveItems[b];c.__isOver&&(this.mouse.target=c,c.mouseout&&c.mouseout(this.mouse),c.__isOver=!1)}},f.InteractionManager.prototype.onMouseUp=function(a){this.mouse.originalEvent=a||window.event,this.mouse.global;for(var b=this.interactiveItems.length,c=!1,d=0;b>d;d++){var e=this.interactiveItems[d];(e.mouseup||e.mouseupoutside||e.click)&&(e.__hit=this.hitTest(e,this.mouse),e.__hit&&!c?(e.mouseup&&e.mouseup(this.mouse),e.__isDown&&e.click&&e.click(this.mouse),e.interactiveChildren||(c=!0)):e.__isDown&&e.mouseupoutside&&e.mouseupoutside(this.mouse),e.__isDown=!1)}},f.InteractionManager.prototype.hitTest=function(a,b){var c=b.global;if(a.vcount!==f.visibleCount)return!1;var d=a instanceof f.Sprite,e=a.worldTransform,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=1/(g*k+h*-j),n=k*m*c.x+-h*m*c.y+(l*h-i*k)*m,o=g*m*c.y+-j*m*c.x+(-l*g+i*j)*m;if(b.target=a,a.hitArea&&a.hitArea.contains)return a.hitArea.contains(n,o)?(b.target=a,!0):!1;if(d){var p,q=a.texture.frame.width,r=a.texture.frame.height,s=-q*a.anchor.x;if(n>s&&s+q>n&&(p=-r*a.anchor.y,o>p&&p+r>o))return b.target=a,!0}for(var t=a.children.length,u=0;t>u;u++){var v=a.children[u],w=this.hitTest(v,b);if(w)return b.target=a,!0}return!1},f.InteractionManager.prototype.onTouchMove=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;dd;d++){var h=this.interactiveItems[d];h.touchmove&&h.touchmove(f)}},f.InteractionManager.prototype.onTouchStart=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i];if((j.touchstart||j.tap)&&(j.__hit=this.hitTest(j,g),j.__hit&&(j.touchstart&&j.touchstart(g),j.__isDown=!0,j.__touchData=g,!j.interactiveChildren)))break}}},f.InteractionManager.prototype.onTouchEnd=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i],k=j.__touchData;j.__hit=this.hitTest(j,f),k==f&&(f.originalEvent=a||window.event,(j.touchend||j.tap)&&(j.__hit&&!g?(j.touchend&&j.touchend(f),j.__isDown&&j.tap&&j.tap(f),j.interactiveChildren||(g=!0)):j.__isDown&&j.touchendoutside&&j.touchendoutside(f),j.__isDown=!1),j.__touchData=null)}this.pool.push(f),this.touchs[e.identifier]=null}},f.InteractionData=function(){this.global=new f.Point,this.local=new f.Point,this.target,this.originalEvent},f.InteractionData.prototype.getLocalPosition=function(a){var b=a.worldTransform,c=this.global,d=b[0],e=b[1],g=b[2],h=b[3],i=b[4],j=b[5],k=1/(d*i+e*-h);return new f.Point(i*k*c.x+-e*k*c.y+(j*e-g*i)*k,d*k*c.y+-h*k*c.x+(-j*d+g*h)*k)},f.InteractionData.prototype.constructor=f.InteractionData,f.Stage=function(a){f.DisplayObjectContainer.call(this),this.worldTransform=f.mat3.create(),this.interactive=!0,this.interactionManager=new f.InteractionManager(this),this.dirty=!0,this.__childrenAdded=[],this.__childrenRemoved=[],this.stage=this,this.stage.hitArea=new f.Rectangle(0,0,1e5,1e5),this.setBackgroundColor(a),this.worldVisible=!0},f.Stage.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Stage.prototype.constructor=f.Stage,f.Stage.prototype.setInteractionDelegate=function(a){this.interactionManager.setTargetDomElement(a)},f.Stage.prototype.updateTransform=function(){this.worldAlpha=1,this.vcount=f.visibleCount;for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform();this.dirty&&(this.dirty=!1,this.interactionManager.dirty=!0),this.interactive&&this.interactionManager.update()},f.Stage.prototype.setBackgroundColor=function(a){this.backgroundColor=a||0,this.backgroundColorSplit=d(this.backgroundColor);var b=this.backgroundColor.toString(16);b="000000".substr(0,6-b.length)+b,this.backgroundColorString="#"+b},f.Stage.prototype.getMousePosition=function(){return this.interactionManager.mouse.global};for(var h=0,i=["ms","moz","webkit","o"],j=0;j>>>>>>>>"),console.log("_");var b=0,c=a.first;for(console.log(c);c._iNext;)if(b++,c=c._iNext,console.log(c),b>100){console.log("BREAK");break}},f.EventTarget=function(){var a={};this.addEventListener=this.on=function(b,c){void 0===a[b]&&(a[b]=[]),-1===a[b].indexOf(c)&&a[b].push(c)},this.dispatchEvent=this.emit=function(b){if(a[b.type]&&a[b.type].length)for(var c=0,d=a[b.type].length;d>c;c++)a[b.type][c](b)},this.removeEventListener=this.off=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)}},f.autoDetectRenderer=function(a,b,c,d,e){a||(a=800),b||(b=600);var g=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}();if(g){var h=-1!=navigator.userAgent.toLowerCase().indexOf("msie");g=!h}return g?new f.WebGLRenderer(a,b,c,d,e):new f.CanvasRenderer(a,b,c,d)},f.PolyK={},f.PolyK.Triangulate=function(a){var b=!0,c=a.length>>1;if(3>c)return[];for(var d=[],e=[],g=0;c>g;g++)e.push(g);for(var g=0,h=c;h>3;){var i=e[(g+0)%h],j=e[(g+1)%h],k=e[(g+2)%h],l=a[2*i],m=a[2*i+1],n=a[2*j],o=a[2*j+1],p=a[2*k],q=a[2*k+1],r=!1;if(f.PolyK._convex(l,m,n,o,p,q,b)){r=!0;for(var s=0;h>s;s++){var t=e[s];if(t!=i&&t!=j&&t!=k&&f.PolyK._PointInTriangle(a[2*t],a[2*t+1],l,m,n,o,p,q)){r=!1;break}}}if(r)d.push(i,j,k),e.splice((g+1)%h,1),h--,g=0;else if(g++>3*h){if(!b)return console.log("PIXI Warning: shape too complex to fill"),[];var d=[];e=[];for(var g=0;c>g;g++)e.push(g);g=0,h=c,b=!1}}return d.push(e[0],e[1],e[2]),d},f.PolyK._PointInTriangle=function(a,b,c,d,e,f,g,h){var i=g-c,j=h-d,k=e-c,l=f-d,m=a-c,n=b-d,o=i*i+j*j,p=i*k+j*l,q=i*m+j*n,r=k*k+l*l,s=k*m+l*n,t=1/(o*r-p*p),u=(r*q-p*s)*t,v=(o*s-p*q)*t;return u>=0&&v>=0&&1>u+v},f.PolyK._convex=function(a,b,c,d,e,f,g){return(b-d)*(e-c)+(c-a)*(f-d)>=0==g},f.initDefaultShaders=function(){f.primitiveShader=new f.PrimitiveShader,f.primitiveShader.init(),f.stripShader=new f.StripShader,f.stripShader.init(),f.defaultShader=new f.PixiShader,f.defaultShader.init();var a=f.gl,b=f.defaultShader.program;a.useProgram(b),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.primitiveShader.program),a.disableVertexAttribArray(f.defaultShader.aVertexPosition),a.disableVertexAttribArray(f.defaultShader.colorAttribute),a.disableVertexAttribArray(f.defaultShader.aTextureCoord),a.enableVertexAttribArray(f.primitiveShader.aVertexPosition),a.enableVertexAttribArray(f.primitiveShader.colorAttribute)},f.deactivatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program),a.disableVertexAttribArray(f.primitiveShader.aVertexPosition),a.disableVertexAttribArray(f.primitiveShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activateStripShader=function(){var a=f.gl;a.useProgram(f.stripShader.program)},f.deactivateStripShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program)},f.CompileVertexShader=function(a,b){return f._CompileShader(a,b,a.VERTEX_SHADER)},f.CompileFragmentShader=function(a,b){return f._CompileShader(a,b,a.FRAGMENT_SHADER)},f._CompileShader=function(a,b,c){var d=b.join("\n"),e=a.createShader(c);return a.shaderSource(e,d),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)?e:(console.log(a.getShaderInfoLog(e)),null)},f.compileProgram=function(a,b){var c=f.gl,d=f.CompileFragmentShader(c,b),e=f.CompileVertexShader(c,a),g=c.createProgram();return c.attachShader(g,e),c.attachShader(g,d),c.linkProgram(g),c.getProgramParameter(g,c.LINK_STATUS)||console.log("Could not initialise shaders"),g},f.PixiShader=function(){this.program,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;","}"]},f.PixiShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc||f.PixiShader.defaultVertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"); +for(var c in this.uniforms)this.uniforms[c].uniformLocation=b.getUniformLocation(a,c);this.program=a},f.PixiShader.prototype.syncUniforms=function(){var a=f.gl;for(var b in this.uniforms){var c=this.uniforms[b].type;if("f"==c&&a.uniform1f(this.uniforms[b].uniformLocation,this.uniforms[b].value),"f2"==c)a.uniform2f(this.uniforms[b].uniformLocation,this.uniforms[b].value.x,this.uniforms[b].value.y);else if("f4"==c)a.uniform4fv(this.uniforms[b].uniformLocation,this.uniforms[b].value);else if("mat4"==c)a.uniformMatrix4fv(this.uniforms[b].uniformLocation,!1,this.uniforms[b].value);else if("sampler2D"==c){var d=this.uniforms[b].value;a.activeTexture(a.TEXTURE1),a.bindTexture(a.TEXTURE_2D,d.baseTexture._glTexture),a.uniform1i(this.uniforms[b].uniformLocation,1)}}},f.PixiShader.defaultVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","varying float vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"],f.StripShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying float vColor;","uniform float alpha;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));","gl_FragColor = gl_FragColor * alpha;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","varying vec2 vTextureCoord;","varying vec2 offsetVector;","varying float vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"]},f.StripShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.PrimitiveShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","gl_FragColor = vColor;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec4 aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform float alpha;","varying vec4 vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","vColor = aColor * alpha;","}"]},f.PrimitiveShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.WebGLGraphics=function(){},f.WebGLGraphics.renderGraphics=function(a,b){var c=f.gl;a._webGL||(a._webGL={points:[],indices:[],lastIndex:0,buffer:c.createBuffer(),indexBuffer:c.createBuffer()}),a.dirty&&(a.dirty=!1,a.clearDirty&&(a.clearDirty=!1,a._webGL.lastIndex=0,a._webGL.points=[],a._webGL.indices=[]),f.WebGLGraphics.updateGraphics(a)),f.activatePrimitiveShader();var d=f.mat3.clone(a.worldTransform);f.mat3.transpose(d),c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA),c.uniformMatrix3fv(f.primitiveShader.translationMatrix,!1,d),c.uniform2f(f.primitiveShader.projectionVector,b.x,-b.y),c.uniform2f(f.primitiveShader.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(f.primitiveShader.alpha,a.worldAlpha),c.bindBuffer(c.ARRAY_BUFFER,a._webGL.buffer),c.vertexAttribPointer(f.primitiveShader.aVertexPosition,2,c.FLOAT,!1,24,0),c.vertexAttribPointer(f.primitiveShader.colorAttribute,4,c.FLOAT,!1,24,8),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),c.drawElements(c.TRIANGLE_STRIP,a._webGL.indices.length,c.UNSIGNED_SHORT,0),f.deactivatePrimitiveShader()},f.WebGLGraphics.updateGraphics=function(a){for(var b=a._webGL.lastIndex;b3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){if(a.lineWidth%2)for(var e=0;ee;e++)k=c[2*(e-1)],l=c[2*(e-1)+1],m=c[2*e],n=c[2*e+1],o=c[2*(e+1)],p=c[2*(e+1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,s=-(n-p),t=m-o,E=Math.sqrt(s*s+t*t),s/=E,t/=E,s*=K,t*=K,w=-r+l-(-r+n),x=-q+m-(-q+k),y=(-q+k)*(-r+n)-(-q+m)*(-r+l),z=-t+p-(-t+n),A=-s+m-(-s+o),B=(-s+o)*(-t+n)-(-s+m)*(-t+p),C=w*A-z*x,Math.abs(C)<.1?(C+=10.1,F.push(m-q,n-r,N,O,P,M),F.push(m+q,n+r,N,O,P,M)):(px=(x*B-A*y)/C,py=(z*y-w*B)/C,D=(px-m)*(px-m)+(py-n)+(py-n),D>19600?(u=q-s,v=r-t,E=Math.sqrt(u*u+v*v),u/=E,v/=E,u*=K,v*=K,F.push(m-u,n-v),F.push(N,O,P,M),F.push(m+u,n+v),F.push(N,O,P,M),F.push(m-u,n-v),F.push(N,O,P,M),I++):(F.push(px,py),F.push(N,O,P,M),F.push(m-(px-m),n-(py-n)),F.push(N,O,P,M)));k=c[2*(H-2)],l=c[2*(H-2)+1],m=c[2*(H-1)],n=c[2*(H-1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,F.push(m-q,n-r),F.push(N,O,P,M),F.push(m+q,n+r),F.push(N,O,P,M),G.push(J);for(var e=0;I>e;e++)G.push(J++);G.push(J-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl,this.transparent)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},flip=!1;var l=[],m=0;f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;if(a.open)a.data instanceof Array?this.filterManager.pushFilter(a):(m++,l.push(a),c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.INCR),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP));else if(a.data instanceof Array)this.filterManager.popFilter();else{var d=l.pop(a);d&&(c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.DECR),f.WebGLGraphics.renderGraphics(d.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)),c.disable(c.STENCIL_TEST)}},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(a){this.transparent=a,this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;hs?s:E,E=E>t?t:E,E=E>u?u:E,E=E>v?v:E,F=F>w?w:F,F=F>x?x:F,F=F>y?y:F,F=F>z?z:F,C=s>C?s:C,C=t>C?t:C,C=u>C?u:C,C=v>C?v:C,D=w>D?w:D,D=x>D?x:D,D=y>D?y:D,D=z>D?z:D),l=!1,A=A._iNext}while(A!=B);a.filterArea.x=E,a.filterArea.y=F,a.filterArea.width=C-E,a.filterArea.height=D-F},f.FilterTexture=function(a,b){var c=f.gl;this.frameBuffer=c.createFramebuffer(),this.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,this.texture),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.bindFramebuffer(c.FRAMEBUFFER,this.framebuffer),c.bindFramebuffer(c.FRAMEBUFFER,this.frameBuffer),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,this.texture,0),this.resize(a,b)},f.FilterTexture.prototype.resize=function(a,b){this.width=a,this.height=b;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a,b,0,c.RGBA,c.UNSIGNED_BYTE,null)},f.CanvasRenderer=function(a,b,c,d){this.transparent=d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.context=this.view.getContext("2d"),this.refresh=!0,this.view.width=this.width,this.view.height=this.height,this.count=0},f.CanvasRenderer.prototype.constructor=f.CanvasRenderer,f.CanvasRenderer.prototype.render=function(a){f.texturesToUpdate=[],f.texturesToDestroy=[],f.visibleCount++,a.updateTransform(),this.view.style.backgroundColor==a.backgroundColorString||this.transparent||(this.view.style.backgroundColor=a.backgroundColorString),this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.width,this.height),this.renderDisplayObject(a),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0&&(f.Texture.frameUpdates=[])},f.CanvasRenderer.prototype.resize=function(a,b){this.width=a,this.height=b,this.view.width=a,this.view.height=b},f.CanvasRenderer.prototype.renderDisplayObject=function(a){var b,c=this.context;c.globalCompositeOperation="source-over";var d=a.last._iNext;a=a.first;do if(b=a.worldTransform,a.visible)if(a.renderable){if(a instanceof f.Sprite){var e=a.texture.frame;e&&e.width&&e.height&&(c.globalAlpha=a.worldAlpha,c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),c.drawImage(a.texture.baseTexture.source,e.x,e.y,e.width,e.height,a.anchor.x*-e.width,a.anchor.y*-e.height,e.width,e.height))}else if(a instanceof f.Strip)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderStrip(a);else if(a instanceof f.TilingSprite)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderTilingSprite(a);else if(a instanceof f.CustomRenderable)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),a.renderCanvas(this);else if(a instanceof f.Graphics)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),f.CanvasGraphics.renderGraphics(a,c);else if(a instanceof f.FilterBlock&&a.data instanceof f.Graphics){var g=a.data;if(a.open){c.save();var h=g.alpha,i=g.worldTransform;c.setTransform(i[0],i[3],i[1],i[4],i[2],i[5]),g.worldAlpha=.5,c.worldAlpha=0,f.CanvasGraphics.renderGraphicsMask(g,c),c.clip(),g.worldAlpha=h}else c.restore()}a=a._iNext}else a=a._iNext;else a=a.last._iNext;while(a!=d)},f.CanvasRenderer.prototype.renderStripFlat=function(a){var b=this.context,c=a.verticies;a.uvs;var d=c.length/2;this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},f.CanvasRenderer.prototype.renderTilingSprite=function(a){var b=this.context;b.globalAlpha=a.worldAlpha,a.__tilePattern||(a.__tilePattern=b.createPattern(a.texture.baseTexture.source,"repeat")),b.beginPath();var c=a.tilePosition,d=a.tileScale;b.scale(d.x,d.y),b.translate(c.x,c.y),b.fillStyle=a.__tilePattern,b.fillRect(-c.x,-c.y,a.width/d.x,a.height/d.y),b.scale(1/d.x,1/d.y),b.translate(-c.x,-c.y),b.closePath()},f.CanvasRenderer.prototype.renderStrip=function(a){var b=this.context,c=a.verticies,d=a.uvs,e=c.length/2;this.count++;for(var f=1;e-2>f;f++){var g=2*f,h=c[g],i=c[g+2],j=c[g+4],k=c[g+1],l=c[g+3],m=c[g+5],n=d[g]*a.texture.width,o=d[g+2]*a.texture.width,p=d[g+4]*a.texture.width,q=d[g+1]*a.texture.height,r=d[g+3]*a.texture.height,s=d[g+5]*a.texture.height;b.save(),b.beginPath(),b.moveTo(h,k),b.lineTo(i,l),b.lineTo(j,m),b.closePath(),b.clip();var t=n*r+q*p+o*s-r*p-q*o-n*s,u=h*r+q*j+i*s-r*j-q*i-h*s,v=n*i+h*p+o*j-i*p-h*o-n*j,w=n*r*j+q*i*p+h*o*s-h*r*p-q*o*j-n*i*s,x=k*r+q*m+l*s-r*m-q*l-k*s,y=n*l+k*p+o*m-l*p-k*o-n*m,z=n*r*m+q*l*p+k*o*s-k*r*p-q*o*m-n*l*s;b.transform(u/t,x/t,v/t,y/t,w/t,z/t),b.drawImage(a.texture.baseTexture.source,0,0),b.restore()}},f.CanvasGraphics=function(){},f.CanvasGraphics.renderGraphics=function(a,b){for(var c=a.worldAlpha,d=0;d1&&(c=1,console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var d=0;1>d;d++){var e=a.graphicsData[d],g=e.points;if(e.type==f.Graphics.POLY){b.beginPath(),b.moveTo(g[0],g[1]);for(var h=1;hb?b:d,e=b+m>e?b+m:e,g=g>c?b:g,h=c+n>h?c+n:h}else if(k===f.Graphics.CIRC||k===f.Graphics.ELIP){b=a.x,c=a.y;var o=a.radius+l/2;d=d>b-o?b-o:d,e=b+o>e?b+o:e,g=g>c-o?c-o:g,h=c+o>h?c+o:h}else for(var p=0;pb-l?b-l:d,e=b+l>e?b+l:e,g=g>c-l?c-l:g,h=c+l>h?c+l:h}this.bounds=new f.Rectangle(d,g,e-d,h-g)}},f.Graphics.POLY=0,f.Graphics.RECT=1,f.Graphics.CIRC=2,f.Graphics.ELIP=3,f.Strip=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.blendMode=f.blendModes.NORMAL;try{this.uvs=new Float32Array([0,1,1,1,1,0,0,1]),this.verticies=new Float32Array([0,0,0,0,0,0,0,0,0]),this.colors=new Float32Array([1,1,1,1]),this.indices=new Uint16Array([0,1,2,3])}catch(d){this.uvs=[0,1,1,1,1,0,0,1],this.verticies=[0,0,0,0,0,0,0,0,0],this.colors=[1,1,1,1],this.indices=[0,1,2,3]}this.width=b,this.height=c,a.baseTexture.hasLoaded?(this.width=this.texture.frame.width,this.height=this.texture.frame.height,this.updateFrame=!0):(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Strip.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Strip.prototype.constructor=f.Strip,f.Strip.prototype.setTexture=function(a){this.texture=a,this.width=a.frame.width,this.height=a.frame.height,this.updateFrame=!0},f.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Rope=function(a,b){f.Strip.call(this,a),this.points=b;try{this.verticies=new Float32Array(4*b.length),this.uvs=new Float32Array(4*b.length),this.colors=new Float32Array(2*b.length),this.indices=new Uint16Array(2*b.length)}catch(c){this.verticies=verticies,this.uvs=uvs,this.colors=colors,this.indices=indices}this.refresh()},f.Rope.prototype=Object.create(f.Strip.prototype),f.Rope.prototype.constructor=f.Rope,f.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=this.indices,d=this.colors,e=a[0],f=a[0];this.count-=.2,b[0]=0,b[1]=1,b[2]=0,b[3]=1,d[0]=1,d[1]=1,c[0]=0,c[1]=1;for(var g=a.length,h=1;g>h;h++){var f=a[h],i=4*h,j=h/(g-1);h%2?(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1):(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1),i=2*h,d[i]=1,d[i+1]=1,i=2*h,c[i]=i,c[i+1]=i+1,e=f}}},f.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var b,c=this.verticies,d=a[0],e={x:0,y:0},g=a[0];this.count-=.2,c[0]=g.x+e.x,c[1]=g.y+e.y,c[2]=g.x-e.x,c[3]=g.y-e.y;for(var h=a.length,i=1;h>i;i++){var g=a[i],j=4*i;b=i1&&(k=1);var l=Math.sqrt(e.x*e.x+e.y*e.y),m=this.texture.height/2;e.x/=l,e.y/=l,e.x*=m,e.y*=m,c[j]=g.x+e.x,c[j+1]=g.y+e.y,c[j+2]=g.x-e.x,c[j+3]=g.y-e.y,d=g}f.DisplayObjectContainer.prototype.updateTransform.call(this)}},f.Rope.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.width=b,this.height=c,this.tileScale=new f.Point(1,1),this.tilePosition=new f.Point(0,0),this.renderable=!0,this.blendMode=f.blendModes.NORMAL},f.TilingSprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.TilingSprite.prototype.constructor=f.TilingSprite,f.TilingSprite.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Spine=function(a){if(f.DisplayObjectContainer.call(this),this.spineData=f.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new n.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new n.AnimationStateData(this.spineData),this.state=new n.AnimationState(this.stateData),this.slotContainers=[];for(var b=0,c=this.skeleton.drawOrder.length;c>b;b++){var d=this.skeleton.drawOrder[b],e=d.attachment,g=new f.DisplayObjectContainer;if(this.slotContainers.push(g),this.addChild(g),e instanceof n.RegionAttachment){var h=e.rendererObject.name,i=this.createSprite(d,e.rendererObject);d.currentSprite=i,d.currentSpriteName=h,g.addChild(i)}}},f.Spine.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Spine.prototype.constructor=f.Spine,f.Spine.prototype.updateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var b=this.skeleton.drawOrder,c=0,d=b.length;d>c;c++){var e=b[c],g=e.attachment,h=this.slotContainers[c];if(g instanceof n.RegionAttachment){if(g.rendererObject&&(!e.currentSpriteName||e.currentSpriteName!=g.name)){var i=g.rendererObject.name;if(void 0!==e.currentSprite&&(e.currentSprite.visible=!1),e.sprites=e.sprites||{},void 0!==e.sprites[i])e.sprites[i].visible=!0;else{var j=this.createSprite(e,g.rendererObject);h.addChild(j)}e.currentSprite=e.sprites[i],e.currentSpriteName=i}h.visible=!0;var k=e.bone;h.position.x=k.worldX+g.x*k.m00+g.y*k.m01,h.position.y=k.worldY+g.x*k.m10+g.y*k.m11,h.scale.x=k.worldScaleX,h.scale.y=k.worldScaleY,h.rotation=-(e.bone.worldRotation*Math.PI/180)}else h.visible=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.Spine.prototype.createSprite=function(a,b){var c=f.TextureCache[b.name]?b.name:b.name+".png",d=new f.Sprite(f.Texture.fromFrame(c));return d.scale=b.scale,d.rotation=b.rotation,d.anchor.x=d.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[b.name]=d,d};var n={};n.BoneData=function(a,b){this.name=a,this.parent=b},n.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1},n.SlotData=function(a,b){this.name=a,this.boneData=b},n.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null},n.Bone=function(a,b){this.data=a,this.parent=b,this.setToSetupPose()},n.Bone.yDown=!1,n.Bone.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,updateWorldTransform:function(a,b){var c=this.parent;null!=c?(this.worldX=this.x*c.m00+this.y*c.m01+c.worldX,this.worldY=this.x*c.m10+this.y*c.m11+c.worldY,this.worldScaleX=c.worldScaleX*this.scaleX,this.worldScaleY=c.worldScaleY*this.scaleY,this.worldRotation=c.worldRotation+this.rotation):(this.worldX=this.x,this.worldY=this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotation);var d=this.worldRotation*Math.PI/180,e=Math.cos(d),f=Math.sin(d);this.m00=e*this.worldScaleX,this.m10=f*this.worldScaleX,this.m01=-f*this.worldScaleY,this.m11=e*this.worldScaleY,a&&(this.m00=-this.m00,this.m01=-this.m01),b&&(this.m10=-this.m10,this.m11=-this.m11),n.Bone.yDown&&(this.m10=-this.m10,this.m11=-this.m11)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY}},n.Slot=function(a,b,c){this.data=a,this.skeleton=b,this.bone=c,this.setToSetupPose()},n.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,setAttachment:function(a){this.attachment=a,this._attachmentTime=this.skeleton.time},setAttachmentTime:function(a){this._attachmentTime=this.skeleton.time-a},getAttachmentTime:function(){return this.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},n.Skin=function(a){this.name=a,this.attachments={}},n.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},n.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},n.Animation.prototype={apply:function(a,b,c){c&&0!=this.duration&&(b%=this.duration);for(var d=this.timelines,e=0,f=d.length;f>e;e++)d[e].apply(a,b,1)},mix:function(a,b,c,d){c&&0!=this.duration&&(b%=this.duration);for(var e=this.timelines,f=0,g=e.length;g>f;f++)e[f].apply(a,b,d)}},n.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(0==e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},n.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},n.Curves=function(a){this.curves=[],this.curves.length=6*(a-1)},n.Curves.prototype={setLinear:function(a){this.curves[6*a]=0},setStepped:function(a){this.curves[6*a]=-1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=6*a,r=this.curves;r[q]=b*i+m*j+o*h,r[q+1]=c*i+n*j+p*h,r[q+2]=m*k+o*l,r[q+3]=n*k+p*l,r[q+4]=o*l,r[q+5]=p*l},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=6*a,d=this.curves,e=d[c];if(!e)return b;if(-1==e)return 0;for(var f=d[c+1],g=d[c+2],h=d[c+3],i=d[c+4],j=d[c+5],k=e,l=f,m=8;;){if(k>=b){var n=k-e,o=l-f;return o+(l-o)*(b-n)/(k-n)}if(0==m)break;m--,e+=g,f+=h,g+=i,h+=j,k+=e,l+=f}return l+(1-l)*(b-k)/(1-k)}},n.RotateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=2*a},n.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-2]){for(var f=e.data.rotation+d[d.length-1]-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;return e.rotation+=f*c,void 0}var g=n.binarySearch(d,b,2),h=d[g-1],i=d[g],j=1-(b-i)/(d[g-2]-i);j=this.curves.getCurvePercent(g/2-1,j);for(var f=d[g+1]-h;f>180;)f-=360;for(;-180>f;)f+=360;for(f=e.data.rotation+(h+f*j)-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;e.rotation+=f*c}}},n.TranslateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.x+=(e.data.x+d[d.length-2]-e.x)*c,e.y+=(e.data.y+d[d.length-1]-e.y)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.x+=(e.data.x+g+(d[f+1]-g)*j-e.x)*c,e.y+=(e.data.y+h+(d[f+2]-h)*j-e.y)*c}}},n.ScaleTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.scaleX+=(e.data.scaleX-1+d[d.length-2]-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+d[d.length-1]-e.scaleY)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.scaleX+=(e.data.scaleX-1+g+(d[f+1]-g)*j-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+h+(d[f+2]-h)*j-e.scaleY)*c}}},n.ColorTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=5*a},n.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(c,d){c*=5,this.frames[c]=d,this.frames[c+1]=r,this.frames[c+2]=g,this.frames[c+3]=b,this.frames[c+4]=a},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-5]){var f=d.length-1;return e.r=d[f-3],e.g=d[f-2],e.b=d[f-1],e.a=d[f],void 0}var g=n.binarySearch(d,b,5),h=d[g-4],i=d[g-3],j=d[g-2],k=d[g-1],l=d[g],m=1-(b-l)/(d[g-5]-l);m=this.curves.getCurvePercent(g/5-1,m);var o=h+(d[g+1]-h)*m,p=i+(d[g+2]-i)*m,q=j+(d[g+3]-j)*m,r=k+(d[g+4]-k)*m;1>c?(e.r+=(o-e.r)*c,e.g+=(p-e.g)*c,e.b+=(q-e.b)*c,e.a+=(r-e.a)*c):(e.r=o,e.g=p,e.b=q,e.a=r)}}},n.AttachmentTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},n.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b){var c=this.frames;if(!(b=c[c.length-1]?c.length-1:n.binarySearch(c,b,1)-1;var e=this.attachmentNames[d];a.slots[this.slotIndex].setAttachment(e?a.getAttachmentBySlotIndex(this.slotIndex,e):null)}}},n.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.animations=[]},n.SkeletonData.prototype={defaultSkin:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},n.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,c=a.bones.length;c>b;b++){var d=a.bones[b],e=d.parent?this.bones[a.bones.indexOf(d.parent)]:null;this.bones.push(new n.Bone(d,e))}this.slots=[],this.drawOrder=[];for(var b=0,c=a.slots.length;c>b;b++){var f=a.slots[b],g=this.bones[a.bones.indexOf(f.boneData)],h=new n.Slot(f,this,g);this.slots.push(h),this.drawOrder.push(h)}},n.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateWorldTransform:function(){for(var a=this.flipX,b=this.flipY,c=this.bones,d=0,e=c.length;e>d;d++)c[d].updateWorldTransform(a,b)},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose()},setSlotsToSetupPose:function(){for(var a=this.slots,b=0,c=a.length;c>b;b++)a[b].setToSetupPose(b)},getRootBone:function(){return 0==this.bones.length?null:this.bones[0]},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a);if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){this.skin&&a&&a._attachAll(this,this.skin),this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.size;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachment(d,b),null==g))throw"Attachment not found: "+b+", for slot: "+a;return f.setAttachment(g),void 0}}throw"Slot not found: "+a},update:function(a){time+=a}},n.AttachmentType={region:0},n.RegionAttachment=function(){this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},n.RegionAttachment.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,c=-this.width/2*this.scaleX+this.regionOffsetX*a,d=-this.height/2*this.scaleY+this.regionOffsetY*b,e=c+this.regionWidth*a,f=d+this.regionHeight*b,g=this.rotation*Math.PI/180,h=Math.cos(g),i=Math.sin(g),j=c*h+this.x,k=c*i,l=d*h+this.y,m=d*i,n=e*h+this.x,o=e*i,p=f*h+this.y,q=f*i,r=this.offset;r[0]=j-m,r[1]=l+k,r[2]=j-q,r[3]=p+k,r[4]=n-q,r[5]=p+o,r[6]=n-m,r[7]=l+o},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},n.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},n.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=this.animationToMixTime[a.name+":"+b.name];return c?c:this.defaultMix}},n.AnimationState=function(a){this.data=a,this.queue=[]},n.AnimationState.prototype={current:null,previous:null,currentTime:0,previousTime:0,currentLoop:!1,previousLoop:!1,mixTime:0,mixDuration:0,update:function(a){if(this.currentTime+=a,this.previousTime+=a,this.mixTime+=a,this.queue.length>0){var b=this.queue[0];this.currentTime>=b.delay&&(this._setAnimation(b.animation,b.loop),this.queue.shift())}},apply:function(a){if(this.current)if(this.previous){this.previous.apply(a,this.previousTime,this.previousLoop);var b=this.mixTime/this.mixDuration;b>=1&&(b=1,this.previous=null),this.current.mix(a,this.currentTime,this.currentLoop,b)}else this.current.apply(a,this.currentTime,this.currentLoop)},clearAnimation:function(){this.previous=null,this.current=null,this.queue.length=0},_setAnimation:function(a,b){this.previous=null,a&&this.current&&(this.mixDuration=this.data.getMix(this.current,a),this.mixDuration>0&&(this.mixTime=0,this.previous=this.current,this.previousTime=this.currentTime,this.previousLoop=this.currentLoop)),this.current=a,this.currentLoop=b,this.currentTime=0},setAnimationByName:function(a,b){var c=this.data.skeletonData.findAnimation(a);if(!c)throw"Animation not found: "+a;this.setAnimation(c,b)},setAnimation:function(a,b){this.queue.length=0,this._setAnimation(a,b)},addAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;this.addAnimation(d,b,c)},addAnimation:function(a,b,c){var d={};if(d.animation=a,d.loop=b,!c||0>=c){var e=0==this.queue.length?this.current:this.queue[this.queue.length-1].animation;c=null!=e?e.duration-this.data.getMix(e,a)+(c||0):0}d.delay=c,this.queue.push(d)},isComplete:function(){return!this.current||this.currentTime>=this.current.duration}},n.SkeletonJson=function(a){this.attachmentLoader=a},n.SkeletonJson.prototype={scale:1,readSkeletonData:function(a){for(var b=new n.SkeletonData,c=a.bones,d=0,e=c.length;e>d;d++){var f=c[d],g=null;if(f.parent&&(g=b.findBone(f.parent),!g))throw"Parent bone not found: "+f.parent;var h=new n.BoneData(f.name,g);h.length=(f.length||0)*this.scale,h.x=(f.x||0)*this.scale,h.y=(f.y||0)*this.scale,h.rotation=f.rotation||0,h.scaleX=f.scaleX||1,h.scaleY=f.scaleY||1,b.bones.push(h)}for(var i=a.slots,d=0,e=i.length;e>d;d++){var j=i[d],h=b.findBone(j.bone); if(!h)throw"Slot bone not found: "+j.bone;var k=new n.SlotData(j.name,h),l=j.color;l&&(k.r=n.SkeletonJson.toColor(l,0),k.g=n.SkeletonJson.toColor(l,1),k.b=n.SkeletonJson.toColor(l,2),k.a=n.SkeletonJson.toColor(l,3)),k.attachmentName=j.attachment,b.slots.push(k)}var m=a.skins;for(var o in m)if(m.hasOwnProperty(o)){var p=m[o],q=new n.Skin(o);for(var r in p)if(p.hasOwnProperty(r)){var s=b.findSlotIndex(r),t=p[r];for(var u in t)if(t.hasOwnProperty(u)){var v=this.readAttachment(q,u,t[u]);null!=v&&q.addAttachment(s,u,v)}}b.skins.push(q),"default"==q.name&&(b.defaultSkin=q)}var w=a.animations;for(var x in w)w.hasOwnProperty(x)&&this.readAnimation(x,w[x],b);return b},readAttachment:function(a,b,c){b=c.name||b;var d=n.AttachmentType[c.type||"region"];if(d==n.AttachmentType.region){var e=new n.RegionAttachment;return e.x=(c.x||0)*this.scale,e.y=(c.y||0)*this.scale,e.scaleX=c.scaleX||1,e.scaleY=c.scaleY||1,e.rotation=c.rotation||0,e.width=(c.width||32)*this.scale,e.height=(c.height||32)*this.scale,e.updateOffset(),e.rendererObject={},e.rendererObject.name=b,e.rendererObject.scale={},e.rendererObject.scale.x=e.scaleX,e.rendererObject.scale.y=e.scaleY,e.rendererObject.rotation=-e.rotation*Math.PI/180,e}throw"Unknown attachment type: "+d},readAnimation:function(a,b,c){var d=[],e=0,f=b.bones;for(var g in f)if(f.hasOwnProperty(g)){var h=c.findBoneIndex(g);if(-1==h)throw"Bone not found: "+g;var i=f[g];for(var j in i)if(i.hasOwnProperty(j)){var k=i[j];if("rotate"==j){var l=new n.RotateTimeline(k.length);l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m,q.time,q.angle),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[2*l.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var l,r=1;"scale"==j?l=new n.ScaleTimeline(k.length):(l=new n.TranslateTimeline(k.length),r=this.scale),l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;l.setFrame(m,q.time,s,t),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[3*l.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var l=new n.ColorTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=n.SkeletonJson.toColor(y,0),A=n.SkeletonJson.toColor(y,1),B=n.SkeletonJson.toColor(y,2),C=n.SkeletonJson.toColor(y,3);l.setFrame(m,q.time,z,A,B,C),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[5*l.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var l=new n.AttachmentTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m++,q.time,q.name)}d.push(l),e=Math.max(e,l.frames[l.getFrameCount()-1])}}}c.animations.push(new n.Animation(a,d,e))}},n.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},n.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},n.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new n.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new n.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new n.AtlasPage,e.name=f,e.format=n.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=n.Atlas.TextureFilter[d[0]],e.magFilter=n.Atlas.TextureFilter[d[1]];var l=c.readValue();e.uWrap=n.Atlas.TextureWrap.clampToEdge,e.vWrap=n.Atlas.TextureWrap.clampToEdge,"x"==l?e.uWrap=n.Atlas.TextureWrap.repeat:"y"==l?e.vWrap=n.Atlas.TextureWrap.repeat:"xy"==l&&(e.uWrap=e.vWrap=n.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},n.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},n.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},n.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},n.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},n.AtlasPage=function(){},n.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},n.AtlasRegion=function(){},n.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},n.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},n.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},n.AtlasAttachmentLoader=function(a){this.atlas=a},n.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case n.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new n.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},n.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;h 0 ? filtersToApply : null; + pondContainer.filters = filtersToApply.length > 0 ? filtersToApply : null; for (var i = 0; i < fishs.length; i++) { @@ -250,5 +274,13 @@ +

+ + + + + +
+ diff --git a/pixi.sublime-workspace b/pixi.sublime-workspace index f3e23fa..ccae875 100644 --- a/pixi.sublime-workspace +++ b/pixi.sublime-workspace @@ -3,18 +3,74 @@ { "selected_items": [ + [ + "for", + "for for (…) {…}" + ], + [ + "filters", + "filtersSwitchs" + ], [ "fil", - "filter" + "filtersSwitchs" + ], + [ + "di", + "displacementMap" + ], + [ + "fis", + "fishId" + ], + [ + "po", + "pondContainer" + ], + [ + "an", + "anchor" + ], + [ + "fish", + "fishs" + ], + [ + "displ", + "displacementTexture" + ], + [ + "pix", + "pixelSize" + ], + [ + "pi", + "pixelSize" + ], + [ + "bg", + "bgFront" + ], + [ + "P", + "PixiShader" + ], + [ + "de", + "defaultShader" + ], + [ + "primi", + "primitiveShader" + ], + [ + "unif", + "uniforms" ], [ "pro", "prototype" ], - [ - "for", - "for for (…) {…}" - ], [ "blu", "blurX" @@ -60,82 +116,10 @@ "buffers": [ { - "file": "examples/example 16 - Displacement/index.html", + "file": "examples/example 15 - Filters/indexAll.html", "settings": { - "buffer_size": 4917, - "line_ending": "Unix" - } - }, - { - "file": "src/pixi/filters/GreyFilter.js", - "settings": - { - "buffer_size": 986, - "line_ending": "Unix" - } - }, - { - "file": "src/pixi/filters/DisplacementFilter.js", - "settings": - { - "buffer_size": 1856, - "line_ending": "Unix" - } - }, - { - "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", - "settings": - { - "buffer_size": 25077, - "line_ending": "Unix" - } - }, - { - "file": "src/pixi/textures/RenderTexture.js", - "settings": - { - "buffer_size": 6698, - "line_ending": "Unix" - } - }, - { - "file": "examples/example 15 - Filters/indexBlur.html", - "settings": - { - "buffer_size": 2162, - "line_ending": "Unix" - } - }, - { - "file": "src/pixi/filters/PixelateFilter.js", - "settings": - { - "buffer_size": 1597, - "line_ending": "Unix" - } - }, - { - "file": "src/pixi/renderers/webgl/WebGLFilterManager.js", - "settings": - { - "buffer_size": 12129, - "line_ending": "Unix" - } - }, - { - "file": "src/pixi/filters/InvertFilter.js", - "settings": - { - "buffer_size": 1038, - "line_ending": "Unix" - } - }, - { - "file": "src/pixi/filters/AbstractFilter.js", - "settings": - { - "buffer_size": 1168, + "buffer_size": 8200, "line_ending": "Unix" } } @@ -143,11 +127,11 @@ "build_system": "", "command_palette": { - "height": 0.0, + "height": 392.0, "selected_items": [ ], - "width": 0.0 + "width": 467.0 }, "console": { @@ -164,34 +148,68 @@ }, "file_history": [ + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/utils/Detector.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 15 - Filters/indexAll.html", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/text/Text.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLRenderer.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 13 - Graphics/indexLineTest.html", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/canvas/CanvasRenderer.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLShaders.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/PrimitiveShader.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/PixiShader.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/test/unit/renderers/CanvasRenderer.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/canvas/CanvasGraphics.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/CrossHatchFilter.js", "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/Gruntfile.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/SmartBlurFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/SepiaFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/ColorMatrixFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/BlurYFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/RGBSplitFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLRenderGroup.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/RBGSplitFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLGraphics.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/display/Stage.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 13 - Graphics/index.html", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 10 - Text/index.html", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 9 - Tiling Texture/index.html", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/BlurFilter.js", "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/BlurXFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/display/DisplayObjectContainer.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/test/unit/DisplayObjectContainer.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/InvertFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/GreyFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/BlurYFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/TwistFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/DotScreenFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/ColorStepFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 14 - Masking/index double mask.html", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 14 - Masking/index nested masks.html", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 14 - Masking/index.html", + "/Users/matgroves/Library/Application Support/Sublime Text 2/Packages/User/Preferences.sublime-settings", "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLFilterManager.js", "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 16 - Displacement/index.html", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/BlurFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLRenderGroup.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/display/DisplayObject.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/PixelateFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/AbstractFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 15 - Filters/indexDisplacement.html", "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/DisplacementFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/GreyFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/InvertFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/ColorMatrixFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/SepiaFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/InteractionManager.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/utils/EventTarget.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/display/DisplayObject.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/textures/BaseTexture.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/test/unit/Sprite.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/extras/TilingSprite.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 15 - Filters/indexBlur.html", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/SmartBlurFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/display/DisplayObjectContainer.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/test/unit/DisplayObjectContainer.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/StripShader.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLBatch.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/textures/RenderTexture.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/PixiStripShader.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/bin/pixi.dev.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/extras/CustomRenderable.js", "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/test/unit/DisplayObject.js", "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/SmartBlur.js", "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/filters/FilterManager.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/textures/RenderTexture.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/PixiShader.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 13 - Graphics/index.html", "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/primitives/Graphics.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLGraphics.js", "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 11 - RenderTexture/index.html", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 14 - Masking/index.html", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLShaders.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLRenderer.js", "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/test/unit/renderers/WebGLShaders.js", "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/core/Matrix.js", "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/docs/classes/RenderTexture.html", @@ -214,6 +232,42 @@ "case_sensitive": false, "find_history": [ + "displ", + "wordWrap", + "console.log", + "count", + "getAttribLocation", + "setT", + "clear", + "filterManager", + "center", + "angle", + "filter", + "renderSt", + "width", + "mapDimensions", + "flo", + "consol", + " \n", + "pad", + "shaderProgram", + "renderTilingSprite", + "sta", + "PIXI.currentShader", + "primitiveProgram", + "shaderProgram", + "setun", + "2f", + "projectionVector", + "vertexPositionAttribute", + "render", + "textureCoordAttribute", + "pop", + "Filter", + "pus", + "push", + "pushShader", + "colorAttribute", "consol", "BlurXFilter", "filter", @@ -306,23 +360,23 @@ "groups": [ { - "selected": 3, + "selected": 0, "sheets": [ { "buffer": 0, - "file": "examples/example 16 - Displacement/index.html", + "file": "examples/example 15 - Filters/indexAll.html", "settings": { - "buffer_size": 4917, + "buffer_size": 8200, "regions": { }, "selection": [ [ - 3159, - 3159 + 365, + 365 ] ], "settings": @@ -331,272 +385,10 @@ "translate_tabs_to_spaces": false }, "translation.x": 0.0, - "translation.y": 1599.0, - "zoom_level": 1.0 - }, - "type": "text" - }, - { - "buffer": 1, - "file": "src/pixi/filters/GreyFilter.js", - "settings": - { - "buffer_size": 986, - "regions": - { - }, - "selection": - [ - [ - 662, - 662 - ], - [ - 738, - 738 - ], - [ - 778, - 778 - ] - ], - "settings": - { - "syntax": "Packages/JavaScript/JavaScript.tmLanguage" - }, - "translation.x": 0.0, "translation.y": 0.0, "zoom_level": 1.0 }, "type": "text" - }, - { - "buffer": 2, - "file": "src/pixi/filters/DisplacementFilter.js", - "settings": - { - "buffer_size": 1856, - "regions": - { - }, - "selection": - [ - [ - 1271, - 1271 - ], - [ - 1355, - 1355 - ], - [ - 1403, - 1403 - ] - ], - "settings": - { - "syntax": "Packages/JavaScript/JavaScript.tmLanguage" - }, - "translation.x": 0.0, - "translation.y": 159.0, - "zoom_level": 1.0 - }, - "type": "text" - }, - { - "buffer": 3, - "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", - "settings": - { - "buffer_size": 25077, - "regions": - { - }, - "selection": - [ - [ - 4449, - 4449 - ] - ], - "settings": - { - "syntax": "Packages/JavaScript/JavaScript.tmLanguage", - "translate_tabs_to_spaces": false - }, - "translation.x": 0.0, - "translation.y": 3015.0, - "zoom_level": 1.0 - }, - "type": "text" - }, - { - "buffer": 4, - "file": "src/pixi/textures/RenderTexture.js", - "settings": - { - "buffer_size": 6698, - "regions": - { - }, - "selection": - [ - [ - 5441, - 5455 - ] - ], - "settings": - { - "syntax": "Packages/JavaScript/JavaScript.tmLanguage", - "translate_tabs_to_spaces": false - }, - "translation.x": 0.0, - "translation.y": 2750.0, - "zoom_level": 1.0 - }, - "type": "text" - }, - { - "buffer": 5, - "file": "examples/example 15 - Filters/indexBlur.html", - "settings": - { - "buffer_size": 2162, - "regions": - { - }, - "selection": - [ - [ - 1657, - 1657 - ] - ], - "settings": - { - "syntax": "Packages/HTML/HTML.tmLanguage", - "translate_tabs_to_spaces": false - }, - "translation.x": 0.0, - "translation.y": 702.0, - "zoom_level": 1.0 - }, - "type": "text" - }, - { - "buffer": 6, - "file": "src/pixi/filters/PixelateFilter.js", - "settings": - { - "buffer_size": 1597, - "regions": - { - }, - "selection": - [ - [ - 664, - 664 - ] - ], - "settings": - { - "syntax": "Packages/JavaScript/JavaScript.tmLanguage" - }, - "translation.x": 0.0, - "translation.y": 74.0, - "zoom_level": 1.0 - }, - "type": "text" - }, - { - "buffer": 7, - "file": "src/pixi/renderers/webgl/WebGLFilterManager.js", - "settings": - { - "buffer_size": 12129, - "regions": - { - }, - "selection": - [ - [ - 3743, - 3743 - ] - ], - "settings": - { - "syntax": "Packages/JavaScript/JavaScript.tmLanguage", - "translate_tabs_to_spaces": false - }, - "translation.x": 0.0, - "translation.y": 2171.0, - "zoom_level": 1.0 - }, - "type": "text" - }, - { - "buffer": 8, - "file": "src/pixi/filters/InvertFilter.js", - "settings": - { - "buffer_size": 1038, - "regions": - { - }, - "selection": - [ - [ - 703, - 703 - ], - [ - 781, - 781 - ], - [ - 823, - 823 - ] - ], - "settings": - { - "syntax": "Packages/JavaScript/JavaScript.tmLanguage" - }, - "translation.x": 0.0, - "translation.y": 0.0, - "zoom_level": 1.0 - }, - "type": "text" - }, - { - "buffer": 9, - "file": "src/pixi/filters/AbstractFilter.js", - "settings": - { - "buffer_size": 1168, - "regions": - { - }, - "selection": - [ - [ - 980, - 982 - ] - ], - "settings": - { - "syntax": "Packages/JavaScript/JavaScript.tmLanguage" - }, - "translation.x": 0.0, - "translation.y": 74.0, - "zoom_level": 1.0 - }, - "type": "text" } ] } @@ -642,10 +434,170 @@ "height": 0.0, "selected_items": [ + [ + "indexall", + "examples/example 15 - Filters/indexAll.html" + ], + [ + "dete", + "src/pixi/utils/Detector.js" + ], + [ + "webglren", + "src/pixi/renderers/webgl/WebGLRenderGroup.js" + ], + [ + "rgb", + "src/pixi/filters/RGBSplitFilter.js" + ], + [ + "grun", + "Gruntfile.js" + ], + [ + "crossha", + "src/pixi/filters/CrossHatchFilter.js" + ], + [ + "text", + "src/pixi/text/Text.js" + ], + [ + "webglgr", + "src/pixi/renderers/webgl/WebGLGraphics.js" + ], + [ + "canvas", + "src/pixi/renderers/canvas/CanvasGraphics.js" + ], + [ + "pixisha", + "src/pixi/renderers/webgl/PixiShader.js" + ], + [ + "sta", + "src/pixi/display/Stage.js" + ], + [ + "ind", + "examples/example 13 - Graphics/index.html" + ], + [ + "webglgrap", + "src/pixi/renderers/webgl/WebGLGraphics.js" + ], + [ + "indexlinete", + "examples/example 13 - Graphics/indexLineTest.html" + ], + [ + "detec", + "src/pixi/utils/Detector.js" + ], + [ + "index", + "examples/example 10 - Text/index.html" + ], + [ + "index.html", + "examples/example 9 - Tiling Texture/index.html" + ], + [ + "tex", + "src/pixi/text/Text.js" + ], + [ + "indexnest", + "examples/example 14 - Masking/index nested masks.html" + ], + [ + "indexdouble", + "examples/example 14 - Masking/index double mask.html" + ], + [ + "filterma", + "src/pixi/renderers/webgl/WebGLFilterManager.js" + ], + [ + "bl", + "src/pixi/filters/BlurXFilter.js" + ], + [ + "blurfi", + "src/pixi/filters/BlurFilter.js" + ], + [ + "indexa", + "examples/example 15 - Filters/indexAll.html" + ], + [ + "interac", + "src/pixi/InteractionManager.js" + ], + [ + "even", + "src/pixi/utils/EventTarget.js" + ], + [ + "sprite", + "test/unit/Sprite.js" + ], + [ + "base", + "src/pixi/textures/BaseTexture.js" + ], [ "webglr", "src/pixi/renderers/webgl/WebGLRenderGroup.js" ], + [ + "displa", + "src/pixi/filters/DisplacementFilter.js" + ], + [ + "tilings", + "src/pixi/extras/TilingSprite.js" + ], + [ + "indexbl", + "examples/example 15 - Filters/indexBlur.html" + ], + [ + "indexdis", + "examples/example 15 - Filters/indexDisplacement.html" + ], + [ + "displayobjectcon", + "src/pixi/display/DisplayObjectContainer.js" + ], + [ + "inde", + "examples/example 9 - Tiling Texture/index.html" + ], + [ + "grunt", + "Gruntfile.js" + ], + [ + "rendert", + "src/pixi/textures/RenderTexture.js" + ], + [ + "custom", + "src/pixi/extras/CustomRenderable.js" + ], + [ + "webgls", + "src/pixi/renderers/webgl/WebGLShaders.js" + ], + [ + "webglsh", + "src/pixi/renderers/webgl/WebGLShaders.js" + ], + [ + "pixish", + "src/pixi/renderers/webgl/PixiShader.js" + ], [ "displayobjectco", "src/pixi/display/DisplayObjectContainer.js" @@ -674,46 +626,14 @@ "greyfil", "src/pixi/filters/GreyFilter.js" ], - [ - "grun", - "Gruntfile.js" - ], [ "webgle", "src/pixi/renderers/webgl/WebGLRenderGroup.js" ], - [ - "displa", - "src/pixi/display/DisplayObject.js" - ], - [ - "index", - "examples/example 16 - Displacement/index.html" - ], - [ - "ind", - "examples/example 13 - Graphics/index.html" - ], - [ - "grunt", - "Gruntfile.js" - ], - [ - "webglgr", - "src/pixi/renderers/webgl/WebGLGraphics.js" - ], - [ - "webglsh", - "src/pixi/renderers/webgl/WebGLShaders.js" - ], [ "webglsha", "test/unit/renderers/WebGLShaders.js" ], - [ - "webglren", - "src/pixi/renderers/webgl/WebGLRenderer.js" - ], [ "webgl", "src/pixi/renderers/webgl/WebGLShaders.js" @@ -726,18 +646,10 @@ "index.", "examples/example 13 - Graphics/index.html" ], - [ - "inde", - "examples/example 14 - Masking/index.html" - ], [ "rendertexture", "src/pixi/textures/RenderTexture.js" ], - [ - "rendert", - "docs/classes/RenderTexture.html" - ], [ "matrix", "src/pixi/core/Matrix.js" diff --git a/src/pixi/filters/CrossHatchFilter.js b/src/pixi/filters/CrossHatchFilter.js new file mode 100644 index 0000000..cd050cb --- /dev/null +++ b/src/pixi/filters/CrossHatchFilter.js @@ -0,0 +1,69 @@ +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + + +PIXI.CrossHatchFilter = function() +{ + PIXI.AbstractFilter.call( this ); + + this.passes = [this]; + + // set the uniforms + this.uniforms = { + blur: {type: 'f', value: 1/512}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float blur;", + "uniform sampler2D uSampler;", + "void main(void) {", + + + " float lum = length(texture2D(uSampler, vTextureCoord.xy).rgb);", + " ", + " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);", + " ", + " if (lum < 1.00) {", + " if (mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0) {", + " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);", + " }", + " }", + " ", + " if (lum < 0.75) {", + " if (mod(gl_FragCoord.x - gl_FragCoord.y, 10.0) == 0.0) {", + " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);", + " }", + " }", + " ", + " if (lum < 0.50) {", + " if (mod(gl_FragCoord.x + gl_FragCoord.y - 5.0, 10.0) == 0.0) {", + " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);", + " }", + " }", + " ", + " if (lum < 0.3) {", + " if (mod(gl_FragCoord.x - gl_FragCoord.y - 5.0, 10.0) == 0.0) {", + " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);", + " }", + " }", + "}" + ]; +} + +PIXI.CrossHatchFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); +PIXI.CrossHatchFilter.prototype.constructor = PIXI.BlurYFilter; + +Object.defineProperty(PIXI.CrossHatchFilter.prototype, 'blur', { + get: function() { + return this.uniforms.blur.value / (1/7000); + }, + set: function(value) { + //this.padding = value; + this.uniforms.blur.value = (1/7000) * value; + } +}); diff --git a/src/pixi/filters/RGBSplitFilter.js b/src/pixi/filters/RGBSplitFilter.js new file mode 100644 index 0000000..5303d64 --- /dev/null +++ b/src/pixi/filters/RGBSplitFilter.js @@ -0,0 +1,50 @@ +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + + +PIXI.RGBSplitFilter = function() +{ + PIXI.AbstractFilter.call( this ); + + this.passes = [this]; + + // set the uniforms + this.uniforms = { + red: {type: 'f2', value: {x:20, y:20}}, + green: {type: 'f2', value: {x:-20, y:20}}, + blue: {type: 'f2', value: {x:20, y:-20}}, + dimensions: {type: 'f4', value:[0,0,0,0]} + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform vec2 red;", + "uniform vec2 green;", + "uniform vec2 blue;", + "uniform vec4 dimensions;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor.r = texture2D(uSampler, vTextureCoord + red/dimensions.xy).r;", + "gl_FragColor.g = texture2D(uSampler, vTextureCoord + green/dimensions.xy).g;", + "gl_FragColor.b = texture2D(uSampler, vTextureCoord + blue/dimensions.xy).b;", + "gl_FragColor.a = texture2D(uSampler, vTextureCoord).a;", + "}" + ]; +} + +PIXI.RGBSplitFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); +PIXI.RGBSplitFilter.prototype.constructor = PIXI.RGBSplitFilter; + +Object.defineProperty(PIXI.RGBSplitFilter.prototype, 'angle', { + get: function() { + return this.uniforms.blur.value / (1/7000); + }, + set: function(value) { + //this.padding = value; + this.uniforms.blur.value = (1/7000) * value; + } +}); diff --git a/src/pixi/renderers/webgl/WebGLFilterManager.js b/src/pixi/renderers/webgl/WebGLFilterManager.js index 01c2bd7..f3e9027 100644 --- a/src/pixi/renderers/webgl/WebGLFilterManager.js +++ b/src/pixi/renderers/webgl/WebGLFilterManager.js @@ -3,8 +3,10 @@ */ -PIXI.WebGLFilterManager = function() +PIXI.WebGLFilterManager = function(transparent) { + this.transparent = transparent; + this.filterStack = []; this.texturePool = []; @@ -195,7 +197,7 @@ PIXI.WebGLFilterManager.prototype.popFilter = function() // time to render the filters texture to the previous scene if(this.filterStack.length === 0) { - gl.colorMask(true, true, true, this.buffer); + gl.colorMask(true, true, true, this.transparent); } else { diff --git a/src/pixi/renderers/webgl/WebGLRenderGroup.js b/src/pixi/renderers/webgl/WebGLRenderGroup.js index b0d8d6c..7a52a9f 100644 --- a/src/pixi/renderers/webgl/WebGLRenderGroup.js +++ b/src/pixi/renderers/webgl/WebGLRenderGroup.js @@ -15,16 +15,18 @@ * @contructor * @param gl {WebGLContext} An instance of the webGL context */ -PIXI.WebGLRenderGroup = function(gl) +PIXI.WebGLRenderGroup = function(gl, transparent) { this.gl = gl; this.root; this.backgroundColor; + this.transparent = transparent == undefined ? true : transparent; + this.batchs = []; this.toRemove = []; - - this.filterManager = new PIXI.WebGLFilterManager(); + console.log(this.transparent) + this.filterManager = new PIXI.WebGLFilterManager(this.transparent); } // constructor diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js index 356c033..e11cd44 100644 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ b/src/pixi/renderers/webgl/WebGLRenderer.js @@ -94,8 +94,8 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) //PIXI.pushShader(PIXI.defaultShader); - this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); - + this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl, this.transparent); + // this.stageRenderGroup. = this.transparent } // constructor From 000df6b33b96d519465b4f4f65108d693fb6508f Mon Sep 17 00:00:00 2001 From: Chad Engler Date: Wed, 6 Nov 2013 06:28:03 -0800 Subject: [PATCH 74/96] remove sublime-* files --- pixi.sublime-project | 8 - pixi.sublime-workspace | 678 ----------------------------------------- 2 files changed, 686 deletions(-) delete mode 100644 pixi.sublime-project delete mode 100644 pixi.sublime-workspace diff --git a/pixi.sublime-project b/pixi.sublime-project deleted file mode 100644 index d834dea..0000000 --- a/pixi.sublime-project +++ /dev/null @@ -1,8 +0,0 @@ -{ - "folders": - [ - { - "path": "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js" - } - ] -} diff --git a/pixi.sublime-workspace b/pixi.sublime-workspace deleted file mode 100644 index ccae875..0000000 --- a/pixi.sublime-workspace +++ /dev/null @@ -1,678 +0,0 @@ -{ - "auto_complete": - { - "selected_items": - [ - [ - "for", - "for for (…) {…}" - ], - [ - "filters", - "filtersSwitchs" - ], - [ - "fil", - "filtersSwitchs" - ], - [ - "di", - "displacementMap" - ], - [ - "fis", - "fishId" - ], - [ - "po", - "pondContainer" - ], - [ - "an", - "anchor" - ], - [ - "fish", - "fishs" - ], - [ - "displ", - "displacementTexture" - ], - [ - "pix", - "pixelSize" - ], - [ - "pi", - "pixelSize" - ], - [ - "bg", - "bgFront" - ], - [ - "P", - "PixiShader" - ], - [ - "de", - "defaultShader" - ], - [ - "primi", - "primitiveShader" - ], - [ - "unif", - "uniforms" - ], - [ - "pro", - "prototype" - ], - [ - "blu", - "blurX" - ], - [ - "Blu", - "BlurXFilter" - ], - [ - "appl", - "applyFilterPass" - ], - [ - "ou", - "outputTexture" - ], - [ - "filte", - "filterBlock" - ], - [ - "We", - "WebGLGraphics" - ], - [ - "max", - "maxY" - ], - [ - "min", - "minY" - ], - [ - "re", - "rectangle" - ], - [ - "rend", - "renderable" - ] - ] - }, - "buffers": - [ - { - "file": "examples/example 15 - Filters/indexAll.html", - "settings": - { - "buffer_size": 8200, - "line_ending": "Unix" - } - } - ], - "build_system": "", - "command_palette": - { - "height": 392.0, - "selected_items": - [ - ], - "width": 467.0 - }, - "console": - { - "height": 139.0 - }, - "distraction_free": - { - "menu_visible": true, - "show_minimap": false, - "show_open_files": false, - "show_tabs": false, - "side_bar_visible": false, - "status_bar_visible": false - }, - "file_history": - [ - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/utils/Detector.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 15 - Filters/indexAll.html", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/text/Text.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLRenderer.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 13 - Graphics/indexLineTest.html", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/canvas/CanvasRenderer.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLShaders.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/PrimitiveShader.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/PixiShader.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/test/unit/renderers/CanvasRenderer.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/canvas/CanvasGraphics.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/CrossHatchFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/Gruntfile.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/RGBSplitFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLRenderGroup.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/RBGSplitFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLGraphics.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/display/Stage.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 13 - Graphics/index.html", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 10 - Text/index.html", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 9 - Tiling Texture/index.html", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/BlurFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/BlurXFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/InvertFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/GreyFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/BlurYFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/TwistFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/DotScreenFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/ColorStepFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 14 - Masking/index double mask.html", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 14 - Masking/index nested masks.html", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 14 - Masking/index.html", - "/Users/matgroves/Library/Application Support/Sublime Text 2/Packages/User/Preferences.sublime-settings", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLFilterManager.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 16 - Displacement/index.html", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/PixelateFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/AbstractFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 15 - Filters/indexDisplacement.html", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/DisplacementFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/ColorMatrixFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/SepiaFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/InteractionManager.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/utils/EventTarget.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/display/DisplayObject.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/textures/BaseTexture.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/test/unit/Sprite.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/extras/TilingSprite.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 15 - Filters/indexBlur.html", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/SmartBlurFilter.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/display/DisplayObjectContainer.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/test/unit/DisplayObjectContainer.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/StripShader.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLBatch.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/textures/RenderTexture.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/PixiStripShader.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/bin/pixi.dev.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/extras/CustomRenderable.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/test/unit/DisplayObject.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/SmartBlur.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/filters/FilterManager.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/primitives/Graphics.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 11 - RenderTexture/index.html", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/test/unit/renderers/WebGLShaders.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/core/Matrix.js", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/docs/classes/RenderTexture.html", - "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/core/Ellipse.js" - ], - "find": - { - "height": 35.0 - }, - "find_in_files": - { - "height": 0.0, - "where_history": - [ - "" - ] - }, - "find_state": - { - "case_sensitive": false, - "find_history": - [ - "displ", - "wordWrap", - "console.log", - "count", - "getAttribLocation", - "setT", - "clear", - "filterManager", - "center", - "angle", - "filter", - "renderSt", - "width", - "mapDimensions", - "flo", - "consol", - " \n", - "pad", - "shaderProgram", - "renderTilingSprite", - "sta", - "PIXI.currentShader", - "primitiveProgram", - "shaderProgram", - "setun", - "2f", - "projectionVector", - "vertexPositionAttribute", - "render", - "textureCoordAttribute", - "pop", - "Filter", - "pus", - "push", - "pushShader", - "colorAttribute", - "consol", - "BlurXFilter", - "filter", - "blurAmount", - " \n", - "console", - " \n", - "/˚˚/ console.log(PIXI.frameBufferPool.length);\n ", - "cons", - "console", - "pand", - "colorMatrix", - "FilterTexture", - "minY", - "minX", - "uvBuffer", - " \n", - "console", - "data", - "console", - "applyFilterPass", - " \n", - "filterA", - " \n", - "filters", - "render", - "filter", - "Filter", - "filter", - "Filter", - "filter", - " //", - " \n", - "\n ", - " \n", - "pass", - "RTScene", - "vTexCoord", - "blurSize", - "FilterManager", - "i", - "dirty", - "console", - " ", - "PIXI.projection", - "\n ", - "h1", - "h0", - "w1", - "w0", - "TODO", - "radius", - "Things", - "radius", - " ", - "t", - "cle", - "this", - "PIXI", - ");\n", - "\n", - " \n", - " \n", - "console", - " \n", - "this", - "this.renderSpecial(renderable, projection);\nthis.renderSpecial(renderable, projection);\nrenderSpecial", - "this.renderSpecial(renderable, projection);", - "off", - "atlas", - "spineboy.atlas", - "spineboy.atla", - "spineboy.png", - "floor", - "groun" - ], - "highlight": true, - "in_selection": false, - "preserve_case": false, - "regex": false, - "replace_history": - [ - ], - "reverse": false, - "show_context": true, - "use_buffer2": true, - "whole_word": false, - "wrap": true - }, - "groups": - [ - { - "selected": 0, - "sheets": - [ - { - "buffer": 0, - "file": "examples/example 15 - Filters/indexAll.html", - "settings": - { - "buffer_size": 8200, - "regions": - { - }, - "selection": - [ - [ - 365, - 365 - ] - ], - "settings": - { - "syntax": "Packages/HTML/HTML.tmLanguage", - "translate_tabs_to_spaces": false - }, - "translation.x": 0.0, - "translation.y": 0.0, - "zoom_level": 1.0 - }, - "type": "text" - } - ] - } - ], - "incremental_find": - { - "height": 0.0 - }, - "input": - { - "height": 33.0 - }, - "layout": - { - "cells": - [ - [ - 0, - 0, - 1, - 1 - ] - ], - "cols": - [ - 0.0, - 1.0 - ], - "rows": - [ - 0.0, - 1.0 - ] - }, - "menu_visible": true, - "replace": - { - "height": 0.0 - }, - "save_all_on_build": true, - "select_file": - { - "height": 0.0, - "selected_items": - [ - [ - "indexall", - "examples/example 15 - Filters/indexAll.html" - ], - [ - "dete", - "src/pixi/utils/Detector.js" - ], - [ - "webglren", - "src/pixi/renderers/webgl/WebGLRenderGroup.js" - ], - [ - "rgb", - "src/pixi/filters/RGBSplitFilter.js" - ], - [ - "grun", - "Gruntfile.js" - ], - [ - "crossha", - "src/pixi/filters/CrossHatchFilter.js" - ], - [ - "text", - "src/pixi/text/Text.js" - ], - [ - "webglgr", - "src/pixi/renderers/webgl/WebGLGraphics.js" - ], - [ - "canvas", - "src/pixi/renderers/canvas/CanvasGraphics.js" - ], - [ - "pixisha", - "src/pixi/renderers/webgl/PixiShader.js" - ], - [ - "sta", - "src/pixi/display/Stage.js" - ], - [ - "ind", - "examples/example 13 - Graphics/index.html" - ], - [ - "webglgrap", - "src/pixi/renderers/webgl/WebGLGraphics.js" - ], - [ - "indexlinete", - "examples/example 13 - Graphics/indexLineTest.html" - ], - [ - "detec", - "src/pixi/utils/Detector.js" - ], - [ - "index", - "examples/example 10 - Text/index.html" - ], - [ - "index.html", - "examples/example 9 - Tiling Texture/index.html" - ], - [ - "tex", - "src/pixi/text/Text.js" - ], - [ - "indexnest", - "examples/example 14 - Masking/index nested masks.html" - ], - [ - "indexdouble", - "examples/example 14 - Masking/index double mask.html" - ], - [ - "filterma", - "src/pixi/renderers/webgl/WebGLFilterManager.js" - ], - [ - "bl", - "src/pixi/filters/BlurXFilter.js" - ], - [ - "blurfi", - "src/pixi/filters/BlurFilter.js" - ], - [ - "indexa", - "examples/example 15 - Filters/indexAll.html" - ], - [ - "interac", - "src/pixi/InteractionManager.js" - ], - [ - "even", - "src/pixi/utils/EventTarget.js" - ], - [ - "sprite", - "test/unit/Sprite.js" - ], - [ - "base", - "src/pixi/textures/BaseTexture.js" - ], - [ - "webglr", - "src/pixi/renderers/webgl/WebGLRenderGroup.js" - ], - [ - "displa", - "src/pixi/filters/DisplacementFilter.js" - ], - [ - "tilings", - "src/pixi/extras/TilingSprite.js" - ], - [ - "indexbl", - "examples/example 15 - Filters/indexBlur.html" - ], - [ - "indexdis", - "examples/example 15 - Filters/indexDisplacement.html" - ], - [ - "displayobjectcon", - "src/pixi/display/DisplayObjectContainer.js" - ], - [ - "inde", - "examples/example 9 - Tiling Texture/index.html" - ], - [ - "grunt", - "Gruntfile.js" - ], - [ - "rendert", - "src/pixi/textures/RenderTexture.js" - ], - [ - "custom", - "src/pixi/extras/CustomRenderable.js" - ], - [ - "webgls", - "src/pixi/renderers/webgl/WebGLShaders.js" - ], - [ - "webglsh", - "src/pixi/renderers/webgl/WebGLShaders.js" - ], - [ - "pixish", - "src/pixi/renderers/webgl/PixiShader.js" - ], - [ - "displayobjectco", - "src/pixi/display/DisplayObjectContainer.js" - ], - [ - "displ", - "test/unit/DisplayObjectContainer.js" - ], - [ - "pixela", - "src/pixi/filters/PixelateFilter.js" - ], - [ - "indexblur", - "examples/example 15 - Filters/indexBlur.html" - ], - [ - "render", - "src/pixi/textures/RenderTexture.js" - ], - [ - "webglrend", - "src/pixi/renderers/webgl/WebGLRenderGroup.js" - ], - [ - "greyfil", - "src/pixi/filters/GreyFilter.js" - ], - [ - "webgle", - "src/pixi/renderers/webgl/WebGLRenderGroup.js" - ], - [ - "webglsha", - "test/unit/renderers/WebGLShaders.js" - ], - [ - "webgl", - "src/pixi/renderers/webgl/WebGLShaders.js" - ], - [ - "grap", - "src/pixi/primitives/Graphics.js" - ], - [ - "index.", - "examples/example 13 - Graphics/index.html" - ], - [ - "rendertexture", - "src/pixi/textures/RenderTexture.js" - ], - [ - "matrix", - "src/pixi/core/Matrix.js" - ] - ], - "width": 0.0 - }, - "select_project": - { - "height": 500.0, - "selected_items": - [ - [ - "", - "/Users/matgroves/Dropbox/Development/html/workspace/Project Awesome/js/moments.sublime-project" - ] - ], - "width": 380.0 - }, - "show_minimap": true, - "show_open_files": false, - "show_tabs": true, - "side_bar_visible": true, - "side_bar_width": 229.0, - "status_bar_visible": true -} From 414d5c5be4150988dfd416c56c602ab368ade01d Mon Sep 17 00:00:00 2001 From: Chad Engler Date: Wed, 6 Nov 2013 06:29:11 -0800 Subject: [PATCH 75/96] ignore sublime text files --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 12e1b62..7395838 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules .DS_Store -.project \ No newline at end of file +.project +*.sublime-* \ No newline at end of file From ce43cfdb5c6b91f9d091ef45b0fef22bc6800a3f Mon Sep 17 00:00:00 2001 From: Chad Engler Date: Wed, 6 Nov 2013 09:41:29 -0800 Subject: [PATCH 76/96] Change grey to gray, silly English... --- src/pixi/filters/ColorStepFilter.js | 2 +- .../filters/{GreyFilter.js => GrayFilter.js} | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) rename src/pixi/filters/{GreyFilter.js => GrayFilter.js} (59%) diff --git a/src/pixi/filters/ColorStepFilter.js b/src/pixi/filters/ColorStepFilter.js index ebf040b..d891db8 100644 --- a/src/pixi/filters/ColorStepFilter.js +++ b/src/pixi/filters/ColorStepFilter.js @@ -6,7 +6,7 @@ /** * * This turns your displayObjects to black and white. - * @class GreyFilter + * @class ColorStepFilter * @contructor */ PIXI.ColorStepFilter = function() diff --git a/src/pixi/filters/GreyFilter.js b/src/pixi/filters/GrayFilter.js similarity index 59% rename from src/pixi/filters/GreyFilter.js rename to src/pixi/filters/GrayFilter.js index d182975..a39888f 100644 --- a/src/pixi/filters/GreyFilter.js +++ b/src/pixi/filters/GrayFilter.js @@ -6,10 +6,10 @@ /** * * This turns your displayObjects to black and white. - * @class GreyFilter + * @class GrayFilter * @contructor */ -PIXI.GreyFilter = function() +PIXI.GrayFilter = function() { PIXI.AbstractFilter.call( this ); @@ -17,7 +17,7 @@ PIXI.GreyFilter = function() // set the uniforms this.uniforms = { - grey: {type: 'f', value: 1}, + gray: {type: 'f', value: 1}, }; this.fragmentSrc = [ @@ -25,27 +25,27 @@ PIXI.GreyFilter = function() "varying vec2 vTextureCoord;", "varying float vColor;", "uniform sampler2D uSampler;", - "uniform float grey;", + "uniform float gray;", "void main(void) {", "gl_FragColor = texture2D(uSampler, vTextureCoord);", - "gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), grey);", + "gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), gray);", "gl_FragColor = gl_FragColor * vColor;", "}" ]; } -PIXI.GreyFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); -PIXI.GreyFilter.prototype.constructor = PIXI.GreyFilter; +PIXI.GrayFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); +PIXI.GrayFilter.prototype.constructor = PIXI.GrayFilter; /** -The strength of the grey. 1 will make the object black and white, 0 will make the object its normal color -@property grey +The strength of the gray. 1 will make the object black and white, 0 will make the object its normal color +@property gray */ -Object.defineProperty(PIXI.GreyFilter.prototype, 'grey', { +Object.defineProperty(PIXI.GrayFilter.prototype, 'gray', { get: function() { - return this.uniforms.grey.value; + return this.uniforms.gray.value; }, set: function(value) { - this.uniforms.grey.value = value; + this.uniforms.gray.value = value; } }); From d7ce7616089a759d0f318a79a8c791520975fc1b Mon Sep 17 00:00:00 2001 From: Chad Engler Date: Sun, 10 Nov 2013 09:13:59 -0800 Subject: [PATCH 77/96] Manually merge #400 --- src/pixi/loaders/AssetLoader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pixi/loaders/AssetLoader.js b/src/pixi/loaders/AssetLoader.js index 02e02a9..57c4e8a 100644 --- a/src/pixi/loaders/AssetLoader.js +++ b/src/pixi/loaders/AssetLoader.js @@ -85,7 +85,7 @@ PIXI.AssetLoader.prototype.load = function() for (var i=0; i < this.assetURLs.length; i++) { var fileName = this.assetURLs[i]; - var fileType = fileName.split(".").pop().toLowerCase(); + var fileType = fileName.split("?").shift().split(".").pop().toLowerCase(); var loaderClass = this.loadersByType[fileType]; if(!loaderClass) From 49fff52fc85a7a01480486dfbfbfcb8cb73da108 Mon Sep 17 00:00:00 2001 From: photonstorm Date: Wed, 20 Nov 2013 16:19:25 +0000 Subject: [PATCH 78/96] Updated PixiShader to use standard uniform naming conventions (1f, 2f, 2fv, etc). Added support for multiple sampler2D calls, allowing multi-texture shaders. Added support for Linear, Repeat, Nearest, Audio and Keyboard textures. Updated all the examples to use the new uniform naming convention. Updated Gruntfile to use the renamed GrayFilter and fixed indexAll in Example 15 to use the GrayFilter as well. --- Gruntfile.js | 2 +- bin/pixi.dev.js | 24823 +++++++++--------- bin/pixi.js | 12 +- examples/example 15 - Filters/indexAll.html | 16 +- src/pixi/display/DisplayObject.js | 2 +- src/pixi/filters/BlurXFilter.js | 2 +- src/pixi/filters/BlurYFilter.js | 2 +- src/pixi/filters/ColorStepFilter.js | 2 +- src/pixi/filters/CrossHatchFilter.js | 2 +- src/pixi/filters/DisplacementFilter.js | 8 +- src/pixi/filters/DotScreenFilter.js | 6 +- src/pixi/filters/GrayFilter.js | 2 +- src/pixi/filters/InvertFilter.js | 2 +- src/pixi/filters/PixelateFilter.js | 6 +- src/pixi/filters/RGBSplitFilter.js | 8 +- src/pixi/filters/SepiaFilter.js | 2 +- src/pixi/filters/SmartBlurFilter.js | 2 +- src/pixi/filters/TwistFilter.js | 6 +- src/pixi/renderers/webgl/PixiShader.js | 415 +- 19 files changed, 12914 insertions(+), 12406 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index cc634ab..576df8e 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -60,7 +60,7 @@ module.exports = function(grunt) { '<%= dirs.src %>/loaders/SpineLoader.js', '<%= dirs.src %>/filters/AbstractFilter.js', '<%= dirs.src %>/filters/ColorMatrixFilter.js', - '<%= dirs.src %>/filters/GreyFilter.js', + '<%= dirs.src %>/filters/GrayFilter.js', '<%= dirs.src %>/filters/DisplacementFilter.js', '<%= dirs.src %>/filters/PixelateFilter.js', '<%= dirs.src %>/filters/BlurXFilter.js', diff --git a/bin/pixi.dev.js b/bin/pixi.dev.js index 21b0257..1e11684 100644 --- a/bin/pixi.dev.js +++ b/bin/pixi.dev.js @@ -1,3 +1,14 @@ +/** + * @license + * Pixi.JS - v1.3.0 + * Copyright (c) 2012, Mat Groves + * http://goodboydigital.com/ + * + * Compiled: 2013-11-20 + * + * Pixi.JS is licensed under the MIT License. + * http://www.opensource.org/licenses/mit-license.php + */ /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -5,12285 +16,12533 @@ (function(){ var root = this; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * @module PIXI - */ -var PIXI = PIXI || {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The Point object represents a location in a two-dimensional coordinate system, where x represents the horizontal axis and y represents the vertical axis. - * - * @class Point - * @constructor - * @param x {Number} position of the point - * @param y {Number} position of the point - */ -PIXI.Point = function(x, y) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; -} - -/** - * Creates a clone of this point - * - * @method clone - * @return {Point} a copy of the point - */ -PIXI.Point.prototype.clone = function() -{ - return new PIXI.Point(this.x, this.y); -} - -// constructor -PIXI.Point.prototype.constructor = PIXI.Point; - - -/** - * @author Mat Groves http://matgroves.com/ - */ - -/** - * the Rectangle object is an area defined by its position, as indicated by its top-left corner point (x, y) and by its width and its height. - * - * @class Rectangle - * @constructor - * @param x {Number} The X coord of the upper-left corner of the rectangle - * @param y {Number} The Y coord of the upper-left corner of the rectangle - * @param width {Number} The overall width of this rectangle - * @param height {Number} The overall height of this rectangle - */ -PIXI.Rectangle = function(x, y, width, height) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property width - * @type Number - * @default 0 - */ - this.width = width || 0; - - /** - * @property height - * @type Number - * @default 0 - */ - this.height = height || 0; -} - -/** - * Creates a clone of this Rectangle - * - * @method clone - * @return {Rectangle} a copy of the rectangle - */ -PIXI.Rectangle.prototype.clone = function() -{ - return new PIXI.Rectangle(this.x, this.y, this.width, this.height); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this Rectangle - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this Rectangle - */ -PIXI.Rectangle.prototype.contains = function(x, y) -{ - if(this.width <= 0 || this.height <= 0) - return false; - - var x1 = this.x; - if(x >= x1 && x <= x1 + this.width) - { - var y1 = this.y; - - if(y >= y1 && y <= y1 + this.height) - { - return true; - } - } - - return false; -} - -// constructor -PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; - - -/** - * @author Adrien Brault - */ - -/** - * @class Polygon - * @constructor - * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, - * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be - * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the - * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are - * Numbers. - */ -PIXI.Polygon = function(points) -{ - //if points isn't an array, use arguments as the array - if(!(points instanceof Array)) - points = Array.prototype.slice.call(arguments); - - //if this is a flat array of numbers, convert it to points - if(typeof points[0] === 'number') { - var p = []; - for(var i = 0, il = points.length; i < il; i+=2) { - p.push( - new PIXI.Point(points[i], points[i + 1]) - ); - } - - points = p; - } - - this.points = points; -} - -/** - * Creates a clone of this polygon - * - * @method clone - * @return {Polygon} a copy of the polygon - */ -PIXI.Polygon.prototype.clone = function() -{ - var points = []; - for (var i=0; i y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); - - if(intersect) inside = !inside; - } - - return inside; -} - -// constructor -PIXI.Polygon.prototype.constructor = PIXI.Polygon; - -/** - * @author Chad Engler - */ - -/** - * The Circle object can be used to specify a hit area for displayobjects - * - * @class Circle - * @constructor - * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle - * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle - * @param radius {Number} The radius of the circle - */ -PIXI.Circle = function(x, y, radius) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property radius - * @type Number - * @default 0 - */ - this.radius = radius || 0; -} - -/** - * Creates a clone of this Circle instance - * - * @method clone - * @return {Circle} a copy of the polygon - */ -PIXI.Circle.prototype.clone = function() -{ - return new PIXI.Circle(this.x, this.y, this.radius); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this circle - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this polygon - */ -PIXI.Circle.prototype.contains = function(x, y) -{ - if(this.radius <= 0) - return false; - - var dx = (this.x - x), - dy = (this.y - y), - r2 = this.radius * this.radius; - - dx *= dx; - dy *= dy; - - return (dx + dy <= r2); -} - -// constructor -PIXI.Circle.prototype.constructor = PIXI.Circle; - - -/** - * @author Chad Engler - */ - -/** - * The Ellipse object can be used to specify a hit area for displayobjects - * - * @class Ellipse - * @constructor - * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse - * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse - * @param width {Number} The overall width of this ellipse - * @param height {Number} The overall height of this ellipse - */ -PIXI.Ellipse = function(x, y, width, height) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property width - * @type Number - * @default 0 - */ - this.width = width || 0; - - /** - * @property height - * @type Number - * @default 0 - */ - this.height = height || 0; -} - -/** - * Creates a clone of this Ellipse instance - * - * @method clone - * @return {Ellipse} a copy of the ellipse - */ -PIXI.Ellipse.prototype.clone = function() -{ - return new PIXI.Ellipse(this.x, this.y, this.width, this.height); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this ellipse - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this ellipse - */ -PIXI.Ellipse.prototype.contains = function(x, y) -{ - if(this.width <= 0 || this.height <= 0) - return false; - - //normalize the coords to an ellipse with center 0,0 - //and a radius of 0.5 - var normx = ((x - this.x) / this.width) - 0.5, - normy = ((y - this.y) / this.height) - 0.5; - - normx *= normx; - normy *= normy; - - return (normx + normy < 0.25); -} - -PIXI.Ellipse.getBounds = function() -{ - return new PIXI.Rectangle(this.x, this.y, this.width, this.height); -} - -// constructor -PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; - - - -/* - * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV - * you both rock! - */ - -function determineMatrixArrayType() { - PIXI.Matrix = (typeof Float32Array !== 'undefined') ? Float32Array : Array; - return PIXI.Matrix; -} - -determineMatrixArrayType(); - -PIXI.mat3 = {}; - -PIXI.mat3.create = function() -{ - var matrix = new PIXI.Matrix(9); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 1; - matrix[5] = 0; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 1; - - return matrix; -} - - -PIXI.mat3.identity = function(matrix) -{ - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 1; - matrix[5] = 0; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 1; - - return matrix; -} - - -PIXI.mat4 = {}; - -PIXI.mat4.create = function() -{ - var matrix = new PIXI.Matrix(16); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 0; - matrix[5] = 1; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = 1; - matrix[11] = 0; - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; - - return matrix; -} - -PIXI.mat3.multiply = function (mat, mat2, dest) -{ - if (!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[0], a01 = mat[1], a02 = mat[2], - a10 = mat[3], a11 = mat[4], a12 = mat[5], - a20 = mat[6], a21 = mat[7], a22 = mat[8], - - b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], - b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], - b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; - - dest[0] = b00 * a00 + b01 * a10 + b02 * a20; - dest[1] = b00 * a01 + b01 * a11 + b02 * a21; - dest[2] = b00 * a02 + b01 * a12 + b02 * a22; - - dest[3] = b10 * a00 + b11 * a10 + b12 * a20; - dest[4] = b10 * a01 + b11 * a11 + b12 * a21; - dest[5] = b10 * a02 + b11 * a12 + b12 * a22; - - dest[6] = b20 * a00 + b21 * a10 + b22 * a20; - dest[7] = b20 * a01 + b21 * a11 + b22 * a21; - dest[8] = b20 * a02 + b21 * a12 + b22 * a22; - - return dest; -} - -PIXI.mat3.clone = function(mat) -{ - var matrix = new PIXI.Matrix(9); - - matrix[0] = mat[0]; - matrix[1] = mat[1]; - matrix[2] = mat[2]; - matrix[3] = mat[3]; - matrix[4] = mat[4]; - matrix[5] = mat[5]; - matrix[6] = mat[6]; - matrix[7] = mat[7]; - matrix[8] = mat[8]; - - return matrix; -} - -PIXI.mat3.transpose = function (mat, dest) -{ - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) { - var a01 = mat[1], a02 = mat[2], - a12 = mat[5]; - - mat[1] = mat[3]; - mat[2] = mat[6]; - mat[3] = a01; - mat[5] = mat[7]; - mat[6] = a02; - mat[7] = a12; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[3]; - dest[2] = mat[6]; - dest[3] = mat[1]; - dest[4] = mat[4]; - dest[5] = mat[7]; - dest[6] = mat[2]; - dest[7] = mat[5]; - dest[8] = mat[8]; - return dest; -} - -PIXI.mat3.toMat4 = function (mat, dest) -{ - if (!dest) { dest = PIXI.mat4.create(); } - - dest[15] = 1; - dest[14] = 0; - dest[13] = 0; - dest[12] = 0; - - dest[11] = 0; - dest[10] = mat[8]; - dest[9] = mat[7]; - dest[8] = mat[6]; - - dest[7] = 0; - dest[6] = mat[5]; - dest[5] = mat[4]; - dest[4] = mat[3]; - - dest[3] = 0; - dest[2] = mat[2]; - dest[1] = mat[1]; - dest[0] = mat[0]; - - return dest; -} - - -///// - - -PIXI.mat4.create = function() -{ - var matrix = new PIXI.Matrix(16); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 0; - matrix[5] = 1; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = 1; - matrix[11] = 0; - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; - - return matrix; -} - -PIXI.mat4.transpose = function (mat, dest) -{ - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) - { - var a01 = mat[1], a02 = mat[2], a03 = mat[3], - a12 = mat[6], a13 = mat[7], - a23 = mat[11]; - - mat[1] = mat[4]; - mat[2] = mat[8]; - mat[3] = mat[12]; - mat[4] = a01; - mat[6] = mat[9]; - mat[7] = mat[13]; - mat[8] = a02; - mat[9] = a12; - mat[11] = mat[14]; - mat[12] = a03; - mat[13] = a13; - mat[14] = a23; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[4]; - dest[2] = mat[8]; - dest[3] = mat[12]; - dest[4] = mat[1]; - dest[5] = mat[5]; - dest[6] = mat[9]; - dest[7] = mat[13]; - dest[8] = mat[2]; - dest[9] = mat[6]; - dest[10] = mat[10]; - dest[11] = mat[14]; - dest[12] = mat[3]; - dest[13] = mat[7]; - dest[14] = mat[11]; - dest[15] = mat[15]; - return dest; -} - -PIXI.mat4.multiply = function (mat, mat2, dest) -{ - if (!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; - var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; - var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; - var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - - // Cache only the current line of the second matrix - var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; - dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[4]; - b1 = mat2[5]; - b2 = mat2[6]; - b3 = mat2[7]; - dest[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[8]; - b1 = mat2[9]; - b2 = mat2[10]; - b3 = mat2[11]; - dest[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[12]; - b1 = mat2[13]; - b2 = mat2[14]; - b3 = mat2[15]; - dest[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - return dest; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The base class for all objects that are rendered on the screen. - * - * @class DisplayObject - * @constructor - */ -PIXI.DisplayObject = function() -{ - this.last = this; - this.first = this; - /** - * The coordinate of the object relative to the local coordinates of the parent. - * - * @property position - * @type Point - */ - this.position = new PIXI.Point(); - - /** - * The scale factor of the object. - * - * @property scale - * @type Point - */ - this.scale = new PIXI.Point(1,1);//{x:1, y:1}; - - /** - * The pivot point of the displayObject that it rotates around - * - * @property pivot - * @type Point - */ - this.pivot = new PIXI.Point(0,0); - - /** - * The rotation of the object in radians. - * - * @property rotation - * @type Number - */ - this.rotation = 0; - - /** - * The opacity of the object. - * - * @property alpha - * @type Number - */ - this.alpha = 1; - - /** - * The visibility of the object. - * - * @property visible - * @type Boolean - */ - this.visible = true; - - /** - * This is the defined area that will pick up mouse / touch events. It is null by default. - * Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children) - * - * @property hitArea - * @type Rectangle|Circle|Ellipse|Polygon - */ - this.hitArea = null; - - /** - * This is used to indicate if the displayObject should display a mouse hand cursor on rollover - * - * @property buttonMode - * @type Boolean - */ - this.buttonMode = false; - - /** - * Can this object be rendered - * - * @property renderable - * @type Boolean - */ - this.renderable = false; - - /** - * [read-only] The display object container that contains this display object. - * - * @property parent - * @type DisplayObjectContainer - * @readOnly - */ - this.parent = null; - - /** - * [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage. - * - * @property stage - * @type Stage - * @readOnly - */ - this.stage = null; - - /** - * [read-only] The multiplied alpha of the displayobject - * - * @property worldAlpha - * @type Number - * @readOnly - */ - this.worldAlpha = 1; - - /** - * [read-only] Whether or not the object is interactive, do not toggle directly! use the `interactive` property - * - * @property _interactive - * @type Boolean - * @readOnly - * @private - */ - this._interactive = false; - - /** - * [read-only] Current transform of the object based on world (parent) factors - * - * @property worldTransform - * @type Mat3 - * @readOnly - * @private - */ - this.worldTransform = PIXI.mat3.create()//mat3.identity(); - - /** - * [read-only] Current transform of the object locally - * - * @property localTransform - * @type Mat3 - * @readOnly - * @private - */ - this.localTransform = PIXI.mat3.create()//mat3.identity(); - - /** - * [NYI] Unkown - * - * @property color - * @type Array<> - * @private - */ - this.color = []; - - /** - * [NYI] Holds whether or not this object is dynamic, for rendering optimization - * - * @property dynamic - * @type Boolean - * @private - */ - this.dynamic = true; - - // chach that puppy! - this._sr = 0; - this._cr = 1; - - - this.filterArea = new PIXI.Rectangle(0,0,1,1); - - /* - * MOUSE Callbacks - */ - - /** - * A callback that is used when the users clicks on the displayObject with their mouse - * @method click - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user clicks the mouse down over the sprite - * @method mousedown - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject - * for this callback to be fired the mouse must have been pressed down over the displayObject - * @method mouseup - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject - * for this callback to be fired, The touch must have started over the displayObject - * @method mouseupoutside - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the users mouse rolls over the displayObject - * @method mouseover - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the users mouse leaves the displayObject - * @method mouseout - * @param interactionData {InteractionData} - */ - - - /* - * TOUCH Callbacks - */ - - /** - * A callback that is used when the users taps on the sprite with their finger - * basically a touch version of click - * @method tap - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user touch's over the displayObject - * @method touchstart - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases a touch over the displayObject - * @method touchend - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the touch that was over the displayObject - * for this callback to be fired, The touch must have started over the sprite - * @method touchendoutside - * @param interactionData {InteractionData} - */ -} - -// constructor -PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; - -/** - * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default - * Instead of using this function you can now simply set the interactive property to true or false - * - * @method setInteractive - * @param interactive {Boolean} - * @deprecated Simply set the `interactive` property directly - */ -PIXI.DisplayObject.prototype.setInteractive = function(interactive) -{ - this.interactive = interactive; -} - -/** - * Indicates if the sprite will have touch and mouse interactivity. It is false by default - * - * @property interactive - * @type Boolean - * @default false - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'interactive', { - get: function() { - return this._interactive; - }, - set: function(value) { - this._interactive = value; - - // TODO more to be done here.. - // need to sort out a re-crawl! - if(this.stage)this.stage.dirty = true; - } -}); - -/** - * Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. - * In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. - * To remove a mask, set this property to null. - * - * @property mask - * @type Graphics - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { - get: function() { - return this._mask; - }, - set: function(value) { - - - if(value) - { - if(this._mask) - { - value.start = this._mask.start; - value.end = this._mask.end; - } - else - { - this.addFilter(value); - value.renderable = false; - } - } - else - { - this.removeFilter(this._mask); - this._mask.renderable = true; - } - - this._mask = value; - } -}); - -/** - * Sets the filters for the displayObject. - * * IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer. - * To remove filters simply set this property to 'null' - * @property filters - * @type Array An array of filters - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { - get: function() { - return this._filters; - }, - set: function(value) { - - if(value) - { - if(this._filters)this.removeFilter(this._filters); - this.addFilter(value); - - // now put all the passes in one place.. - var passes = []; - for (var i = 0; i < value.length; i++) - { - var filterPasses = value[i].passes; - for (var j = 0; j < filterPasses.length; j++) - { - passes.push(filterPasses[j]); - }; - }; - - value.start.filterPasses = passes; - } - else - { - if(this._filters)this.removeFilter(this._filters); - } - - this._filters = value; - - - - - } -}); - -/* - * Adds a filter to this displayObject - * - * @method addFilter - * @param mask {Graphics} the graphics object to use as a filter - * @private - */ -PIXI.DisplayObject.prototype.addFilter = function(data) -{ - //if(this.filter)return; - //this.filter = true; -// data[0].target = this; - - - // insert a filter block.. - // TODO Onject pool thease bad boys.. - var start = new PIXI.FilterBlock(); - var end = new PIXI.FilterBlock(); - - data.start = start; - data.end = end; - - start.data = data; - end.data = data; - - start.first = start.last = this; - end.first = end.last = this; - - start.open = true; - - start.target = this; - - /* - * insert start - */ - - var childFirst = start - var childLast = start - var nextObject; - var previousObject; - - previousObject = this.first._iPrev; - - if(previousObject) - { - nextObject = previousObject._iNext; - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - } - else - { - nextObject = this; - } - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - - // now insert the end filter block.. - - /* - * insert end filter - */ - var childFirst = end - var childLast = end - var nextObject = null; - var previousObject = null; - - previousObject = this.last; - nextObject = previousObject._iNext; - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - var updateLast = this; - - var prevLast = this.last; - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = end; - } - updateLast = updateLast.parent; - } - - this.first = start; - - // if webGL... - if(this.__renderGroup) - { - this.__renderGroup.addFilterBlocks(start, end); - } - -} - -/* - * Removes the filter to this displayObject - * - * @method removeFilter - * @private - */ -PIXI.DisplayObject.prototype.removeFilter = function(data) -{ - //if(!this.filter)return; - //this.filter = false; - console.log("YUOIO") - // modify the list.. - var startBlock = data.start; - - - var nextObject = startBlock._iNext; - var previousObject = startBlock._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - if(previousObject)previousObject._iNext = nextObject; - - this.first = startBlock._iNext; - - // remove the end filter - var lastBlock = data.end; - - var nextObject = lastBlock._iNext; - var previousObject = lastBlock._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - - // this is always true too! - var tempLast = lastBlock._iPrev; - // need to make sure the parents last is updated too - var updateLast = this; - while(updateLast.last == lastBlock) - { - updateLast.last = tempLast; - updateLast = updateLast.parent; - if(!updateLast)break; - } - - // if webGL... - if(this.__renderGroup) - { - this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); - } -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.DisplayObject.prototype.updateTransform = function() -{ - // TODO OPTIMIZE THIS!! with dirty - if(this.rotation !== this.rotationCache) - { - this.rotationCache = this.rotation; - this._sr = Math.sin(this.rotation); - this._cr = Math.cos(this.rotation); - } - - var localTransform = this.localTransform; - var parentTransform = this.parent.worldTransform; - var worldTransform = this.worldTransform; - //console.log(localTransform) - localTransform[0] = this._cr * this.scale.x; - localTransform[1] = -this._sr * this.scale.y - localTransform[3] = this._sr * this.scale.x; - localTransform[4] = this._cr * this.scale.y; - - // TODO --> do we even need a local matrix??? - - var px = this.pivot.x; - var py = this.pivot.y; - - // Cache the matrix values (makes for huge speed increases!) - var a00 = localTransform[0], a01 = localTransform[1], a02 = this.position.x - localTransform[0] * px - py * localTransform[1], - a10 = localTransform[3], a11 = localTransform[4], a12 = this.position.y - localTransform[4] * py - px * localTransform[3], - - b00 = parentTransform[0], b01 = parentTransform[1], b02 = parentTransform[2], - b10 = parentTransform[3], b11 = parentTransform[4], b12 = parentTransform[5]; - - localTransform[2] = a02 - localTransform[5] = a12 - - worldTransform[0] = b00 * a00 + b01 * a10; - worldTransform[1] = b00 * a01 + b01 * a11; - worldTransform[2] = b00 * a02 + b01 * a12 + b02; - - worldTransform[3] = b10 * a00 + b11 * a10; - worldTransform[4] = b10 * a01 + b11 * a11; - worldTransform[5] = b10 * a02 + b11 * a12 + b12; - - // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! - // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); - this.worldAlpha = this.alpha * this.parent.worldAlpha; - - this.vcount = PIXI.visibleCount; - -} - -PIXI.visibleCount = 0; -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * A DisplayObjectContainer represents a collection of display objects. - * It is the base class of all display objects that act as a container for other objects. - * - * @class DisplayObjectContainer - * @extends DisplayObject - * @constructor - */ -PIXI.DisplayObjectContainer = function() -{ - PIXI.DisplayObject.call( this ); - - /** - * [read-only] The of children of this container. - * - * @property children - * @type Array - * @readOnly - */ - this.children = []; -} - -// constructor -PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); -PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; - -/** - * Adds a child to the container. - * - * @method addChild - * @param child {DisplayObject} The DisplayObject to add to the container - */ -PIXI.DisplayObjectContainer.prototype.addChild = function(child) -{ - if(child.parent != undefined) - { - - //// COULD BE THIS??? - child.parent.removeChild(child); - // return; - } - - child.parent = this; - - this.children.push(child); - - // update the stage refference.. - - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = this.stage; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // LINKED LIST // - - // modify the list.. - var childFirst = child.first - var childLast = child.last; - var nextObject; - var previousObject; - - // this could be wrong if there is a filter?? - if(this._filters || this._mask) - { - previousObject = this.last._iPrev; - } - else - { - previousObject = this.last; - } - - nextObject = previousObject._iNext; - - // always true in this case - // need to make sure the parents last is updated too - var updateLast = this; - var prevLast = previousObject; - - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = child.last; - } - updateLast = updateLast.parent; - } - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - // need to remove any render groups.. - if(this.__renderGroup) - { - // being used by a renderTexture.. if it exists then it must be from a render texture; - if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); - // add them to the new render group.. - this.__renderGroup.addDisplayObjectAndChildren(child); - } - -} - -/** - * Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown - * - * @method addChildAt - * @param child {DisplayObject} The child to add - * @param index {Number} The index to place the child in - */ -PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) -{ - if(index >= 0 && index <= this.children.length) - { - if(child.parent != undefined) - { - child.parent.removeChild(child); - } - child.parent = this; - - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = this.stage; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // modify the list.. - var childFirst = child.first; - var childLast = child.last; - var nextObject; - var previousObject; - - if(index == this.children.length) - { - previousObject = this.last; - var updateLast = this; - var prevLast = this.last; - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = child.last; - } - updateLast = updateLast.parent; - } - } - else if(index == 0) - { - previousObject = this; - } - else - { - previousObject = this.children[index-1].last; - } - - nextObject = previousObject._iNext; - - // always true in this case - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - this.children.splice(index, 0, child); - // need to remove any render groups.. - if(this.__renderGroup) - { - // being used by a renderTexture.. if it exists then it must be from a render texture; - if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); - // add them to the new render group.. - this.__renderGroup.addDisplayObjectAndChildren(child); - } - - } - else - { - throw new Error(child + " The index "+ index +" supplied is out of bounds " + this.children.length); - } -} - -/** - * [NYI] Swaps the depth of 2 displayObjects - * - * @method swapChildren - * @param child {DisplayObject} - * @param child2 {DisplayObject} - * @private - */ -PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2) -{ - /* - * this funtion needs to be recoded.. - * can be done a lot faster.. - */ - return; - - // need to fix this function :/ - /* - // TODO I already know this?? - var index = this.children.indexOf( child ); - var index2 = this.children.indexOf( child2 ); - - if ( index !== -1 && index2 !== -1 ) - { - // cool - - /* - if(this.stage) - { - // this is to satisfy the webGL batching.. - // TODO sure there is a nicer way to achieve this! - this.stage.__removeChild(child); - this.stage.__removeChild(child2); - - this.stage.__addChild(child); - this.stage.__addChild(child2); - } - - // swap the positions.. - this.children[index] = child2; - this.children[index2] = child; - - } - else - { - throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); - }*/ -} - -/** - * Returns the Child at the specified index - * - * @method getChildAt - * @param index {Number} The index to get the child from - */ -PIXI.DisplayObjectContainer.prototype.getChildAt = function(index) -{ - if(index >= 0 && index < this.children.length) - { - return this.children[index]; - } - else - { - throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); - } -} - -/** - * Removes a child from the container. - * - * @method removeChild - * @param child {DisplayObject} The DisplayObject to remove - */ -PIXI.DisplayObjectContainer.prototype.removeChild = function(child) -{ - var index = this.children.indexOf( child ); - if ( index !== -1 ) - { - // unlink // - // modify the list.. - var childFirst = child.first; - var childLast = child.last; - - var nextObject = childLast._iNext; - var previousObject = childFirst._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - - if(this.last == childLast) - { - var tempLast = childFirst._iPrev; - // need to make sure the parents last is updated too - var updateLast = this; - while(updateLast.last == childLast.last) - { - updateLast.last = tempLast; - updateLast = updateLast.parent; - if(!updateLast)break; - } - } - - childLast._iNext = null; - childFirst._iPrev = null; - - // update the stage reference.. - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = null; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // webGL trim - if(child.__renderGroup) - { - child.__renderGroup.removeDisplayObjectAndChildren(child); - } - - child.parent = undefined; - this.children.splice( index, 1 ); - } - else - { - throw new Error(child + " The supplied DisplayObject must be a child of the caller " + this); - } -} - -/* - * Updates the container's children's transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.DisplayObjectContainer.prototype.updateTransform = function() -{ - if(!this.visible)return; - - PIXI.DisplayObject.prototype.updateTransform.call( this ); - - for(var i=0,j=this.children.length; i} an array of {Texture} objects that make up the animation - */ -PIXI.MovieClip = function(textures) -{ - PIXI.Sprite.call(this, textures[0]); - - /** - * The array of textures that make up the animation - * - * @property textures - * @type Array - */ - this.textures = textures; - - /** - * The speed that the MovieClip will play at. Higher is faster, lower is slower - * - * @property animationSpeed - * @type Number - * @default 1 - */ - this.animationSpeed = 1; - - /** - * Whether or not the movie clip repeats after playing. - * - * @property loop - * @type Boolean - * @default true - */ - this.loop = true; - - /** - * Function to call when a MovieClip finishes playing - * - * @property onComplete - * @type Function - */ - this.onComplete = null; - - /** - * [read-only] The index MovieClips current frame (this may not have to be a whole number) - * - * @property currentFrame - * @type Number - * @default 0 - * @readOnly - */ - this.currentFrame = 0; - - /** - * [read-only] Indicates if the MovieClip is currently playing - * - * @property playing - * @type Boolean - * @readOnly - */ - this.playing = false; -} - -// constructor -PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); -PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; - -/** -* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures -* assigned to the MovieClip. -* -* @property totalFrames -* @type Number -* @default 0 -* @readOnly -*/ -Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { - get: function() { - - return this.textures.length; - } -}); - - -/** - * Stops the MovieClip - * - * @method stop - */ -PIXI.MovieClip.prototype.stop = function() -{ - this.playing = false; -} - -/** - * Plays the MovieClip - * - * @method play - */ -PIXI.MovieClip.prototype.play = function() -{ - this.playing = true; -} - -/** - * Stops the MovieClip and goes to a specific frame - * - * @method gotoAndStop - * @param frameNumber {Number} frame index to stop at - */ -PIXI.MovieClip.prototype.gotoAndStop = function(frameNumber) -{ - this.playing = false; - this.currentFrame = frameNumber; - var round = (this.currentFrame + 0.5) | 0; - this.setTexture(this.textures[round % this.textures.length]); -} - -/** - * Goes to a specific frame and begins playing the MovieClip - * - * @method gotoAndPlay - * @param frameNumber {Number} frame index to start at - */ -PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) -{ - this.currentFrame = frameNumber; - this.playing = true; -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.MovieClip.prototype.updateTransform = function() -{ - PIXI.Sprite.prototype.updateTransform.call(this); - - if(!this.playing)return; - - this.currentFrame += this.animationSpeed; - - var round = (this.currentFrame + 0.5) | 0; - - if(this.loop || round < this.textures.length) - { - this.setTexture(this.textures[round % this.textures.length]); - } - else if(round >= this.textures.length) - { - this.gotoAndStop(this.textures.length - 1); - if(this.onComplete) - { - this.onComplete(); - } - } -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - - -PIXI.FilterBlock = function() -{ - this.visible = true; - this.renderable = true; -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Text Object will create a line(s) of text to split a line you can use "\n" - * - * @class Text - * @extends Sprite - * @constructor - * @param text {String} The copy that you would like the text to display - * @param [style] {Object} The style parameters - * @param [style.font] {String} default "bold 20pt Arial" The style and size of the font - * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - * @param [style.stroke] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" - * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) - * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used - * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap - */ -PIXI.Text = function(text, style) -{ - this.canvas = document.createElement("canvas"); - this.context = this.canvas.getContext("2d"); - PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas)); - - this.setText(text); - this.setStyle(style); - - this.updateText(); - this.dirty = false; -}; - -// constructor -PIXI.Text.prototype = Object.create(PIXI.Sprite.prototype); -PIXI.Text.prototype.constructor = PIXI.Text; - -/** - * Set the style of the text - * - * @method setStyle - * @param [style] {Object} The style parameters - * @param [style.font="bold 20pt Arial"] {String} The style and size of the font - * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - * @param [style.stroke="black"] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" - * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) - * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used - * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap - */ -PIXI.Text.prototype.setStyle = function(style) -{ - style = style || {}; - style.font = style.font || "bold 20pt Arial"; - style.fill = style.fill || "black"; - style.align = style.align || "left"; - style.stroke = style.stroke || "black"; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136 - style.strokeThickness = style.strokeThickness || 0; - style.wordWrap = style.wordWrap || false; - style.wordWrapWidth = style.wordWrapWidth || 100; - this.style = style; - this.dirty = true; -}; - -/** - * Set the copy for the text object. To split a line you can use "\n" - * - * @methos setText - * @param {String} text The copy that you would like the text to display - */ -PIXI.Text.prototype.setText = function(text) -{ - this.text = text.toString() || " "; - this.dirty = true; -}; - -/** - * Renders text - * - * @method updateText - * @private - */ -PIXI.Text.prototype.updateText = function() -{ - this.context.font = this.style.font; - - var outputText = this.text; - - // word wrap - // preserve original text - if(this.style.wordWrap)outputText = this.wordWrap(this.text); - - //split text into lines - var lines = outputText.split(/(?:\r\n|\r|\n)/); - - //calculate text width - var lineWidths = []; - var maxLineWidth = 0; - for (var i = 0; i < lines.length; i++) - { - var lineWidth = this.context.measureText(lines[i]).width; - lineWidths[i] = lineWidth; - maxLineWidth = Math.max(maxLineWidth, lineWidth); - } - this.canvas.width = maxLineWidth + this.style.strokeThickness; - - //calculate text height - var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; - this.canvas.height = lineHeight * lines.length; - - //set canvas text styles - this.context.fillStyle = this.style.fill; - this.context.font = this.style.font; - - this.context.strokeStyle = this.style.stroke; - this.context.lineWidth = this.style.strokeThickness; - - this.context.textBaseline = "top"; - - //draw lines line by line - for (i = 0; i < lines.length; i++) - { - var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); - - if(this.style.align == "right") - { - linePosition.x += maxLineWidth - lineWidths[i]; - } - else if(this.style.align == "center") - { - linePosition.x += (maxLineWidth - lineWidths[i]) / 2; - } - - if(this.style.stroke && this.style.strokeThickness) - { - this.context.strokeText(lines[i], linePosition.x, linePosition.y); - } - - if(this.style.fill) - { - this.context.fillText(lines[i], linePosition.x, linePosition.y); - } - } - - this.updateTexture(); -}; - -/** - * Updates texture size based on canvas size - * - * @method updateTexture - * @private - */ -PIXI.Text.prototype.updateTexture = function() -{ - this.texture.baseTexture.width = this.canvas.width; - this.texture.baseTexture.height = this.canvas.height; - this.texture.frame.width = this.canvas.width; - this.texture.frame.height = this.canvas.height; - - this._width = this.canvas.width; - this._height = this.canvas.height; - - PIXI.texturesToUpdate.push(this.texture.baseTexture); -}; - -/** - * Updates the transfor of this object - * - * @method updateTransform - * @private - */ -PIXI.Text.prototype.updateTransform = function() -{ - if(this.dirty) - { - this.updateText(); - this.dirty = false; - } - - PIXI.Sprite.prototype.updateTransform.call(this); -}; - -/* - * http://stackoverflow.com/users/34441/ellisbben - * great solution to the problem! - * - * @method determineFontHeight - * @param fontStyle {Object} - * @private - */ -PIXI.Text.prototype.determineFontHeight = function(fontStyle) -{ - // build a little reference dictionary so if the font style has been used return a - // cached version... - var result = PIXI.Text.heightCache[fontStyle]; - - if(!result) - { - var body = document.getElementsByTagName("body")[0]; - var dummy = document.createElement("div"); - var dummyText = document.createTextNode("M"); - dummy.appendChild(dummyText); - dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); - body.appendChild(dummy); - - result = dummy.offsetHeight; - PIXI.Text.heightCache[fontStyle] = result; - - body.removeChild(dummy); - } - - return result; -}; - -/** - * Applies newlines to a string to have it optimally fit into the horizontal - * bounds set by the Text object's wordWrapWidth property. - * - * @method wordWrap - * @param text {String} - * @private - */ -PIXI.Text.prototype.wordWrap = function(text) -{ - // Greedy wrapping algorithm that will wrap words as the line grows longer - // than its horizontal bounds. - var result = ""; - var lines = text.split("\n"); - for (var i = 0; i < lines.length; i++) - { - var spaceLeft = this.style.wordWrapWidth; - var words = lines[i].split(" "); - for (var j = 0; j < words.length; j++) - { - var wordWidth = this.context.measureText(words[j]).width; - var wordWidthWithSpace = wordWidth + this.context.measureText(" ").width; - if(wordWidthWithSpace > spaceLeft) - { - // Skip printing the newline if it's the first word of the line that is - // greater than the word wrap width. - if(j > 0) - { - result += "\n"; - } - result += words[j] + " "; - spaceLeft = this.style.wordWrapWidth - wordWidth; - } - else - { - spaceLeft -= wordWidthWithSpace; - result += words[j] + " "; - } - } - result += "\n"; - } - return result; -}; - -/** - * Destroys this text object - * - * @method destroy - * @param destroyTexture {Boolean} - */ -PIXI.Text.prototype.destroy = function(destroyTexture) -{ - if(destroyTexture) - { - this.texture.destroy(); - } - -}; - -PIXI.Text.heightCache = {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" - * You can generate the fnt files using - * http://www.angelcode.com/products/bmfont/ for windows or - * http://www.bmglyph.com/ for mac. - * - * @class BitmapText - * @extends DisplayObjectContainer - * @constructor - * @param text {String} The copy that you would like the text to display - * @param style {Object} The style parameters - * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - */ -PIXI.BitmapText = function(text, style) -{ - PIXI.DisplayObjectContainer.call(this); - - this.setText(text); - this.setStyle(style); - this.updateText(); - this.dirty = false - -}; - -// constructor -PIXI.BitmapText.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); -PIXI.BitmapText.prototype.constructor = PIXI.BitmapText; - -/** - * Set the copy for the text object - * - * @method setText - * @param text {String} The copy that you would like the text to display - */ -PIXI.BitmapText.prototype.setText = function(text) -{ - this.text = text || " "; - this.dirty = true; -}; - -/** - * Set the style of the text - * - * @method setStyle - * @param style {Object} The style parameters - * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - */ -PIXI.BitmapText.prototype.setStyle = function(style) -{ - style = style || {}; - style.align = style.align || "left"; - this.style = style; - - var font = style.font.split(" "); - this.fontName = font[font.length - 1]; - this.fontSize = font.length >= 2 ? parseInt(font[font.length - 2], 10) : PIXI.BitmapText.fonts[this.fontName].size; - - this.dirty = true; -}; - -/** - * Renders text - * - * @method updateText - * @private - */ -PIXI.BitmapText.prototype.updateText = function() -{ - var data = PIXI.BitmapText.fonts[this.fontName]; - var pos = new PIXI.Point(); - var prevCharCode = null; - var chars = []; - var maxLineWidth = 0; - var lineWidths = []; - var line = 0; - var scale = this.fontSize / data.size; - for(var i = 0; i < this.text.length; i++) - { - var charCode = this.text.charCodeAt(i); - if(/(?:\r\n|\r|\n)/.test(this.text.charAt(i))) - { - lineWidths.push(pos.x); - maxLineWidth = Math.max(maxLineWidth, pos.x); - line++; - - pos.x = 0; - pos.y += data.lineHeight; - prevCharCode = null; - continue; - } - - var charData = data.chars[charCode]; - if(!charData) continue; - - if(prevCharCode && charData[prevCharCode]) - { - pos.x += charData.kerning[prevCharCode]; - } - chars.push({texture:charData.texture, line: line, charCode: charCode, position: new PIXI.Point(pos.x + charData.xOffset, pos.y + charData.yOffset)}); - pos.x += charData.xAdvance; - - prevCharCode = charCode; - } - - lineWidths.push(pos.x); - maxLineWidth = Math.max(maxLineWidth, pos.x); - - var lineAlignOffsets = []; - for(i = 0; i <= line; i++) - { - var alignOffset = 0; - if(this.style.align == "right") - { - alignOffset = maxLineWidth - lineWidths[i]; - } - else if(this.style.align == "center") - { - alignOffset = (maxLineWidth - lineWidths[i]) / 2; - } - lineAlignOffsets.push(alignOffset); - } - - for(i = 0; i < chars.length; i++) - { - var c = new PIXI.Sprite(chars[i].texture)//PIXI.Sprite.fromFrame(chars[i].charCode); - c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale; - c.position.y = chars[i].position.y * scale; - c.scale.x = c.scale.y = scale; - this.addChild(c); - } - - this.width = pos.x * scale; - this.height = (pos.y + data.lineHeight) * scale; -}; - -/** - * Updates the transfor of this object - * - * @method updateTransform - * @private - */ -PIXI.BitmapText.prototype.updateTransform = function() -{ - if(this.dirty) - { - while(this.children.length > 0) - { - this.removeChild(this.getChildAt(0)); - } - this.updateText(); - - this.dirty = false; - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -}; - -PIXI.BitmapText.fonts = {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - /** - * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive - * This manager also supports multitouch. - * - * @class InteractionManager - * @constructor - * @param stage {Stage} The stage to handle interactions - */ -PIXI.InteractionManager = function(stage) -{ - /** - * a refference to the stage - * - * @property stage - * @type Stage - */ - this.stage = stage; - - /** - * the mouse data - * - * @property mouse - * @type InteractionData - */ - this.mouse = new PIXI.InteractionData(); - - /** - * an object that stores current touches (InteractionData) by id reference - * - * @property touchs - * @type Object - */ - this.touchs = {}; - - - - // helpers - this.tempPoint = new PIXI.Point(); - //this.tempMatrix = mat3.create(); - - this.mouseoverEnabled = true; - - //tiny little interactiveData pool! - this.pool = []; - - this.interactiveItems = []; - this.interactionDOMElement = null; - - //this will make it so that you dont have to call bind all the time - this.onMouseMove = this.onMouseMove.bind( this ); - this.onMouseDown = this.onMouseDown.bind(this); - this.onMouseOut = this.onMouseOut.bind(this); - this.onMouseUp = this.onMouseUp.bind(this); - - this.onTouchStart = this.onTouchStart.bind(this); - this.onTouchEnd = this.onTouchEnd.bind(this); - this.onTouchMove = this.onTouchMove.bind(this); - - - this.last = 0; -} - -// constructor -PIXI.InteractionManager.prototype.constructor = PIXI.InteractionManager; - -/** - * Collects an interactive sprite recursively to have their interactions managed - * - * @method collectInteractiveSprite - * @param displayObject {DisplayObject} the displayObject to collect - * @param iParent {DisplayObject} - * @private - */ -PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObject, iParent) -{ - var children = displayObject.children; - var length = children.length; - - /// make an interaction tree... {item.__interactiveParent} - for (var i = length-1; i >= 0; i--) - { - var child = children[i]; - -// if(child.visible) { - // push all interactive bits - if(child.interactive) - { - iParent.interactiveChildren = true; - //child.__iParent = iParent; - this.interactiveItems.push(child); - - if(child.children.length > 0) - { - this.collectInteractiveSprite(child, child); - } - } - else - { - child.__iParent = null; - - if(child.children.length > 0) - { - this.collectInteractiveSprite(child, iParent); - } - } -// } - } -} - -/** - * Sets the target for event delegation - * - * @method setTarget - * @param target {WebGLRenderer|CanvasRenderer} the renderer to bind events to - * @private - */ -PIXI.InteractionManager.prototype.setTarget = function(target) -{ - this.target = target; - - //check if the dom element has been set. If it has don't do anything - if( this.interactionDOMElement === null ) { - - this.setTargetDomElement( target.view ); - } - - document.body.addEventListener('mouseup', this.onMouseUp, true); -} - - -/** - * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM - * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element - * to receive those events - * - * @method setTargetDomElement - * @param domElement {DOMElement} the dom element which will receive mouse and touch events - * @private - */ -PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) -{ - //remove previouse listeners - if( this.interactionDOMElement !== null ) - { - this.interactionDOMElement.style['-ms-content-zooming'] = ''; - this.interactionDOMElement.style['-ms-touch-action'] = ''; - - this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); - this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); - this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); - - // aint no multi touch just yet! - this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); - this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); - this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); - } - - - if (window.navigator.msPointerEnabled) - { - // time to remove some of that zoom in ja.. - domElement.style['-ms-content-zooming'] = 'none'; - domElement.style['-ms-touch-action'] = 'none'; - - // DO some window specific touch! - } - - this.interactionDOMElement = domElement; - - domElement.addEventListener('mousemove', this.onMouseMove, true); - domElement.addEventListener('mousedown', this.onMouseDown, true); - domElement.addEventListener('mouseout', this.onMouseOut, true); - - // aint no multi touch just yet! - domElement.addEventListener('touchstart', this.onTouchStart, true); - domElement.addEventListener('touchend', this.onTouchEnd, true); - domElement.addEventListener('touchmove', this.onTouchMove, true); -} - - -/** - * updates the state of interactive objects - * - * @method update - * @private - */ -PIXI.InteractionManager.prototype.update = function() -{ - if(!this.target)return; - - // frequency of 30fps?? - var now = Date.now(); - var diff = now - this.last; - diff = (diff * 30) / 1000; - if(diff < 1)return; - this.last = now; - // - - // ok.. so mouse events?? - // yes for now :) - // OPTIMSE - how often to check?? - if(this.dirty) - { - this.dirty = false; - - var len = this.interactiveItems.length; - - for (var i=0; i < len; i++) { - this.interactiveItems[i].interactiveChildren = false; - } - - this.interactiveItems = []; - - if(this.stage.interactive)this.interactiveItems.push(this.stage); - // go through and collect all the objects that are interactive.. - this.collectInteractiveSprite(this.stage, this.stage); - } - - // loop through interactive objects! - var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - - //if(!item.visible)continue; - - // OPTIMISATION - only calculate every time if the mousemove function exists.. - // OK so.. does the object have any other interactive functions? - // hit-test the clip! - - - if(item.mouseover || item.mouseout || item.buttonMode) - { - // ok so there are some functions so lets hit test it.. - item.__hit = this.hitTest(item, this.mouse); - this.mouse.target = item; - // ok so deal with interactions.. - // loks like there was a hit! - if(item.__hit) - { - if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; - - if(!item.__isOver) - { - - if(item.mouseover)item.mouseover(this.mouse); - item.__isOver = true; - } - } - else - { - if(item.__isOver) - { - // roll out! - if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; - } - } - } - - // ---> - } -} - -/** - * Is called when the mouse moves accross the renderer element - * - * @method onMouseMove - * @param event {Event} The DOM event of the mouse moving - * @private - */ -PIXI.InteractionManager.prototype.onMouseMove = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - // TODO optimize by not check EVERY TIME! maybe half as often? // - var rect = this.interactionDOMElement.getBoundingClientRect(); - - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); - - var length = this.interactiveItems.length; - var global = this.mouse.global; - - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mousemove) - { - //call the function! - item.mousemove(this.mouse); - } - } -} - -/** - * Is called when the mouse button is pressed down on the renderer element - * - * @method onMouseDown - * @param event {Event} The DOM event of a mouse button being pressed down - * @private - */ -PIXI.InteractionManager.prototype.onMouseDown = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - - // loop through inteaction tree... - // hit test each item! -> - // get interactive items under point?? - //stage.__i - var length = this.interactiveItems.length; - var global = this.mouse.global; - - var index = 0; - var parent = this.stage; - - // while - // hit test - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mousedown || item.click) - { - item.__mouseIsDown = true; - item.__hit = this.hitTest(item, this.mouse); - - if(item.__hit) - { - //call the function! - if(item.mousedown)item.mousedown(this.mouse); - item.__isDown = true; - - // just the one! - if(!item.interactiveChildren)break; - } - } - } -} - - -PIXI.InteractionManager.prototype.onMouseOut = function(event) -{ - var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.__isOver) - { - this.mouse.target = item; - if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; - } - } -} - -/** - * Is called when the mouse button is released on the renderer element - * - * @method onMouseUp - * @param event {Event} The DOM event of a mouse button being released - * @private - */ -PIXI.InteractionManager.prototype.onMouseUp = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - - var global = this.mouse.global; - - - var length = this.interactiveItems.length; - var up = false; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mouseup || item.mouseupoutside || item.click) - { - item.__hit = this.hitTest(item, this.mouse); - - if(item.__hit && !up) - { - //call the function! - if(item.mouseup) - { - item.mouseup(this.mouse); - } - if(item.__isDown) - { - if(item.click)item.click(this.mouse); - } - - if(!item.interactiveChildren)up = true; - } - else - { - if(item.__isDown) - { - if(item.mouseupoutside)item.mouseupoutside(this.mouse); - } - } - - item.__isDown = false; - } - } -} - -/** - * Tests if the current mouse coords hit a sprite - * - * @method hitTest - * @param item {DisplayObject} The displayObject to test for a hit - * @param interactionData {InteractionData} The interactiondata object to update in the case of a hit - * @private - */ -PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) -{ - var global = interactionData.global; - - if(item.vcount !== PIXI.visibleCount)return false; - - var isSprite = (item instanceof PIXI.Sprite), - worldTransform = item.worldTransform, - a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10), - x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, - y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - interactionData.target = item; - - //a sprite or display object with a hit area defined - if(item.hitArea && item.hitArea.contains) { - if(item.hitArea.contains(x, y)) { - //if(isSprite) - interactionData.target = item; - - return true; - } - - return false; - } - // a sprite with no hitarea defined - else if(isSprite) - { - var width = item.texture.frame.width, - height = item.texture.frame.height, - x1 = -width * item.anchor.x, - y1; - - if(x > x1 && x < x1 + width) - { - y1 = -height * item.anchor.y; - - if(y > y1 && y < y1 + height) - { - // set the target property if a hit is true! - interactionData.target = item - return true; - } - } - } - - var length = item.children.length; - - for (var i = 0; i < length; i++) - { - var tempItem = item.children[i]; - var hit = this.hitTest(tempItem, interactionData); - if(hit) - { - // hmm.. TODO SET CORRECT TARGET? - interactionData.target = item - return true; - } - } - - return false; -} - -/** - * Is called when a touch is moved accross the renderer element - * - * @method onTouchMove - * @param event {Event} The DOM event of a touch moving accross the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchMove = function(event) -{ - var rect = this.interactionDOMElement.getBoundingClientRect(); - var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - var touchData = this.touchs[touchEvent.identifier]; - touchData.originalEvent = event || window.event; - - // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - } - - var length = this.interactiveItems.length; - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - if(item.touchmove)item.touchmove(touchData); - } -} - -/** - * Is called when a touch is started on the renderer element - * - * @method onTouchStart - * @param event {Event} The DOM event of a touch starting on the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchStart = function(event) -{ - var rect = this.interactionDOMElement.getBoundingClientRect(); - - var changedTouches = event.changedTouches; - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - - var touchData = this.pool.pop(); - if(!touchData)touchData = new PIXI.InteractionData(); - - touchData.originalEvent = event || window.event; - - this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - - var length = this.interactiveItems.length; - - for (var j = 0; j < length; j++) - { - var item = this.interactiveItems[j]; - - if(item.touchstart || item.tap) - { - item.__hit = this.hitTest(item, touchData); - - if(item.__hit) - { - //call the function! - if(item.touchstart)item.touchstart(touchData); - item.__isDown = true; - item.__touchData = touchData; - - if(!item.interactiveChildren)break; - } - } - } - } -} - -/** - * Is called when a touch is ended on the renderer element - * - * @method onTouchEnd - * @param event {Event} The DOM event of a touch ending on the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchEnd = function(event) -{ - //this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.interactionDOMElement.getBoundingClientRect(); - var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - var touchData = this.touchs[touchEvent.identifier]; - var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - - var length = this.interactiveItems.length; - for (var j = 0; j < length; j++) - { - var item = this.interactiveItems[j]; - var itemTouchData = item.__touchData; // <-- Here! - item.__hit = this.hitTest(item, touchData); - - if(itemTouchData == touchData) - { - // so this one WAS down... - touchData.originalEvent = event || window.event; - // hitTest?? - - if(item.touchend || item.tap) - { - if(item.__hit && !up) - { - if(item.touchend)item.touchend(touchData); - if(item.__isDown) - { - if(item.tap)item.tap(touchData); - } - - if(!item.interactiveChildren)up = true; - } - else - { - if(item.__isDown) - { - if(item.touchendoutside)item.touchendoutside(touchData); - } - } - - item.__isDown = false; - } - - item.__touchData = null; - - } - else - { - - } - } - // remove the touch.. - this.pool.push(touchData); - this.touchs[touchEvent.identifier] = null; - } -} - -/** - * Holds all information related to an Interaction event - * - * @class InteractionData - * @constructor - */ -PIXI.InteractionData = function() -{ - /** - * This point stores the global coords of where the touch/mouse event happened - * - * @property global - * @type Point - */ - this.global = new PIXI.Point(); - - // this is here for legacy... but will remove - this.local = new PIXI.Point(); - - /** - * The target Sprite that was interacted with - * - * @property target - * @type Sprite - */ - this.target; - - /** - * When passed to an event handler, this will be the original DOM Event that was captured - * - * @property originalEvent - * @type Event - */ - this.originalEvent; -} - -/** - * This will return the local coords of the specified displayObject for this InteractionData - * - * @method getLocalPosition - * @param displayObject {DisplayObject} The DisplayObject that you would like the local coords off - * @return {Point} A point containing the coords of the InteractionData position relative to the DisplayObject - */ -PIXI.InteractionData.prototype.getLocalPosition = function(displayObject) -{ - var worldTransform = displayObject.worldTransform; - var global = this.global; - - // do a cheeky transform to get the mouse coords; - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - // set the mouse coords... - return new PIXI.Point(a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, - a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id) -} - -// constructor -PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Stage represents the root of the display tree. Everything connected to the stage is rendered - * - * @class Stage - * @extends DisplayObjectContainer - * @constructor - * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format - * like: 0xFFFFFF for white - */ -PIXI.Stage = function(backgroundColor) -{ - PIXI.DisplayObjectContainer.call( this ); - - /** - * [read-only] Current transform of the object based on world (parent) factors - * - * @property worldTransform - * @type Mat3 - * @readOnly - * @private - */ - this.worldTransform = PIXI.mat3.create(); - - /** - * Whether or not the stage is interactive - * - * @property interactive - * @type Boolean - */ - this.interactive = true; - - /** - * The interaction manage for this stage, manages all interactive activity on the stage - * - * @property interactive - * @type InteractionManager - */ - this.interactionManager = new PIXI.InteractionManager(this); - - /** - * Whether the stage is dirty and needs to have interactions updated - * - * @property dirty - * @type Boolean - * @private - */ - this.dirty = true; - - this.__childrenAdded = []; - this.__childrenRemoved = []; - - //the stage is it's own stage - this.stage = this; - - //optimize hit detection a bit - this.stage.hitArea = new PIXI.Rectangle(0,0,100000, 100000); - - this.setBackgroundColor(backgroundColor); - this.worldVisible = true; -} - -// constructor -PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Stage.prototype.constructor = PIXI.Stage; - -/** - * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. - * This is useful for when you have other DOM elements ontop of the Canvas element. - * - * @method setInteractionDelegate - * @param domElement {DOMElement} This new domElement which will receive mouse/touch events - */ -PIXI.Stage.prototype.setInteractionDelegate = function(domElement) -{ - this.interactionManager.setTargetDomElement( domElement ); -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.Stage.prototype.updateTransform = function() -{ - this.worldAlpha = 1; - this.vcount = PIXI.visibleCount; - - for(var i=0,j=this.children.length; i> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; -} - -/** - * A polyfill for Function.prototype.bind - * - * @method bind - */ -if (typeof Function.prototype.bind != 'function') { - Function.prototype.bind = (function () { - var slice = Array.prototype.slice; - return function (thisArg) { - var target = this, boundArgs = slice.call(arguments, 1); - - if (typeof target != 'function') throw new TypeError(); - - function bound() { - var args = boundArgs.concat(slice.call(arguments)); - target.apply(this instanceof bound ? this : thisArg, args); - } - - bound.prototype = (function F(proto) { - proto && (F.prototype = proto); - if (!(this instanceof F)) return new F; - })(target.prototype); - - return bound; - }; - })(); -} - -/** - * A wrapper for ajax requests to be handled cross browser - * - * @class AjaxRequest - * @constructor - */ -var AjaxRequest = PIXI.AjaxRequest = function() -{ - var activexmodes = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Microsoft.XMLHTTP"] //activeX versions to check for in IE - - if (window.ActiveXObject) - { //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken) - for (var i=0; i>>>>>>>>") - console.log("_") - var safe = 0; - var tmp = item.first; - console.log(tmp); - - while(tmp._iNext) - { - safe++; - tmp = tmp._iNext; - console.log(tmp); - // console.log(tmp); - - if(safe > 100) - { - console.log("BREAK") - break - } - } -} - - - - - - -/** - * https://github.com/mrdoob/eventtarget.js/ - * THankS mr DOob! - */ - -/** - * Adds event emitter functionality to a class - * - * @class EventTarget - * @example - * function MyEmitter() { - * PIXI.EventTarget.call(this); //mixes in event target stuff - * } - * - * var em = new MyEmitter(); - * em.emit({ type: 'eventName', data: 'some data' }); - */ -PIXI.EventTarget = function () { - - var listeners = {}; - - this.addEventListener = this.on = function ( type, listener ) { - - - if ( listeners[ type ] === undefined ) { - - listeners[ type ] = []; - - } - - if ( listeners[ type ].indexOf( listener ) === - 1 ) { - - listeners[ type ].push( listener ); - } - - }; - - this.dispatchEvent = this.emit = function ( event ) { - - if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { - - return; - - } - - for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { - - listeners[ event.type ][ i ]( event ); - - } - - }; - - this.removeEventListener = this.off = function ( type, listener ) { - - var index = listeners[ type ].indexOf( listener ); - - if ( index !== - 1 ) { - - listeners[ type ].splice( index, 1 ); - - } - - }; - -}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * This helper function will automatically detect which renderer you should be using. - * WebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by - * the browser then this function will return a canvas renderer - * - * @method autoDetectRenderer - * @static - * @param width {Number} the width of the renderers view - * @param height {Number} the height of the renderers view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) - * - * antialias - */ -PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) -{ - if(!width)width = 800; - if(!height)height = 600; - - // BORROWED from Mr Doob (mrdoob.com) - var webgl = ( function () { try { var canvas = document.createElement( 'canvas' ); return !! window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ); } catch( e ) { return false; } } )(); - - if(webgl) - { - var ie = (navigator.userAgent.toLowerCase().indexOf('msie') != -1); - webgl = !ie; - } - - //console.log(webgl); - if( webgl ) - { - return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); - } - - return new PIXI.CanvasRenderer(width, height, view, transparent); -}; - - - -/* - PolyK library - url: http://polyk.ivank.net - Released under MIT licence. - - Copyright (c) 2012 Ivan Kuckir - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - - This is an amazing lib! - - slightly modified by mat groves (matgroves.com); -*/ - -PIXI.PolyK = {}; - -/** - * Triangulates shapes for webGL graphic fills - * - * @method Triangulate - * @namespace PolyK - * @constructor - */ -PIXI.PolyK.Triangulate = function(p) -{ - var sign = true; - - var n = p.length>>1; - if(n<3) return []; - var tgs = []; - var avl = []; - for(var i=0; i 3) - { - var i0 = avl[(i+0)%al]; - var i1 = avl[(i+1)%al]; - var i2 = avl[(i+2)%al]; - - var ax = p[2*i0], ay = p[2*i0+1]; - var bx = p[2*i1], by = p[2*i1+1]; - var cx = p[2*i2], cy = p[2*i2+1]; - - var earFound = false; - if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) - { - earFound = true; - for(var j=0; j 3*al) - { - // need to flip flip reverse it! - // reset! - if(sign) - { - var tgs = []; - avl = []; - for(var i=0; i= 0) && (v >= 0) && (u + v < 1); -} - -/** - * Checks if a shape is convex - * - * @class _convex - * @namespace PolyK - * @private - */ -PIXI.PolyK._convex = function(ax, ay, bx, by, cx, cy, sign) -{ - return ((ay-by)*(cx-bx) + (bx-ax)*(cy-by) >= 0) == sign; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -PIXI.initDefaultShaders = function() -{ - PIXI.primitiveShader = new PIXI.PrimitiveShader(); - PIXI.primitiveShader.init(); - - PIXI.stripShader = new PIXI.StripShader(); - PIXI.stripShader.init(); - - PIXI.defaultShader = new PIXI.PixiShader(); - PIXI.defaultShader.init(); - - var gl = PIXI.gl; - var shaderProgram = PIXI.defaultShader.program; - - - gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(PIXI.defaultShader.aVertexPosition); - gl.enableVertexAttribArray(PIXI.defaultShader.colorAttribute); - gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord); -} - -PIXI.activatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.primitiveShader.program); - - gl.disableVertexAttribArray(PIXI.defaultShader.aVertexPosition); - gl.disableVertexAttribArray(PIXI.defaultShader.colorAttribute); - gl.disableVertexAttribArray(PIXI.defaultShader.aTextureCoord); - - gl.enableVertexAttribArray(PIXI.primitiveShader.aVertexPosition); - gl.enableVertexAttribArray(PIXI.primitiveShader.colorAttribute); -} - -PIXI.deactivatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.defaultShader.program); - - gl.disableVertexAttribArray(PIXI.primitiveShader.aVertexPosition); - gl.disableVertexAttribArray(PIXI.primitiveShader.colorAttribute); - - gl.enableVertexAttribArray(PIXI.defaultShader.aVertexPosition); - gl.enableVertexAttribArray(PIXI.defaultShader.colorAttribute); - gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord); - -} - -PIXI.activateStripShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.stripShader.program); - // gl.disableVertexAttribArray(PIXI.defaultShader.aTextureCoord); -} - -PIXI.deactivateStripShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.defaultShader.program); - //gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord); -} - -/* - -SHADER COMPILER HELPERS -*/ - -PIXI.CompileVertexShader = function(gl, shaderSrc) -{ - return PIXI._CompileShader(gl, shaderSrc, gl.VERTEX_SHADER); -} - -PIXI.CompileFragmentShader = function(gl, shaderSrc) -{ - return PIXI._CompileShader(gl, shaderSrc, gl.FRAGMENT_SHADER); -} - -PIXI._CompileShader = function(gl, shaderSrc, shaderType) -{ - var src = shaderSrc.join("\n"); - var shader = gl.createShader(shaderType); - gl.shaderSource(shader, src); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - console.log(gl.getShaderInfoLog(shader)); - return null; - } - - return shader; -} - - -PIXI.compileProgram = function(vertexSrc, fragmentSrc) -{ - var gl = PIXI.gl; - var fragmentShader = PIXI.CompileFragmentShader(gl, fragmentSrc); - var vertexShader = PIXI.CompileVertexShader(gl, vertexSrc); - - var shaderProgram = gl.createProgram(); - - gl.attachShader(shaderProgram, vertexShader); - gl.attachShader(shaderProgram, fragmentShader); - gl.linkProgram(shaderProgram); - - if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { - console.log("Could not initialise shaders"); - } - - return shaderProgram; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -PIXI.PixiShader = function() -{ - // the webGL program.. - this.program; - - this.fragmentSrc = [ - "precision lowp float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", - "}" - ]; - -} - -PIXI.PixiShader.prototype.init = function() -{ - var program = PIXI.compileProgram(this.vertexSrc || PIXI.PixiShader.defaultVertexSrc, this.fragmentSrc) - - var gl = PIXI.gl; - - gl.useProgram(program); - - // get and store the uniforms for the shader - this.uSampler = gl.getUniformLocation(program, "uSampler"); - this.projectionVector = gl.getUniformLocation(program, "projectionVector"); - this.offsetVector = gl.getUniformLocation(program, "offsetVector"); - //this.dimensions = gl.getUniformLocation(this.program, "dimensions"); - - // get and store the attributes - this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); - this.colorAttribute = gl.getAttribLocation(program, "aColor"); - this.aTextureCoord = gl.getAttribLocation(program, "aTextureCoord"); - - // add those custom shaders! - for (var key in this.uniforms) - { - - // get the uniform locations.. - // program[key] = - this.uniforms[key].uniformLocation = gl.getUniformLocation(program, key); - - - } - - this.program = program; -} - -PIXI.PixiShader.prototype.syncUniforms = function() -{ - var gl = PIXI.gl; - - for (var key in this.uniforms) - { - //var - var type = this.uniforms[key].type; - - // need to grow this! - if(type == "f") - { - gl.uniform1f(this.uniforms[key].uniformLocation, this.uniforms[key].value); - } - if(type == "f2") - { - // console.log(this.program[key]) - gl.uniform2f(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y); - } - else if(type == "f4") - { - // console.log(this.uniforms[key].value) - gl.uniform4fv(this.uniforms[key].uniformLocation, this.uniforms[key].value); - } - else if(type == "mat4") - { - gl.uniformMatrix4fv(this.uniforms[key].uniformLocation, false, this.uniforms[key].value); - } - else if(type == "sampler2D") - { - // first texture... - var texture = this.uniforms[key].value; - - gl.activeTexture(gl.TEXTURE1); - gl.bindTexture(gl.TEXTURE_2D, texture.baseTexture._glTexture); - - gl.uniform1i(this.uniforms[key].uniformLocation, 1); - - // activate texture.. - // gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); - // gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); - } - } - -} - -PIXI.PixiShader.defaultVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - - "uniform vec2 projectionVector;", - "uniform vec2 offsetVector;", - "varying vec2 vTextureCoord;", - - "varying float vColor;", - - "const vec2 center = vec2(-1.0, 1.0);", - "void main(void) {", - "gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" -]; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -PIXI.StripShader = function() -{ - // the webGL program.. - this.program; - - this.fragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform float alpha;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", - "gl_FragColor = gl_FragColor * alpha;", - "}" - ]; - - this.vertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "varying vec2 vTextureCoord;", - "varying vec2 offsetVector;", - "varying float vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", - "v -= offsetVector.xyx;", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" - ]; -} - -PIXI.StripShader.prototype.init = function() -{ - var program = PIXI.compileProgram(this.vertexSrc, this.fragmentSrc) - - var gl = PIXI.gl; - - gl.useProgram(program); - - // get and store the uniforms for the shader - this.uSampler = gl.getUniformLocation(program, "uSampler"); - this.projectionVector = gl.getUniformLocation(program, "projectionVector"); - this.offsetVector = gl.getUniformLocation(program, "offsetVector"); - this.colorAttribute = gl.getAttribLocation(program, "aColor"); - //this.dimensions = gl.getUniformLocation(this.program, "dimensions"); - - // get and store the attributes - this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); - this.aTextureCoord = gl.getAttribLocation(program, "aTextureCoord"); - - this.translationMatrix = gl.getUniformLocation(program, "translationMatrix"); - this.alpha = gl.getUniformLocation(program, "alpha"); - - this.program = program; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -PIXI.PrimitiveShader = function() -{ - // the webGL program.. - this.program; - - this.fragmentSrc = [ - "precision mediump float;", - "varying vec4 vColor;", - "void main(void) {", - "gl_FragColor = vColor;", - "}" - ]; - - this.vertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec4 aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "uniform vec2 offsetVector;", - "uniform float alpha;", - "varying vec4 vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);", - "v -= offsetVector.xyx;", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vColor = aColor * alpha;", - "}" - ]; - -} - -PIXI.PrimitiveShader.prototype.init = function() -{ - var program = PIXI.compileProgram(this.vertexSrc, this.fragmentSrc); - - var gl = PIXI.gl; - - gl.useProgram(program); - - // get and store the uniforms for the shader - this.projectionVector = gl.getUniformLocation(program, "projectionVector"); - this.offsetVector = gl.getUniformLocation(program, "offsetVector"); - - // get and store the attributes - this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); - this.colorAttribute = gl.getAttribLocation(program, "aColor"); - - this.translationMatrix = gl.getUniformLocation(program, "translationMatrix"); - this.alpha = gl.getUniformLocation(program, "alpha"); - - this.program = program; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A set of functions used by the webGL renderer to draw the primitive graphics data - * - * @class CanvasGraphics - */ -PIXI.WebGLGraphics = function() -{ - -} - -/** - * Renders the graphics object - * - * @static - * @private - * @method renderGraphics - * @param graphics {Graphics} - * @param projection {Object} - */ -PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) -{ - var gl = PIXI.gl; - - if(!graphics._webGL)graphics._webGL = {points:[], indices:[], lastIndex:0, - buffer:gl.createBuffer(), - indexBuffer:gl.createBuffer()}; - - if(graphics.dirty) - { - graphics.dirty = false; - - if(graphics.clearDirty) - { - graphics.clearDirty = false; - - graphics._webGL.lastIndex = 0; - graphics._webGL.points = []; - graphics._webGL.indices = []; - - } - - PIXI.WebGLGraphics.updateGraphics(graphics); - } - - PIXI.activatePrimitiveShader(); - - // This could be speeded up fo sure! - var m = PIXI.mat3.clone(graphics.worldTransform); - - PIXI.mat3.transpose(m); - - // set the matrix transform for the - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - gl.uniformMatrix3fv(PIXI.primitiveShader.translationMatrix, false, m); - - gl.uniform2f(PIXI.primitiveShader.projectionVector, projection.x, -projection.y); - gl.uniform2f(PIXI.primitiveShader.offsetVector, -PIXI.offset.x, -PIXI.offset.y); - - gl.uniform1f(PIXI.primitiveShader.alpha, graphics.worldAlpha); - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - - gl.vertexAttribPointer(PIXI.primitiveShader.aVertexPosition, 2, gl.FLOAT, false, 4 * 6, 0); - gl.vertexAttribPointer(PIXI.primitiveShader.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4); - - // set the index buffer! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); - - - gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); - - PIXI.deactivatePrimitiveShader(); - - - // return to default shader... -// PIXI.activateShader(PIXI.defaultShader); -} - -/** - * Updates the graphics object - * - * @static - * @private - * @method updateGraphics - * @param graphics {Graphics} - */ -PIXI.WebGLGraphics.updateGraphics = function(graphics) -{ - for (var i=graphics._webGL.lastIndex; i < graphics.graphicsData.length; i++) - { - var data = graphics.graphicsData[i]; - - if(data.type == PIXI.Graphics.POLY) - { - if(data.fill) - { - if(data.points.length>3) - PIXI.WebGLGraphics.buildPoly(data, graphics._webGL); - } - - if(data.lineWidth > 0) - { - PIXI.WebGLGraphics.buildLine(data, graphics._webGL); - } - } - else if(data.type == PIXI.Graphics.RECT) - { - PIXI.WebGLGraphics.buildRectangle(data, graphics._webGL); - } - else if(data.type == PIXI.Graphics.CIRC || data.type == PIXI.Graphics.ELIP) - { - PIXI.WebGLGraphics.buildCircle(data, graphics._webGL); - } - }; - - graphics._webGL.lastIndex = graphics.graphicsData.length; - - var gl = PIXI.gl; - - graphics._webGL.glPoints = new Float32Array(graphics._webGL.points); - - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - gl.bufferData(gl.ARRAY_BUFFER, graphics._webGL.glPoints, gl.STATIC_DRAW); - - graphics._webGL.glIndicies = new Uint16Array(graphics._webGL.indices); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.glIndicies, gl.STATIC_DRAW); -} - -/** - * Builds a rectangle to draw - * - * @static - * @private - * @method buildRectangle - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData) -{ - // --- // - // need to convert points to a nice regular data - // - var rectData = graphicsData.points; - var x = rectData[0]; - var y = rectData[1]; - var width = rectData[2]; - var height = rectData[3]; - - - if(graphicsData.fill) - { - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var verts = webGLData.points; - var indices = webGLData.indices; - - var vertPos = verts.length/6; - - // start - verts.push(x, y); - verts.push(r, g, b, alpha); - - verts.push(x + width, y); - verts.push(r, g, b, alpha); - - verts.push(x , y + height); - verts.push(r, g, b, alpha); - - verts.push(x + width, y + height); - verts.push(r, g, b, alpha); - - // insert 2 dead triangles.. - indices.push(vertPos, vertPos, vertPos+1, vertPos+2, vertPos+3, vertPos+3) - } - - if(graphicsData.lineWidth) - { - graphicsData.points = [x, y, - x + width, y, - x + width, y + height, - x, y + height, - x, y]; - - PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); - } - -} - -/** - * Builds a circle to draw - * - * @static - * @private - * @method buildCircle - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData) -{ - // --- // - // need to convert points to a nice regular data - // - var rectData = graphicsData.points; - var x = rectData[0]; - var y = rectData[1]; - var width = rectData[2]; - var height = rectData[3]; - - var totalSegs = 40; - var seg = (Math.PI * 2) / totalSegs ; - - if(graphicsData.fill) - { - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var verts = webGLData.points; - var indices = webGLData.indices; - - var vecPos = verts.length/6; - - indices.push(vecPos); - - for (var i=0; i < totalSegs + 1 ; i++) - { - verts.push(x,y, r, g, b, alpha); - - verts.push(x + Math.sin(seg * i) * width, - y + Math.cos(seg * i) * height, - r, g, b, alpha); - - indices.push(vecPos++, vecPos++); - }; - - indices.push(vecPos-1); - } - - if(graphicsData.lineWidth) - { - graphicsData.points = []; - - for (var i=0; i < totalSegs + 1; i++) - { - graphicsData.points.push(x + Math.sin(seg * i) * width, - y + Math.cos(seg * i) * height) - }; - - PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); - } - -} - -/** - * Builds a line to draw - * - * @static - * @private - * @method buildLine - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) -{ - // TODO OPTIMISE! - - var wrap = true; - var points = graphicsData.points; - if(points.length == 0)return; - - // if the line width is an odd number add 0.5 to align to a whole pixel - if(graphicsData.lineWidth%2) - { - for (var i = 0; i < points.length; i++) { - points[i] += 0.5; - }; - } - - // get first and last point.. figure out the middle! - var firstPoint = new PIXI.Point( points[0], points[1] ); - var lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - - // if the first point is the last point - goona have issues :) - if(firstPoint.x == lastPoint.x && firstPoint.y == lastPoint.y) - { - points.pop(); - points.pop(); - - lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - - var midPointX = lastPoint.x + (firstPoint.x - lastPoint.x) *0.5; - var midPointY = lastPoint.y + (firstPoint.y - lastPoint.y) *0.5; - - points.unshift(midPointX, midPointY); - points.push(midPointX, midPointY) - } - - var verts = webGLData.points; - var indices = webGLData.indices; - var length = points.length / 2; - var indexCount = points.length; - var indexStart = verts.length/6; - - // DRAW the Line - var width = graphicsData.lineWidth / 2; - - // sort color - var color = HEXtoRGB(graphicsData.lineColor); - var alpha = graphicsData.lineAlpha; - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var p1x, p1y, p2x, p2y, p3x, p3y; - var perpx, perpy, perp2x, perp2y, perp3x, perp3y; - var ipx, ipy; - var a1, b1, c1, a2, b2, c2; - var denom, pdist, dist; - - p1x = points[0]; - p1y = points[1]; - - p2x = points[2]; - p2y = points[3]; - - perpx = -(p1y - p2y); - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - // start - verts.push(p1x - perpx , p1y - perpy, - r, g, b, alpha); - - verts.push(p1x + perpx , p1y + perpy, - r, g, b, alpha); - - for (var i = 1; i < length-1; i++) - { - p1x = points[(i-1)*2]; - p1y = points[(i-1)*2 + 1]; - - p2x = points[(i)*2] - p2y = points[(i)*2 + 1] - - p3x = points[(i+1)*2]; - p3y = points[(i+1)*2 + 1]; - - perpx = -(p1y - p2y); - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - perp2x = -(p2y - p3y); - perp2y = p2x - p3x; - - dist = Math.sqrt(perp2x*perp2x + perp2y*perp2y); - perp2x /= dist; - perp2y /= dist; - perp2x *= width; - perp2y *= width; - - a1 = (-perpy + p1y) - (-perpy + p2y); - b1 = (-perpx + p2x) - (-perpx + p1x); - c1 = (-perpx + p1x) * (-perpy + p2y) - (-perpx + p2x) * (-perpy + p1y); - a2 = (-perp2y + p3y) - (-perp2y + p2y); - b2 = (-perp2x + p2x) - (-perp2x + p3x); - c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y); - - denom = a1*b2 - a2*b1; - - if(Math.abs(denom) < 0.1 ) - { - - denom+=10.1; - verts.push(p2x - perpx , p2y - perpy, - r, g, b, alpha); - - verts.push(p2x + perpx , p2y + perpy, - r, g, b, alpha); - - continue; - } - - px = (b1*c2 - b2*c1)/denom; - py = (a2*c1 - a1*c2)/denom; - - - pdist = (px -p2x) * (px -p2x) + (py -p2y) + (py -p2y); - - - if(pdist > 140 * 140) - { - perp3x = perpx - perp2x; - perp3y = perpy - perp2y; - - dist = Math.sqrt(perp3x*perp3x + perp3y*perp3y); - perp3x /= dist; - perp3y /= dist; - perp3x *= width; - perp3y *= width; - - verts.push(p2x - perp3x, p2y -perp3y); - verts.push(r, g, b, alpha); - - verts.push(p2x + perp3x, p2y +perp3y); - verts.push(r, g, b, alpha); - - verts.push(p2x - perp3x, p2y -perp3y); - verts.push(r, g, b, alpha); - - indexCount++; - } - else - { - - verts.push(px , py); - verts.push(r, g, b, alpha); - - verts.push(p2x - (px-p2x), p2y - (py - p2y)); - verts.push(r, g, b, alpha); - } - } - - p1x = points[(length-2)*2] - p1y = points[(length-2)*2 + 1] - - p2x = points[(length-1)*2] - p2y = points[(length-1)*2 + 1] - - perpx = -(p1y - p2y) - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - verts.push(p2x - perpx , p2y - perpy) - verts.push(r, g, b, alpha); - - verts.push(p2x + perpx , p2y + perpy) - verts.push(r, g, b, alpha); - - indices.push(indexStart); - - for (var i=0; i < indexCount; i++) - { - indices.push(indexStart++); - }; - - indices.push(indexStart-1); -} - -/** - * Builds a polygon to draw - * - * @static - * @private - * @method buildPoly - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData) -{ - var points = graphicsData.points; - if(points.length < 6)return; - - // get first and last point.. figure out the middle! - var verts = webGLData.points; - var indices = webGLData.indices; - - var length = points.length / 2; - - // sort color - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var triangles = PIXI.PolyK.Triangulate(points); - - var vertPos = verts.length / 6; - - for (var i=0; i < triangles.length; i+=3) - { - indices.push(triangles[i] + vertPos); - indices.push(triangles[i] + vertPos); - indices.push(triangles[i+1] + vertPos); - indices.push(triangles[i+2] +vertPos); - indices.push(triangles[i+2] + vertPos); - }; - - for (var i = 0; i < length; i++) - { - verts.push(points[i * 2], points[i * 2 + 1], - r, g, b, alpha); - }; -} - -function HEXtoRGB(hex) { - return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; -} - - - - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI._defaultFrame = new PIXI.Rectangle(0,0,1,1); - -// an instance of the gl context.. -// only one at the moment :/ -PIXI.gl; - -/** - * the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer - * should be used for browsers support webGL. This Render works by automatically managing webGLBatchs. - * So no need for Sprite Batch's or Sprite Cloud's - * Dont forget to add the view to your DOM or you will not see anything :) - * - * @class WebGLRenderer - * @constructor - * @param width=0 {Number} the width of the canvas view - * @param height=0 {Number} the height of the canvas view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) - * - */ -PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) -{ - // do a catch.. only 1 webGL renderer.. - - this.transparent = !!transparent; - - this.width = width || 800; - this.height = height || 600; - - this.view = view || document.createElement( 'canvas' ); - this.view.width = this.width; - this.view.height = this.height; - - // deal with losing context.. - var scope = this; - this.view.addEventListener('webglcontextlost', function(event) { scope.handleContextLost(event); }, false) - this.view.addEventListener('webglcontextrestored', function(event) { scope.handleContextRestored(event); }, false) - - this.batchs = []; - - var options = { - alpha: this.transparent, - antialias:!!antialias, // SPEED UP?? - premultipliedAlpha:false, - stencil:true - } - - //try 'experimental-webgl' - try { - PIXI.gl = this.gl = this.view.getContext("experimental-webgl", options); - } catch (e) { - //try 'webgl' - try { - PIXI.gl = this.gl = this.view.getContext("webgl", options); - } catch (e) { - // fail, not able to get a context - throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); - } - } - - PIXI.initDefaultShaders(); - - - - - // PIXI.activateDefaultShader(); - - var gl = this.gl; - - gl.useProgram(PIXI.defaultShader.program); - - - PIXI.WebGLRenderer.gl = gl; - - this.batch = new PIXI.WebGLBatch(gl); - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - - gl.enable(gl.BLEND); - gl.colorMask(true, true, true, this.transparent); - - PIXI.projection = new PIXI.Point(400, 300); - PIXI.offset = new PIXI.Point(0, 0); - - // TODO remove thease globals.. - - this.resize(this.width, this.height); - this.contextLost = false; - - //PIXI.pushShader(PIXI.defaultShader); - - this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl, this.transparent); - // this.stageRenderGroup. = this.transparent -} - -// constructor -PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; - -/** - * Gets a new WebGLBatch from the pool - * - * @static - * @method getBatch - * @return {WebGLBatch} - * @private - */ -PIXI.WebGLRenderer.getBatch = function() -{ - if(PIXI._batchs.length == 0) - { - return new PIXI.WebGLBatch(PIXI.WebGLRenderer.gl); - } - else - { - return PIXI._batchs.pop(); - } -} - -/** - * Puts a batch back into the pool - * - * @static - * @method returnBatch - * @param batch {WebGLBatch} The batch to return - * @private - */ -PIXI.WebGLRenderer.returnBatch = function(batch) -{ - batch.clean(); - PIXI._batchs.push(batch); -} - -/** - * Renders the stage to its webGL view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.WebGLRenderer.prototype.render = function(stage) -{ - if(this.contextLost)return; - - - // if rendering a new stage clear the batchs.. - if(this.__stage !== stage) - { - // TODO make this work - // dont think this is needed any more? - this.__stage = stage; - this.stageRenderGroup.setRenderable(stage); - } - - // update any textures - PIXI.WebGLRenderer.updateTextures(); - - // update the scene graph - PIXI.visibleCount++; - stage.updateTransform(); - - var gl = this.gl; - - // -- Does this need to be set every frame? -- // - gl.colorMask(true, true, true, this.transparent); - gl.viewport(0, 0, this.width, this.height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); - gl.clear(gl.COLOR_BUFFER_BIT); - - // HACK TO TEST - - this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; - - PIXI.projection.x = this.width/2; - PIXI.projection.y = -this.height/2; - - this.stageRenderGroup.render(PIXI.projection); - - // interaction - // run interaction! - if(stage.interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - - // after rendering lets confirm all frames that have been uodated.. - if(PIXI.Texture.frameUpdates.length > 0) - { - for (var i=0; i < PIXI.Texture.frameUpdates.length; i++) - { - PIXI.Texture.frameUpdates[i].updateFrame = false; - }; - - PIXI.Texture.frameUpdates = []; - } -} - -/** - * Updates the textures loaded into this webgl renderer - * - * @static - * @method updateTextures - * @private - */ -PIXI.WebGLRenderer.updateTextures = function() -{ - //TODO break this out into a texture manager... - for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); - PIXI.texturesToUpdate = []; - PIXI.texturesToDestroy = []; -} - -/** - * Updates a loaded webgl texture - * - * @static - * @method updateTexture - * @param texture {Texture} The texture to update - * @private - */ -PIXI.WebGLRenderer.updateTexture = function(texture) -{ - //TODO break this out into a texture manager... - var gl = PIXI.gl; - - if(!texture._glTexture) - { - texture._glTexture = gl.createTexture(); - } - - if(texture.hasLoaded) - { - gl.bindTexture(gl.TEXTURE_2D, texture._glTexture); - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - - // reguler... - - if(!texture._powerOf2) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - } - - gl.bindTexture(gl.TEXTURE_2D, null); - } -} - -/** - * Destroys a loaded webgl texture - * - * @method destroyTexture - * @param texture {Texture} The texture to update - * @private - */ -PIXI.WebGLRenderer.destroyTexture = function(texture) -{ - //TODO break this out into a texture manager... - var gl = PIXI.gl; - - if(texture._glTexture) - { - texture._glTexture = gl.createTexture(); - gl.deleteTexture(gl.TEXTURE_2D, texture._glTexture); - } -} - -/** - * resizes the webGL view to the specified width and height - * - * @method resize - * @param width {Number} the new width of the webGL view - * @param height {Number} the new height of the webGL view - */ -PIXI.WebGLRenderer.prototype.resize = function(width, height) -{ - this.width = width; - this.height = height; - - this.view.width = width; - this.view.height = height; - - this.gl.viewport(0, 0, this.width, this.height); - - //var projectionMatrix = this.projectionMatrix; - - PIXI.projection.x = this.width/2; - PIXI.projection.y = -this.height/2; - - //PIXI.size.x = this.width/2; - //PIXI.size.y = -this.height/2; - -// projectionMatrix[0] = 2/this.width; -// projectionMatrix[5] = -2/this.height; -// projectionMatrix[12] = -1; -// projectionMatrix[13] = 1; -} - -/** - * Handles a lost webgl context - * - * @method handleContextLost - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextLost = function(event) -{ - event.preventDefault(); - this.contextLost = true; -} - -/** - * Handles a restored webgl context - * - * @method handleContextRestored - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextRestored = function(event) -{ - this.gl = this.view.getContext("experimental-webgl", { - alpha: true - }); - - this.initShaders(); - - for(var key in PIXI.TextureCache) - { - var texture = PIXI.TextureCache[key].baseTexture; - texture._glTexture = null; - PIXI.WebGLRenderer.updateTexture(texture); - }; - - for (var i=0; i < this.batchs.length; i++) - { - this.batchs[i].restoreLostContext(this.gl)// - this.batchs[i].dirty = true; - }; - - PIXI._restoreBatchs(this.gl); - - this.contextLost = false; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI._batchs = []; - -/** - * @private - */ -PIXI._getBatch = function(gl) -{ - if(PIXI._batchs.length == 0) - { - return new PIXI.WebGLBatch(gl); - } - else - { - return PIXI._batchs.pop(); - } -} - -/** - * @private - */ -PIXI._returnBatch = function(batch) -{ - batch.clean(); - PIXI._batchs.push(batch); -} - -/** - * @private - */ -PIXI._restoreBatchs = function(gl) -{ - for (var i=0; i < PIXI._batchs.length; i++) - { - PIXI._batchs[i].restoreLostContext(gl); - }; -} - -/** - * A WebGLBatch Enables a group of sprites to be drawn using the same settings. - * if a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch. - * All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites - * in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled - * automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster - * the webGL renderer will run. - * - * @class WebGLBatch - * @constructor - * @param gl {WebGLContext} an instance of the webGL context - */ -PIXI.WebGLBatch = function(gl) -{ - this.gl = gl; - - this.size = 0; - - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); - this.blendMode = PIXI.blendModes.NORMAL; - this.dynamicSize = 1; -} - -// constructor -PIXI.WebGLBatch.prototype.constructor = PIXI.WebGLBatch; - -/** - * Cleans the batch so that is can be returned to an object pool and reused - * - * @method clean - */ -PIXI.WebGLBatch.prototype.clean = function() -{ - this.verticies = []; - this.uvs = []; - this.indices = []; - this.colors = []; - this.dynamicSize = 1; - this.texture = null; - this.last = null; - this.size = 0; - this.head; - this.tail; -} - -/** - * Recreates the buffers in the event of a context loss - * - * @method restoreLostContext - * @param gl {WebGLContext} - */ -PIXI.WebGLBatch.prototype.restoreLostContext = function(gl) -{ - this.gl = gl; - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); -} - -/** - * inits the batch's texture and blend mode based if the supplied sprite - * - * @method init - * @param sprite {Sprite} the first sprite to be added to the batch. Only sprites with - * the same base texture and blend mode will be allowed to be added to this batch - */ -PIXI.WebGLBatch.prototype.init = function(sprite) -{ - sprite.batch = this; - this.dirty = true; - this.blendMode = sprite.blendMode; - this.texture = sprite.texture.baseTexture; - this.head = sprite; - this.tail = sprite; - this.size = 1; - - this.growBatch(); -} - -/** - * inserts a sprite before the specified sprite - * - * @method insertBefore - * @param sprite {Sprite} the sprite to be added - * @param nextSprite {nextSprite} the first sprite will be inserted before this sprite - */ -PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) -{ - this.size++; - - sprite.batch = this; - this.dirty = true; - var tempPrev = nextSprite.__prev; - nextSprite.__prev = sprite; - sprite.__next = nextSprite; - - if(tempPrev) - { - sprite.__prev = tempPrev; - tempPrev.__next = sprite; - } - else - { - this.head = sprite; - } -} - -/** - * inserts a sprite after the specified sprite - * - * @method insertAfter - * @param sprite {Sprite} the sprite to be added - * @param previousSprite {Sprite} the first sprite will be inserted after this sprite - */ -PIXI.WebGLBatch.prototype.insertAfter = function(sprite, previousSprite) -{ - this.size++; - - sprite.batch = this; - this.dirty = true; - - var tempNext = previousSprite.__next; - previousSprite.__next = sprite; - sprite.__prev = previousSprite; - - if(tempNext) - { - sprite.__next = tempNext; - tempNext.__prev = sprite; - } - else - { - this.tail = sprite - } -} - -/** - * removes a sprite from the batch - * - * @method remove - * @param sprite {Sprite} the sprite to be removed - */ -PIXI.WebGLBatch.prototype.remove = function(sprite) -{ - this.size--; - - if(this.size == 0) - { - sprite.batch = null; - sprite.__prev = null; - sprite.__next = null; - return; - } - - if(sprite.__prev) - { - sprite.__prev.__next = sprite.__next; - } - else - { - this.head = sprite.__next; - this.head.__prev = null; - } - - if(sprite.__next) - { - sprite.__next.__prev = sprite.__prev; - } - else - { - this.tail = sprite.__prev; - this.tail.__next = null - } - - sprite.batch = null; - sprite.__next = null; - sprite.__prev = null; - this.dirty = true; -} - -/** - * Splits the batch into two with the specified sprite being the start of the new batch. - * - * @method split - * @param sprite {Sprite} the sprite that indicates where the batch should be split - * @return {WebGLBatch} the new batch - */ -PIXI.WebGLBatch.prototype.split = function(sprite) -{ - this.dirty = true; - - var batch = new PIXI.WebGLBatch(this.gl); - batch.init(sprite); - batch.texture = this.texture; - batch.tail = this.tail; - - this.tail = sprite.__prev; - this.tail.__next = null; - - sprite.__prev = null; - // return a splite batch! - - // TODO this size is wrong! - // need to recalculate :/ problem with a linked list! - // unless it gets calculated in the "clean"? - - // need to loop through items as there is no way to know the length on a linked list :/ - var tempSize = 0; - while(sprite) - { - tempSize++; - sprite.batch = batch; - sprite = sprite.__next; - } - - batch.size = tempSize; - this.size -= tempSize; - - return batch; -} - -/** - * Merges two batchs together - * - * @method merge - * @param batch {WebGLBatch} the batch that will be merged - */ -PIXI.WebGLBatch.prototype.merge = function(batch) -{ - this.dirty = true; - - this.tail.__next = batch.head; - batch.head.__prev = this.tail; - - this.size += batch.size; - - this.tail = batch.tail; - - var sprite = batch.head; - while(sprite) - { - sprite.batch = this; - sprite = sprite.__next; - } -} - -/** - * Grows the size of the batch. As the elements in the batch cannot have a dynamic size this - * function is used to increase the size of the batch. It also creates a little extra room so - * that the batch does not need to be resized every time a sprite is added - * - * @method growBatch - */ -PIXI.WebGLBatch.prototype.growBatch = function() -{ - var gl = this.gl; - if( this.size == 1) - { - this.dynamicSize = 1; - } - else - { - this.dynamicSize = this.size * 1.5 - } - // grow verts - this.verticies = new Float32Array(this.dynamicSize * 8); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); - - this.uvs = new Float32Array( this.dynamicSize * 8 ); - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); - - this.dirtyUVS = true; - - this.colors = new Float32Array( this.dynamicSize * 4 ); - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); - - this.dirtyColors = true; - - this.indices = new Uint16Array(this.dynamicSize * 6); - var length = this.indices.length/6; - - for (var i=0; i < length; i++) - { - var index2 = i * 6; - var index3 = i * 4; - this.indices[index2 + 0] = index3 + 0; - this.indices[index2 + 1] = index3 + 1; - this.indices[index2 + 2] = index3 + 2; - this.indices[index2 + 3] = index3 + 0; - this.indices[index2 + 4] = index3 + 2; - this.indices[index2 + 5] = index3 + 3; - }; - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); -} - -/** - * Refresh's all the data in the batch and sync's it with the webGL buffers - * - * @method refresh - */ -PIXI.WebGLBatch.prototype.refresh = function() -{ - var gl = this.gl; - - if (this.dynamicSize < this.size) - { - this.growBatch(); - } - - var indexRun = 0; - var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index; - var a, b, c, d, tx, ty; - - var displayObject = this.head; - - while(displayObject) - { - index = indexRun * 8; - - var texture = displayObject.texture; - - var frame = texture.frame; - var tw = texture.baseTexture.width; - var th = texture.baseTexture.height; - - this.uvs[index + 0] = frame.x / tw; - this.uvs[index +1] = frame.y / th; - - this.uvs[index +2] = (frame.x + frame.width) / tw; - this.uvs[index +3] = frame.y / th; - - this.uvs[index +4] = (frame.x + frame.width) / tw; - this.uvs[index +5] = (frame.y + frame.height) / th; - - this.uvs[index +6] = frame.x / tw; - this.uvs[index +7] = (frame.y + frame.height) / th; - - displayObject.updateFrame = false; - - colorIndex = indexRun * 4; - this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; - - displayObject = displayObject.__next; - - indexRun ++; - } - - this.dirtyUVS = true; - this.dirtyColors = true; -} - -/** - * Updates all the relevant geometry and uploads the data to the GPU - * - * @method update - */ -PIXI.WebGLBatch.prototype.update = function() -{ - var gl = this.gl; - var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index, index2, index3 - - var a, b, c, d, tx, ty; - - var indexRun = 0; - - var displayObject = this.head; - var verticies = this.verticies; - var uvs = this.uvs; - var colors = this.colors; - - while(displayObject) - { - if(displayObject.vcount === PIXI.visibleCount) - { - width = displayObject.texture.frame.width; - height = displayObject.texture.frame.height; - - // TODO trim?? - aX = displayObject.anchor.x;// - displayObject.texture.trim.x - aY = displayObject.anchor.y; //- displayObject.texture.trim.y - w0 = width * (1-aX); - w1 = width * -aX; - - h0 = height * (1-aY); - h1 = height * -aY; - - index = indexRun * 8; - - worldTransform = displayObject.worldTransform; - - a = worldTransform[0]; - b = worldTransform[3]; - c = worldTransform[1]; - d = worldTransform[4]; - tx = worldTransform[2]; - ty = worldTransform[5]; - - verticies[index + 0 ] = a * w1 + c * h1 + tx; - verticies[index + 1 ] = d * h1 + b * w1 + ty; - - verticies[index + 2 ] = a * w0 + c * h1 + tx; - verticies[index + 3 ] = d * h1 + b * w0 + ty; - - verticies[index + 4 ] = a * w0 + c * h0 + tx; - verticies[index + 5 ] = d * h0 + b * w0 + ty; - - verticies[index + 6] = a * w1 + c * h0 + tx; - verticies[index + 7] = d * h0 + b * w1 + ty; - - if(displayObject.updateFrame || displayObject.texture.updateFrame) - { - this.dirtyUVS = true; - - var texture = displayObject.texture; - - var frame = texture.frame; - var tw = texture.baseTexture.width; - var th = texture.baseTexture.height; - - uvs[index + 0] = frame.x / tw; - uvs[index +1] = frame.y / th; - - uvs[index +2] = (frame.x + frame.width) / tw; - uvs[index +3] = frame.y / th; - - uvs[index +4] = (frame.x + frame.width) / tw; - uvs[index +5] = (frame.y + frame.height) / th; - - uvs[index +6] = frame.x / tw; - uvs[index +7] = (frame.y + frame.height) / th; - - displayObject.updateFrame = false; - } - - // TODO this probably could do with some optimisation.... - if(displayObject.cacheAlpha != displayObject.worldAlpha) - { - displayObject.cacheAlpha = displayObject.worldAlpha; - - var colorIndex = indexRun * 4; - colors[colorIndex] = colors[colorIndex + 1] = colors[colorIndex + 2] = colors[colorIndex + 3] = displayObject.worldAlpha; - this.dirtyColors = true; - } - } - else - { - index = indexRun * 8; - - verticies[index + 0 ] = verticies[index + 1 ] = verticies[index + 2 ] = verticies[index + 3 ] = verticies[index + 4 ] = verticies[index + 5 ] = verticies[index + 6] = verticies[index + 7] = 0; - } - - indexRun++; - displayObject = displayObject.__next; - } -} - -/** - * Draws the batch to the frame buffer - * - * @method render - */ -PIXI.WebGLBatch.prototype.render = function(start, end) -{ - start = start || 0; - - if(end == undefined)end = this.size; - - if(this.dirty) - { - this.refresh(); - this.dirty = false; - } - - if (this.size == 0)return; - - this.update(); - var gl = this.gl; - - //TODO optimize this! - - var shaderProgram = PIXI.defaultShader; - - //gl.useProgram(shaderProgram); - - // update the verts.. - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - // ok.. - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) - gl.vertexAttribPointer(shaderProgram.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - // update the uvs - //var isDefault = (shaderProgram == PIXI.shaderProgram) - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - - if(this.dirtyUVS) - { - this.dirtyUVS = false; - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvs); - } - - gl.vertexAttribPointer(shaderProgram.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this.texture._glTexture); - - // update color! - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - - if(this.dirtyColors) - { - this.dirtyColors = false; - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.colors); - } - - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - var len = end - start; - - // DRAW THAT this! - gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A WebGLBatch Enables a group of sprites to be drawn using the same settings. - * if a group of sprites all have the same baseTexture and blendMode then they can be - * grouped into a batch. All the sprites in a batch can then be drawn in one go by the - * GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch - * even if the batch only contains one sprite. Batching is handled automatically by the - * webGL renderer. A good tip is: the smaller the number of batchs there are, the faster - * the webGL renderer will run. - * - * @class WebGLBatch - * @contructor - * @param gl {WebGLContext} An instance of the webGL context - */ -PIXI.WebGLRenderGroup = function(gl, transparent) -{ - this.gl = gl; - this.root; - - this.backgroundColor; - this.transparent = transparent == undefined ? true : transparent; - - this.batchs = []; - this.toRemove = []; - console.log(this.transparent) - this.filterManager = new PIXI.WebGLFilterManager(this.transparent); -} - -// constructor -PIXI.WebGLRenderGroup.prototype.constructor = PIXI.WebGLRenderGroup; - -/** - * Add a display object to the webgl renderer - * - * @method setRenderable - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.setRenderable = function(displayObject) -{ - // has this changed?? - if(this.root)this.removeDisplayObjectAndChildren(this.root); - - displayObject.worldVisible = displayObject.visible; - - // soooooo // - // to check if any batchs exist already?? - - // TODO what if its already has an object? should remove it - this.root = displayObject; - this.addDisplayObjectAndChildren(displayObject); -} - -/** - * Renders the stage to its webgl view - * - * @method render - * @param projection {Object} - */ -PIXI.WebGLRenderGroup.prototype.render = function(projection, buffer) -{ - PIXI.WebGLRenderer.updateTextures(); - - var gl = this.gl; - gl.uniform2f(PIXI.defaultShader.projectionVector, projection.x, projection.y); - - this.filterManager.begin(projection, buffer); - - - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - // will render all the elements in the group - var renderable; - - for (var i=0; i < this.batchs.length; i++) - { - - renderable = this.batchs[i]; - if(renderable instanceof PIXI.WebGLBatch) - { - this.batchs[i].render(); - continue; - } - - // render special - this.renderSpecial(renderable, projection); - } - -} - -/** - * Renders a specific displayObject - * - * @method renderSpecific - * @param displayObject {DisplayObject} - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection, buffer) -{ - PIXI.WebGLRenderer.updateTextures(); - var gl = this.gl; - - gl.uniform2f(PIXI.defaultShader.projectionVector, projection.x, projection.y); - - this.filterManager.begin(projection, buffer); - - // to do! - // render part of the scene... - - var startIndex; - var startBatchIndex; - - var endIndex; - var endBatchIndex; - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.first; - while(nextRenderable._iNext) - { - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - nextRenderable = nextRenderable._iNext; - } - var startBatch = nextRenderable.batch; - //console.log(nextRenderable); - - //console.log(renderable) - if(nextRenderable instanceof PIXI.Sprite) - { - startBatch = nextRenderable.batch; - - var head = startBatch.head; - var next = head; - - // ok now we have the batch.. need to find the start index! - if(head == nextRenderable) - { - startIndex = 0; - } - else - { - startIndex = 1; - - while(head.__next != nextRenderable) - { - startIndex++; - head = head.__next; - } - } - } - else - { - startBatch = nextRenderable; - } - - // Get the LAST renderable object - var lastRenderable = displayObject.last; - while(lastRenderable._iPrev) - { - if(lastRenderable.renderable && lastRenderable.__renderGroup)break; - lastRenderable = lastRenderable._iNext; - } - - if(lastRenderable instanceof PIXI.Sprite) - { - endBatch = lastRenderable.batch; - - var head = endBatch.head; - - if(head == lastRenderable) - { - endIndex = 0; - } - else - { - endIndex = 1; - - while(head.__next != lastRenderable) - { - endIndex++; - head = head.__next; - } - } - } - else - { - endBatch = lastRenderable; - } - - //console.log(endBatch); - // TODO - need to fold this up a bit! - - if(startBatch == endBatch) - { - if(startBatch instanceof PIXI.WebGLBatch) - { - startBatch.render(startIndex, endIndex+1); - } - else - { - this.renderSpecial(startBatch, projection); - } - return; - } - - // now we have first and last! - startBatchIndex = this.batchs.indexOf(startBatch); - endBatchIndex = this.batchs.indexOf(endBatch); - - // DO the first batch - if(startBatch instanceof PIXI.WebGLBatch) - { - startBatch.render(startIndex); - } - else - { - this.renderSpecial(startBatch, projection); - } - - // DO the middle batchs.. - for (var i=startBatchIndex+1; i < endBatchIndex; i++) - { - renderable = this.batchs[i]; - - if(renderable instanceof PIXI.WebGLBatch) - { - this.batchs[i].render(); - } - else - { - this.renderSpecial(renderable, projection); - } - } - - // DO the last batch.. - if(endBatch instanceof PIXI.WebGLBatch) - { - endBatch.render(0, endIndex+1); - } - else - { - this.renderSpecial(endBatch, projection); - } -} - -/** - * Renders a specific renderable - * - * @method renderSpecial - * @param renderable {DisplayObject} - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) -{ - - var worldVisible = renderable.vcount === PIXI.visibleCount - - - if(renderable instanceof PIXI.TilingSprite) - { - if(worldVisible)this.renderTilingSprite(renderable, projection); - } - else if(renderable instanceof PIXI.Strip) - { - if(worldVisible)this.renderStrip(renderable, projection); - } - else if(renderable instanceof PIXI.CustomRenderable) - { - if(worldVisible) renderable.renderWebGL(this, projection); - } - else if(renderable instanceof PIXI.Graphics) - { - if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); - } - else if(renderable instanceof PIXI.FilterBlock) - { - this.handleFilterBlock(renderable, projection); - } -} - -flip = false; -var maskStack = []; -var maskPosition = 0; - -//var usedMaskStack = []; - -PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(filterBlock, projection) -{ - /* - * for now only masks are supported.. - */ - var gl = PIXI.gl; - - if(filterBlock.open) - { - if(filterBlock.data instanceof Array) - { - this.filterManager.pushFilter(filterBlock); - // ok so.. - - } - else - { - maskPosition++; - - maskStack.push(filterBlock) - - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - - gl.stencilFunc(gl.ALWAYS,1,1); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.INCR); - - PIXI.WebGLGraphics.renderGraphics(filterBlock.data, projection); - - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL,0,maskStack.length); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - } - else - { - if(filterBlock.data instanceof Array) - { - this.filterManager.popFilter(); - } - else - { - var maskData = maskStack.pop(filterBlock) - - - if(maskData) - { - gl.colorMask(false, false, false, false); - - gl.stencilFunc(gl.ALWAYS,1,1); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.DECR); - - PIXI.WebGLGraphics.renderGraphics(maskData.data, projection); - - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL,0,maskStack.length); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - }; - - gl.disable(gl.STENCIL_TEST); - } - } -} - -/** - * Updates a webgl texture - * - * @method updateTexture - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject) -{ - - // TODO definitely can optimse this function.. - - this.removeObject(displayObject); - - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - var previousRenderable = displayObject.first; - while(previousRenderable != this.root) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.last; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - - this.insertObject(displayObject, previousRenderable, nextRenderable); -} - -/** - * Adds filter blocks - * - * @method addFilterBlocks - * @param start {FilterBlock} - * @param end {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) -{ - start.__renderGroup = this; - end.__renderGroup = this; - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - var previousRenderable = start; - while(previousRenderable != this.root.first) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - this.insertAfter(start, previousRenderable); - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var previousRenderable2 = end; - while(previousRenderable2 != this.root.first) - { - previousRenderable2 = previousRenderable2._iPrev; - if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; - } - this.insertAfter(end, previousRenderable2); -} - -/** - * Remove filter blocks - * - * @method removeFilterBlocks - * @param start {FilterBlock} - * @param end {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeFilterBlocks = function(start, end) -{ - this.removeObject(start); - this.removeObject(end); -} - -/** - * Adds a display object and children to the webgl context - * - * @method addDisplayObjectAndChildren - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayObject) -{ - if(displayObject.__renderGroup)displayObject.__renderGroup.removeDisplayObjectAndChildren(displayObject); - - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - - var previousRenderable = displayObject.first; - while(previousRenderable != this.root.first) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.last; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - - // one the display object hits this. we can break the loop - - var tempObject = displayObject.first; - var testObject = displayObject.last._iNext; - do - { - tempObject.__renderGroup = this; - - if(tempObject.renderable) - { - - this.insertObject(tempObject, previousRenderable, nextRenderable); - previousRenderable = tempObject; - } - - tempObject = tempObject._iNext; - } - while(tempObject != testObject) -} - -/** - * Removes a display object and children to the webgl context - * - * @method removeDisplayObjectAndChildren - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren = function(displayObject) -{ - if(displayObject.__renderGroup != this)return; - -// var displayObject = displayObject.first; - var lastObject = displayObject.last; - do - { - displayObject.__renderGroup = null; - if(displayObject.renderable)this.removeObject(displayObject); - displayObject = displayObject._iNext; - } - while(displayObject) -} - -/** - * Inserts a displayObject into the linked list - * - * @method insertObject - * @param displayObject {DisplayObject} - * @param previousObject {DisplayObject} - * @param nextObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousObject, nextObject) -{ - // while looping below THE OBJECT MAY NOT HAVE BEEN ADDED - var previousSprite = previousObject; - var nextSprite = nextObject; - - /* - * so now we have the next renderable and the previous renderable - * - */ - if(displayObject instanceof PIXI.Sprite) - { - var previousBatch - var nextBatch - - if(previousSprite instanceof PIXI.Sprite) - { - previousBatch = previousSprite.batch; - if(previousBatch) - { - if(previousBatch.texture == displayObject.texture.baseTexture && previousBatch.blendMode == displayObject.blendMode) - { - previousBatch.insertAfter(displayObject, previousSprite); - return; - } - } - } - else - { - // TODO reword! - previousBatch = previousSprite; - } - - if(nextSprite) - { - if(nextSprite instanceof PIXI.Sprite) - { - nextBatch = nextSprite.batch; - - //batch may not exist if item was added to the display list but not to the webGL - if(nextBatch) - { - if(nextBatch.texture == displayObject.texture.baseTexture && nextBatch.blendMode == displayObject.blendMode) - { - nextBatch.insertBefore(displayObject, nextSprite); - return; - } - else - { - if(nextBatch == previousBatch) - { - // THERE IS A SPLIT IN THIS BATCH! // - var splitBatch = previousBatch.split(nextSprite); - // COOL! - // add it back into the array - /* - * OOPS! - * seems the new sprite is in the middle of a batch - * lets split it.. - */ - var batch = PIXI.WebGLRenderer.getBatch(); - - var index = this.batchs.indexOf( previousBatch ); - batch.init(displayObject); - this.batchs.splice(index+1, 0, batch, splitBatch); - - return; - } - } - } - } - else - { - // TODO re-word! - - nextBatch = nextSprite; - } - } - - /* - * looks like it does not belong to any batch! - * but is also not intersecting one.. - * time to create anew one! - */ - - var batch = PIXI.WebGLRenderer.getBatch(); - batch.init(displayObject); - - if(previousBatch) // if this is invalid it means - { - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, batch); - } - else - { - this.batchs.push(batch); - } - - return; - } - else if(displayObject instanceof PIXI.TilingSprite) - { - - // add to a batch!! - this.initTilingSprite(displayObject); - // this.batchs.push(displayObject); - - } - else if(displayObject instanceof PIXI.Strip) - { - // add to a batch!! - this.initStrip(displayObject); - // this.batchs.push(displayObject); - } - else if(displayObject)// instanceof PIXI.Graphics) - { - //displayObject.initWebGL(this); - - // add to a batch!! - //this.initStrip(displayObject); - //this.batchs.push(displayObject); - } - - this.insertAfter(displayObject, previousSprite); - - // insert and SPLIT! - -} - -/** - * Inserts a displayObject into the linked list - * - * @method insertAfter - * @param item {DisplayObject} - * @param displayObject {DisplayObject} The object to insert - * @private - */ -PIXI.WebGLRenderGroup.prototype.insertAfter = function(item, displayObject) -{ - if(displayObject instanceof PIXI.Sprite) - { - var previousBatch = displayObject.batch; - - if(previousBatch) - { - // so this object is in a batch! - - // is it not? need to split the batch - if(previousBatch.tail == displayObject) - { - // is it tail? insert in to batchs - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, item); - } - else - { - // TODO MODIFY ADD / REMOVE CHILD TO ACCOUNT FOR FILTERS (also get prev and next) // - - // THERE IS A SPLIT IN THIS BATCH! // - var splitBatch = previousBatch.split(displayObject.__next); - - // COOL! - // add it back into the array - /* - * OOPS! - * seems the new sprite is in the middle of a batch - * lets split it.. - */ - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, item, splitBatch); - } - } - else - { - this.batchs.push(item); - } - } - else - { - var index = this.batchs.indexOf( displayObject ); - this.batchs.splice(index+1, 0, item); - } -} - -/** - * Removes a displayObject from the linked list - * - * @method removeObject - * @param displayObject {DisplayObject} The object to remove - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) -{ - // loop through children.. - // display object // - - // add a child from the render group.. - // remove it and all its children! - //displayObject.cacheVisible = false;//displayObject.visible; - - /* - * removing is a lot quicker.. - * - */ - var batchToRemove; - - if(displayObject instanceof PIXI.Sprite) - { - // should always have a batch! - var batch = displayObject.batch; - if(!batch)return; // this means the display list has been altered befre rendering - - batch.remove(displayObject); - - if(batch.size==0) - { - batchToRemove = batch; - } - } - else - { - batchToRemove = displayObject; - } - - /* - * Looks like there is somthing that needs removing! - */ - if(batchToRemove) - { - var index = this.batchs.indexOf( batchToRemove ); - if(index == -1)return;// this means it was added then removed before rendered - - // ok so.. check to see if you adjacent batchs should be joined. - // TODO may optimise? - if(index == 0 || index == this.batchs.length-1) - { - // wha - eva! just get of the empty batch! - this.batchs.splice(index, 1); - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - - return; - } - - if(this.batchs[index-1] instanceof PIXI.WebGLBatch && this.batchs[index+1] instanceof PIXI.WebGLBatch) - { - if(this.batchs[index-1].texture == this.batchs[index+1].texture && this.batchs[index-1].blendMode == this.batchs[index+1].blendMode) - { - //console.log("MERGE") - this.batchs[index-1].merge(this.batchs[index+1]); - - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - PIXI.WebGLRenderer.returnBatch(this.batchs[index+1]); - this.batchs.splice(index, 2); - return; - } - } - - this.batchs.splice(index, 1); - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - } -} - - -/** - * Initializes a tiling sprite - * - * @method initTilingSprite - * @param sprite {TilingSprite} The tiling sprite to initialize - * @private - */ -PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) -{ - var gl = this.gl; - - // make the texture tilable.. - - sprite.verticies = new Float32Array([0, 0, - sprite.width, 0, - sprite.width, sprite.height, - 0, sprite.height]); - - sprite.uvs = new Float32Array([0, 0, - 1, 0, - 1, 1, - 0, 1]); - - sprite.colors = new Float32Array([1,1,1,1]); - - sprite.indices = new Uint16Array([0, 1, 3,2])//, 2]); - - sprite._vertexBuffer = gl.createBuffer(); - sprite._indexBuffer = gl.createBuffer(); - sprite._uvBuffer = gl.createBuffer(); - sprite._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.verticies, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.uvs, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.colors, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sprite._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sprite.indices, gl.STATIC_DRAW); - -// return ( (x > 0) && ((x & (x - 1)) == 0) ); - - if(sprite.texture.baseTexture._glTexture) - { - gl.bindTexture(gl.TEXTURE_2D, sprite.texture.baseTexture._glTexture); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - sprite.texture.baseTexture._powerOf2 = true; - } - else - { - sprite.texture.baseTexture._powerOf2 = true; - } -} - -/** - * Renders a Strip - * - * @method renderStrip - * @param strip {Strip} The strip to render - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) -{ - var gl = this.gl; - - PIXI.activateStripShader(); - - var shader = PIXI.stripShader; - - var program = shader.program; - - var m = PIXI.mat3.clone(strip.worldTransform); - - PIXI.mat3.transpose(m); - -// console.log(projection) - // set the matrix transform for the - gl.uniformMatrix3fv(shader.translationMatrix, false, m); - gl.uniform2f(shader.projectionVector, projection.x, projection.y); - gl.uniform2f(shader.offsetVector, -PIXI.offset.x, -PIXI.offset.y); - - gl.uniform1f(shader.alpha, strip.worldAlpha); - - /* - if(strip.blendMode == PIXI.blendModes.NORMAL) - { - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - } - else - { - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR); - } - */ - - //console.log("!!") - if(!strip.dirty) - { - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, strip.verticies) - gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.vertexAttribPointer(shader.colorAttribute, 1, gl.FLOAT, false, 0, 0); - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - } - else - { - strip.dirty = false; - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.STATIC_DRAW) - gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW) - gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - // console.log(strip.texture.baseTexture._glTexture) - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW) - gl.vertexAttribPointer(shader.colorAttribute, 1, gl.FLOAT, false, 0, 0); - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); - - } - - gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - - PIXI.deactivateStripShader(); - //gl.useProgram(PIXI.currentProgram); -} - -/** - * Renders a TilingSprite - * - * @method renderTilingSprite - * @param sprite {TilingSprite} The tiling sprite to render - * @param projectionMatrix {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderTilingSprite = function(sprite, projectionMatrix) -{ - var gl = this.gl; - - - var shaderProgram = PIXI.shaderProgram; - - var tilePosition = sprite.tilePosition; - var tileScale = sprite.tileScale; - - var offsetX = tilePosition.x/sprite.texture.baseTexture.width; - var offsetY = tilePosition.y/sprite.texture.baseTexture.height; - - var scaleX = (sprite.width / sprite.texture.baseTexture.width) / tileScale.x; - var scaleY = (sprite.height / sprite.texture.baseTexture.height) / tileScale.y; - - sprite.uvs[0] = 0 - offsetX; - sprite.uvs[1] = 0 - offsetY; - - sprite.uvs[2] = (1 * scaleX) -offsetX; - sprite.uvs[3] = 0 - offsetY; - - sprite.uvs[4] = (1 *scaleX) - offsetX; - sprite.uvs[5] = (1 *scaleY) - offsetY; - - sprite.uvs[6] = 0 - offsetX; - sprite.uvs[7] = (1 *scaleY) - offsetY; - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, sprite.uvs) - - this.renderStrip(sprite, projectionMatrix); -} - -/** - * Initializes a strip to be rendered - * - * @method initStrip - * @param strip {Strip} The strip to initialize - * @private - */ -PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) -{ - // build the strip! - var gl = this.gl; - var shaderProgram = this.shaderProgram; - - strip._vertexBuffer = gl.createBuffer(); - strip._indexBuffer = gl.createBuffer(); - strip._uvBuffer = gl.createBuffer(); - strip._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW); - - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -PIXI.WebGLFilterManager = function(transparent) -{ - this.transparent = transparent; - - this.filterStack = []; - this.texturePool = []; - - this.offsetX = 0; - this.offsetY = 0; - - this.initShaderBuffers(); -} - -// API - -PIXI.WebGLFilterManager.prototype.begin = function(projection, buffer) -{ - this.width = projection.x * 2; - this.height = -projection.y * 2; - this.buffer = buffer; -} - -PIXI.WebGLFilterManager.prototype.pushFilter = function(filterBlock) -{ - var gl = PIXI.gl; - - // filter program - // OPTIMISATION - the first filter is free if its a simple color change? - this.filterStack.push(filterBlock); - - var filter = filterBlock.filterPasses[0]; - - - - this.offsetX += filterBlock.target.filterArea.x; - this.offsetY += filterBlock.target.filterArea.y; - - - - - - var texture = this.texturePool.pop(); - if(!texture)texture = new PIXI.FilterTexture(this.width, this.height); - - gl.bindTexture(gl.TEXTURE_2D, texture.texture); - - this.getBounds(filterBlock.target); - - // addpadding? - //displayObject.filterArea.x - - var filterArea = filterBlock.target.filterArea; - - var padidng = filter.padding; - filterArea.x -= padidng; - filterArea.y -= padidng; - filterArea.width += padidng * 2; - filterArea.height += padidng * 2; - - // cap filter to screen size.. - if(filterArea.x < 0)filterArea.x = 0; - if(filterArea.width > this.width)filterArea.width = this.width; - if(filterArea.y < 0)filterArea.y = 0; - if(filterArea.height > this.height)filterArea.height = this.height; - - - //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, filterArea.width, filterArea.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - gl.bindFramebuffer(gl.FRAMEBUFFER, texture.frameBuffer); - - // console.log(filterArea) - // set view port - gl.viewport(0, 0, filterArea.width, filterArea.height); - - PIXI.projection.x = filterArea.width/2; - PIXI.projection.y = -filterArea.height/2; - - PIXI.offset.x = -filterArea.x; - PIXI.offset.y = -filterArea.y; - - //console.log(PIXI.defaultShader.projectionVector) - // update projection - gl.uniform2f(PIXI.defaultShader.projectionVector, filterArea.width/2, -filterArea.height/2); - gl.uniform2f(PIXI.defaultShader.offsetVector, -filterArea.x, -filterArea.y); - //PIXI.primitiveProgram - - gl.colorMask(true, true, true, true); - gl.clearColor(0,0,0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - - //filter.texture = texture; - filterBlock._glFilterTexture = texture; - - //console.log("PUSH") -} - - -PIXI.WebGLFilterManager.prototype.popFilter = function() -{ - - var gl = PIXI.gl; - - var filterBlock = this.filterStack.pop(); - - - - var filterArea = filterBlock.target.filterArea; - - var texture = filterBlock._glFilterTexture; - - if(filterBlock.filterPasses.length > 1) - { - gl.viewport(0, 0, filterArea.width, filterArea.height); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - - this.vertexArray[0] = 0; - this.vertexArray[1] = filterArea.height; - - this.vertexArray[2] = filterArea.width; - this.vertexArray[3] = filterArea.height; - - this.vertexArray[4] = 0; - this.vertexArray[5] = 0; - - this.vertexArray[6] = filterArea.width; - this.vertexArray[7] = 0; - - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray); - - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - // nnow set the uvs.. - this.uvArray[2] = filterArea.width/this.width; - this.uvArray[5] = filterArea.height/this.height; - this.uvArray[6] = filterArea.width/this.width; - this.uvArray[7] = filterArea.height/this.height; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray); - - var inputTexture = texture; - var outputTexture = this.texturePool.pop(); - if(!outputTexture)outputTexture = new PIXI.FilterTexture(this.width, this.height); - - // need to clear this FBO as it may have some left over elements from a prvious filter. - gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer ); - gl.clear(gl.COLOR_BUFFER_BIT); - - gl.disable(gl.BLEND); - - for (var i = 0; i < filterBlock.filterPasses.length-1; i++) - { - var filterPass = filterBlock.filterPasses[i]; - - gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer ); - - // set texture - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, inputTexture.texture); - - // draw texture.. - //filterPass.applyFilterPass(filterArea.width, filterArea.height); - this.applyFilterPass(filterPass, filterArea, filterArea.width, filterArea.height); - - // swap the textures.. - var temp = inputTexture; - inputTexture = outputTexture; - outputTexture = temp; - - }; - - gl.enable(gl.BLEND); - - texture = inputTexture; - this.texturePool.push(outputTexture); - } - - var filter = filterBlock.filterPasses[filterBlock.filterPasses.length-1]; - - this.offsetX -= filterArea.x; - this.offsetY -= filterArea.y; - - - var sizeX = this.width; - var sizeY = this.height; - - var offsetX = 0; - var offsetY = 0; - - var buffer = this.buffer; - - // time to render the filters texture to the previous scene - if(this.filterStack.length === 0) - { - gl.colorMask(true, true, true, this.transparent); - } - else - { - var currentFilter = this.filterStack[this.filterStack.length-1]; - var filterArea = currentFilter.target.filterArea; - - sizeX = filterArea.width; - sizeY = filterArea.height; - - offsetX = filterArea.x; - offsetY = filterArea.y; - - buffer = currentFilter._glFilterTexture.frameBuffer; - } - - - - // TODO need toremove thease global elements.. - PIXI.projection.x = sizeX/2; - PIXI.projection.y = -sizeY/2; - - PIXI.offset.x = offsetX; - PIXI.offset.y = offsetY; - - - var filterArea = filterBlock.target.filterArea; - var x = filterArea.x-offsetX; - var y = filterArea.y-offsetY; - - // update the buffers.. - // make sure to flip the y! - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - - this.vertexArray[0] = x; - this.vertexArray[1] = y + filterArea.height; - - this.vertexArray[2] = x + filterArea.width; - this.vertexArray[3] = y + filterArea.height; - - this.vertexArray[4] = x; - this.vertexArray[5] = y; - - this.vertexArray[6] = x + filterArea.width; - this.vertexArray[7] = y; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - - this.uvArray[2] = filterArea.width/this.width; - this.uvArray[5] = filterArea.height/this.height; - this.uvArray[6] = filterArea.width/this.width; - this.uvArray[7] = filterArea.height/this.height; - - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray); - - gl.viewport(0, 0, sizeX, sizeY); - // bind the buffer - gl.bindFramebuffer(gl.FRAMEBUFFER, buffer ); - - // set texture - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, texture.texture); - - // apply! - //filter.applyFilterPass(sizeX, sizeY); - this.applyFilterPass(filter, filterArea, sizeX, sizeY); - - // now restore the regular shader.. - gl.useProgram(PIXI.defaultShader.program); - gl.uniform2f(PIXI.defaultShader.projectionVector, sizeX/2, -sizeY/2); - gl.uniform2f(PIXI.defaultShader.offsetVector, -offsetX, -offsetY); - - // return the texture to the pool - this.texturePool.push(texture); - filterBlock._glFilterTexture = null; -} - -PIXI.WebGLFilterManager.prototype.applyFilterPass = function(filter, filterArea, width, height) -{ - // use program - var gl = PIXI.gl; - - if(!filter.shader) - { - var shader = new PIXI.PixiShader(); - - shader.fragmentSrc = filter.fragmentSrc; - shader.uniforms = filter.uniforms; - shader.init(); - - filter.shader = shader; - } - - var shader = filter.shader; - - // set the shader - gl.useProgram(shader.program); - - gl.uniform2f(shader.projectionVector, width/2, -height/2); - gl.uniform2f(shader.offsetVector, 0,0) - - if(filter.uniforms.dimensions) - { - //console.log(filter.uniforms.dimensions) - filter.uniforms.dimensions.value[0] = this.width;//width; - filter.uniforms.dimensions.value[1] = this.height;//height; - filter.uniforms.dimensions.value[2] = this.vertexArray[0]; - filter.uniforms.dimensions.value[3] = this.vertexArray[5];//filterArea.height; - // console.log(this.vertexArray[5]) - } - - shader.syncUniforms(); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - // draw the filter... - gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); -} - -PIXI.WebGLFilterManager.prototype.initShaderBuffers = function() -{ - var gl = PIXI.gl; - - // create some buffers - this.vertexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - - // bind and upload the vertexs.. - // keep a refferance to the vertexFloatData.. - this.vertexArray = new Float32Array([0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0, - 1.0, 1.0]); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.bufferData( - gl.ARRAY_BUFFER, - this.vertexArray, - gl.STATIC_DRAW); - - - // bind and upload the uv buffer - this.uvArray = new Float32Array([0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0, - 1.0, 1.0]); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.bufferData( - gl.ARRAY_BUFFER, - this.uvArray, - gl.STATIC_DRAW); - - // bind and upload the index - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData( - gl.ELEMENT_ARRAY_BUFFER, - new Uint16Array([0, 1, 2, 1, 3, 2]), - gl.STATIC_DRAW); -} - -PIXI.WebGLFilterManager.prototype.getBounds = function(displayObject) -{ - // time to get the width and height of the object! - var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index, doTest; - var a, b, c, d, tx, ty, x1, x2, x3, x4, y1, y2, y3, y4; - - var tempObject = displayObject.first; - var testObject = displayObject.last._iNext; - - var maxX = -Infinity; - var maxY = -Infinity; - - var minX = Infinity; - var minY = Infinity; - - do - { - // TODO can be optimized! - what if there is no scale / rotation? - - if(tempObject.visible) - { - if(tempObject instanceof PIXI.Sprite) - { - width = tempObject.texture.frame.width; - height = tempObject.texture.frame.height; - - // TODO trim?? - aX = tempObject.anchor.x; - aY = tempObject.anchor.y; - w0 = width * (1-aX); - w1 = width * -aX; - - h0 = height * (1-aY); - h1 = height * -aY; - - doTest = true; - } - else if(tempObject instanceof PIXI.Graphics) - { - tempObject.updateFilterBounds(); - - var bounds = tempObject.bounds; - - width = bounds.width; - height = bounds.height; - - w0 = bounds.x - w1 = bounds.x + bounds.width; - - h0 = bounds.y - h1 = bounds.y + bounds.height; - - doTest = true; - } - } - - if(doTest) - { - worldTransform = tempObject.worldTransform; - - a = worldTransform[0]; - b = worldTransform[3]; - c = worldTransform[1]; - d = worldTransform[4]; - tx = worldTransform[2]; - ty = worldTransform[5]; - - x1 = a * w1 + c * h1 + tx; - y1 = d * h1 + b * w1 + ty; - - x2 = a * w0 + c * h1 + tx; - y2 = d * h1 + b * w0 + ty; - - x3 = a * w0 + c * h0 + tx; - y3 = d * h0 + b * w0 + ty; - - x4 = a * w1 + c * h0 + tx; - y4 = d * h0 + b * w1 + ty; - - 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; - } - - doTest = false; - tempObject = tempObject._iNext; - - } - while(tempObject != testObject) - - // maximum bounds is the size of the screen.. - //minX = minX > 0 ? minX : 0; - //minY = minY > 0 ? minY : 0; - - displayObject.filterArea.x = minX; - displayObject.filterArea.y = minY; - -// console.log(maxX+ " : " + minX) - displayObject.filterArea.width = maxX - minX; - displayObject.filterArea.height = maxY - minY; -} - -PIXI.FilterTexture = function(width, height) -{ - var gl = PIXI.gl; - - // next time to create a frame buffer and texture - this.frameBuffer = gl.createFramebuffer(); - this.texture = gl.createTexture(); - - gl.bindTexture(gl.TEXTURE_2D, this.texture); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer ); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer ); - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0); - - this.resize(width, height); -} - -PIXI.FilterTexture.prototype.resize = function(width, height) -{ - this.width = width; - this.height = height; - - var gl = PIXI.gl; - - gl.bindTexture(gl.TEXTURE_2D, this.texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * the CanvasRenderer draws the stage and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. - * Dont forget to add the view to your DOM or you will not see anything :) - * - * @class CanvasRenderer - * @constructor - * @param width=0 {Number} the width of the canvas view - * @param height=0 {Number} the height of the canvas view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - */ -PIXI.CanvasRenderer = function(width, height, view, transparent) -{ - this.transparent = transparent; - - /** - * The width of the canvas view - * - * @property width - * @type Number - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @property height - * @type Number - * @default 600 - */ - this.height = height || 600; - - /** - * The canvas element that the everything is drawn to - * - * @property view - * @type Canvas - */ - this.view = view || document.createElement( 'canvas' ); - - /** - * The canvas context that the everything is drawn to - * @property context - * @type Canvas 2d Context - */ - this.context = this.view.getContext("2d"); - - this.refresh = true; - // hack to enable some hardware acceleration! - //this.view.style["transform"] = "translatez(0)"; - - this.view.width = this.width; - this.view.height = this.height; - this.count = 0; -} - -// constructor -PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; - -/** - * Renders the stage to its canvas view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.CanvasRenderer.prototype.render = function(stage) -{ - - //stage.__childrenAdded = []; - //stage.__childrenRemoved = []; - - // update textures if need be - PIXI.texturesToUpdate = []; - PIXI.texturesToDestroy = []; - - PIXI.visibleCount++; - stage.updateTransform(); - - // update the background color - if(this.view.style.backgroundColor!=stage.backgroundColorString && !this.transparent)this.view.style.backgroundColor = stage.backgroundColorString; - - this.context.setTransform(1,0,0,1,0,0); - this.context.clearRect(0, 0, this.width, this.height) - this.renderDisplayObject(stage); - //as - - // run interaction! - if(stage.interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - - // remove frame updates.. - if(PIXI.Texture.frameUpdates.length > 0) - { - PIXI.Texture.frameUpdates = []; - } - - -} - -/** - * resizes the canvas view to the specified width and height - * - * @method resize - * @param width {Number} the new width of the canvas view - * @param height {Number} the new height of the canvas view - */ -PIXI.CanvasRenderer.prototype.resize = function(width, height) -{ - this.width = width; - this.height = height; - - this.view.width = width; - this.view.height = height; -} - -/** - * Renders a display object - * - * @method renderDisplayObject - * @param displayObject {DisplayObject} The displayObject to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) -{ - // no loger recurrsive! - var transform; - var context = this.context; - - context.globalCompositeOperation = 'source-over'; - - // one the display object hits this. we can break the loop - var testObject = displayObject.last._iNext; - displayObject = displayObject.first; - - do - { - transform = displayObject.worldTransform; - - if(!displayObject.visible) - { - displayObject = displayObject.last._iNext; - continue; - } - - if(!displayObject.renderable) - { - displayObject = displayObject._iNext; - continue; - } - - if(displayObject instanceof PIXI.Sprite) - { - - var frame = displayObject.texture.frame; - - if(frame && frame.width && frame.height) - { - context.globalAlpha = displayObject.worldAlpha; - - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); - - context.drawImage(displayObject.texture.baseTexture.source, - frame.x, - frame.y, - frame.width, - frame.height, - (displayObject.anchor.x) * -frame.width, - (displayObject.anchor.y) * -frame.height, - frame.width, - frame.height); - } - } - else if(displayObject instanceof PIXI.Strip) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - this.renderStrip(displayObject); - } - else if(displayObject instanceof PIXI.TilingSprite) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - this.renderTilingSprite(displayObject); - } - else if(displayObject instanceof PIXI.CustomRenderable) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); - displayObject.renderCanvas(this); - } - else if(displayObject instanceof PIXI.Graphics) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - PIXI.CanvasGraphics.renderGraphics(displayObject, context); - } - else if(displayObject instanceof PIXI.FilterBlock) - { - if(displayObject.data instanceof PIXI.Graphics) - { - var mask = displayObject.data; - - if(displayObject.open) - { - context.save(); - - var cacheAlpha = mask.alpha; - var maskTransform = mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(mask, context); - context.clip(); - - mask.worldAlpha = cacheAlpha; - } - else - { - context.restore(); - } - } - else - { - // only masks supported right now! - } - } - // count++ - displayObject = displayObject._iNext; - - - } - while(displayObject != testObject) - - -} - -/** - * Renders a flat strip - * - * @method renderStripFlat - * @param strip {Strip} The Strip to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip) -{ - var context = this.context; - var verticies = strip.verticies; - var uvs = strip.uvs; - - var length = verticies.length/2; - this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - - // draw some triangles! - var index = i*2; - - var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; - var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - }; - - context.fillStyle = "#FF0000"; - context.fill(); - context.closePath(); -} - -/** - * Renders a tiling sprite - * - * @method renderTilingSprite - * @param sprite {TilingSprite} The tilingsprite to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) -{ - var context = this.context; - - context.globalAlpha = sprite.worldAlpha; - - if(!sprite.__tilePattern) sprite.__tilePattern = context.createPattern(sprite.texture.baseTexture.source, "repeat"); - - context.beginPath(); - - var tilePosition = sprite.tilePosition; - var tileScale = sprite.tileScale; - - // offset - context.scale(tileScale.x,tileScale.y); - context.translate(tilePosition.x, tilePosition.y); - - context.fillStyle = sprite.__tilePattern; - context.fillRect(-tilePosition.x,-tilePosition.y,sprite.width / tileScale.x, sprite.height / tileScale.y); - - context.scale(1/tileScale.x, 1/tileScale.y); - context.translate(-tilePosition.x, -tilePosition.y); - - context.closePath(); -} - -/** - * Renders a strip - * - * @method renderStrip - * @param strip {Strip} The Strip to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderStrip = function(strip) -{ - var context = this.context; - - // draw triangles!! - var verticies = strip.verticies; - var uvs = strip.uvs; - - var length = verticies.length/2; - this.count++; - for (var i=1; i < length-2; i++) - { - - // draw some triangles! - var index = i*2; - - var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; - var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - - var u0 = uvs[index] * strip.texture.width, u1 = uvs[index+2] * strip.texture.width, u2 = uvs[index+4]* strip.texture.width; - var v0 = uvs[index+1]* strip.texture.height, v1 = uvs[index+3] * strip.texture.height, v2 = uvs[index+5]* strip.texture.height; - - - 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 delta_a = x0*v1 + v0*x2 + x1*v2 - v1*x2 - v0*x1 - x0*v2; - var delta_b = u0*x1 + x0*u2 + u1*x2 - x1*u2 - x0*u1 - u0*x2; - var delta_c = u0*v1*x2 + v0*x1*u2 + x0*u1*v2 - x0*v1*u2 - v0*u1*x2 - u0*x1*v2; - var delta_d = y0*v1 + v0*y2 + y1*v2 - v1*y2 - v0*y1 - y0*v2; - var delta_e = u0*y1 + y0*u2 + u1*y2 - y1*u2 - y0*u1 - u0*y2; - var delta_f = u0*v1*y2 + v0*y1*u2 + y0*u1*v2 - y0*v1*u2 - v0*u1*y2 - u0*y1*v2; - - - - - context.transform(delta_a/delta, delta_d/delta, - delta_b/delta, delta_e/delta, - delta_c/delta, delta_f/delta); - - context.drawImage(strip.texture.baseTexture.source, 0, 0); - context.restore(); - }; - -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * A set of functions used by the canvas renderer to draw the primitive graphics data - * - * @class CanvasGraphics - */ -PIXI.CanvasGraphics = function() -{ - -} - - -/* - * Renders the graphics object - * - * @static - * @private - * @method renderGraphics - * @param graphics {Graphics} - * @param context {Context2D} - */ -PIXI.CanvasGraphics.renderGraphics = function(graphics, context) -{ - var worldAlpha = graphics.worldAlpha; - - for (var i=0; i < graphics.graphicsData.length; i++) - { - var data = graphics.graphicsData[i]; - var points = data.points; - - context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); - - context.lineWidth = data.lineWidth; - - if(data.type == PIXI.Graphics.POLY) - { - context.beginPath(); - - context.moveTo(points[0], points[1]); - - for (var j=1; j < points.length/2; j++) - { - context.lineTo(points[j * 2], points[j * 2 + 1]); - } - - // if the first and last point are the same close the path - much neater :) - if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) - { - context.closePath(); - } - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - else if(data.type == PIXI.Graphics.RECT) - { - - if(data.fillColor || data.fillColor === 0) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fillRect(points[0], points[1], points[2], points[3]); - - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.strokeRect(points[0], points[1], points[2], points[3]); - } - - } - else if(data.type == PIXI.Graphics.CIRC) - { - // TODO - need to be Undefined! - context.beginPath(); - context.arc(points[0], points[1], points[2],0,2*Math.PI); - context.closePath(); - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - else if(data.type == PIXI.Graphics.ELIP) - { - - // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - - var elipseData = data.points; - - var w = elipseData[2] * 2; - var h = elipseData[3] * 2; - - var x = elipseData[0] - w/2; - var y = elipseData[1] - h/2; - - context.beginPath(); - - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - - context.moveTo(x, ym); - context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - - context.closePath(); - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - - }; -} - -/* - * Renders a graphics mask - * - * @static - * @private - * @method renderGraphicsMask - * @param graphics {Graphics} - * @param context {Context2D} - */ -PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) -{ - var worldAlpha = graphics.worldAlpha; - - var len = graphics.graphicsData.length; - if(len === 0)return; - - if(len > 1) - { - len = 1; - console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") - } - - for (var i=0; i < 1; i++) - { - var data = graphics.graphicsData[i]; - var points = data.points; - - if(data.type == PIXI.Graphics.POLY) - { - context.beginPath(); - context.moveTo(points[0], points[1]); - - for (var j=1; j < points.length/2; j++) - { - context.lineTo(points[j * 2], points[j * 2 + 1]); - } - - // if the first and last point are the same close the path - much neater :) - if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) - { - context.closePath(); - } - - } - else if(data.type == PIXI.Graphics.RECT) - { - context.beginPath(); - context.rect(points[0], points[1], points[2], points[3]); - context.closePath(); - } - else if(data.type == PIXI.Graphics.CIRC) - { - // TODO - need to be Undefined! - context.beginPath(); - context.arc(points[0], points[1], points[2],0,2*Math.PI); - context.closePath(); - } - else if(data.type == PIXI.Graphics.ELIP) - { - - // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - var elipseData = data.points; - - var w = elipseData[2] * 2; - var h = elipseData[3] * 2; - - var x = elipseData[0] - w/2; - var y = elipseData[1] - h/2; - - context.beginPath(); - - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - - context.moveTo(x, ym); - context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - context.closePath(); - } - - - }; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. - * It is important to know that with the webGL renderer only simple polys can be filled at this stage - * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png - * - * @class Graphics - * @extends DisplayObjectContainer - * @constructor - */ -PIXI.Graphics = function() -{ - PIXI.DisplayObjectContainer.call( this ); - - this.renderable = true; - - /** - * The alpha of the fill of this graphics object - * - * @property fillAlpha - * @type Number - */ - this.fillAlpha = 1; - - /** - * The width of any lines drawn - * - * @property lineWidth - * @type Number - */ - this.lineWidth = 0; - - /** - * The color of any lines drawn - * - * @property lineColor - * @type String - */ - this.lineColor = "black"; - - /** - * Graphics data - * - * @property graphicsData - * @type Array - * @private - */ - this.graphicsData = []; - - /** - * Current path - * - * @property currentPath - * @type Object - * @private - */ - this.currentPath = {points:[]}; -} - -// constructor -PIXI.Graphics.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Graphics.prototype.constructor = PIXI.Graphics; - -/** - * Specifies a line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method. - * - * @method lineStyle - * @param lineWidth {Number} width of the line to draw, will update the object's stored style - * @param color {Number} color of the line to draw, will update the object's stored style - * @param alpha {Number} alpha of the line to draw, will update the object's stored style - */ -PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.lineWidth = lineWidth || 0; - this.lineColor = color || 0; - this.lineAlpha = (alpha == undefined) ? 1 : alpha; - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - - this.graphicsData.push(this.currentPath); -} - -/** - * Moves the current drawing position to (x, y). - * - * @method moveTo - * @param x {Number} the X coord to move to - * @param y {Number} the Y coord to move to - */ -PIXI.Graphics.prototype.moveTo = function(x, y) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - - this.currentPath.points.push(x, y); - - this.graphicsData.push(this.currentPath); -} - -/** - * Draws a line using the current line style from the current drawing position to (x, y); - * the current drawing position is then set to (x, y). - * - * @method lineTo - * @param x {Number} the X coord to draw to - * @param y {Number} the Y coord to draw to - */ -PIXI.Graphics.prototype.lineTo = function(x, y) -{ - this.currentPath.points.push(x, y); - this.dirty = true; -} - -/** - * Specifies a simple one-color fill that subsequent calls to other Graphics methods - * (such as lineTo() or drawCircle()) use when drawing. - * - * @method beginFill - * @param color {uint} the color of the fill - * @param alpha {Number} the alpha - */ -PIXI.Graphics.prototype.beginFill = function(color, alpha) -{ - this.filling = true; - this.fillColor = color || 0; - this.fillAlpha = (alpha == undefined) ? 1 : alpha; -} - -/** - * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. - * - * @method endFill - */ -PIXI.Graphics.prototype.endFill = function() -{ - this.filling = false; - this.fillColor = null; - this.fillAlpha = 1; -} - -/** - * @method drawRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - */ -PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, width, height], type:PIXI.Graphics.RECT}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Draws a circle. - * - * @method drawCircle - * @param x {Number} The X coord of the center of the circle - * @param y {Number} The Y coord of the center of the circle - * @param radius {Number} The radius of the circle - */ -PIXI.Graphics.prototype.drawCircle = function( x, y, radius) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Draws an elipse. - * - * @method drawElipse - * @param x {Number} - * @param y {Number} - * @param width {Number} - * @param height {Number} - */ -PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, width, height], type:PIXI.Graphics.ELIP}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @method clear - */ -PIXI.Graphics.prototype.clear = function() -{ - this.lineWidth = 0; - this.filling = false; - - this.dirty = true; - this.clearDirty = true; - this.graphicsData = []; - - this.bounds = null//new PIXI.Rectangle(); -} - - -PIXI.Graphics.prototype.updateFilterBounds = function() -{ - if(!this.bounds) - { - var minX = Infinity; - var maxX = -Infinity; - - var minY = Infinity; - var maxY = -Infinity; - - var points, x, y; - - for (var i = 0; i < this.graphicsData.length; i++) { - - - var data = this.graphicsData[i]; - var type = data.type; - var lineWidth = data.lineWidth; - - points = data.points; - - if(type === PIXI.Graphics.RECT) - { - x = points.x - lineWidth/2; - y = points.y - lineWidth/2; - var width = points.width + lineWidth; - var height = points.height + lineWidth; - - minX = x < minX ? x : minX; - maxX = x + width > maxX ? x + width : maxX; - - minY = y < minY ? x : minY; - maxY = y + height > maxY ? y + height : maxY; - } - else if(type === PIXI.Graphics.CIRC || type === PIXI.Graphics.ELIP) - { - x = points.x; - y = points.y; - var radius = points.radius + lineWidth/2; - - minX = x - radius < minX ? x - radius : minX; - maxX = x + radius > maxX ? x + radius : maxX; - - minY = y - radius < minY ? y - radius : minY; - maxY = y + radius > maxY ? y + radius : maxY; - } - else - { - // POLY - for (var j = 0; j < points.length; j+=2) - { - - x = points[j]; - y = points[j+1]; - - minX = x-lineWidth < minX ? x-lineWidth : minX; - maxX = x+lineWidth > maxX ? x+lineWidth : maxX; - - minY = y-lineWidth < minY ? y-lineWidth : minY; - maxY = y+lineWidth > maxY ? y+lineWidth : maxY; - }; - } - - }; - - this.bounds = new PIXI.Rectangle(minX, minY, maxX - minX, maxY - minY); - - } - -// console.log(this.bounds); -} - -// SOME TYPES: -PIXI.Graphics.POLY = 0; -PIXI.Graphics.RECT = 1; -PIXI.Graphics.CIRC = 2; -PIXI.Graphics.ELIP = 3; - -/** - * @author Mat Groves http://matgroves.com/ - */ - -PIXI.Strip = function(texture, width, height) -{ - PIXI.DisplayObjectContainer.call( this ); - this.texture = texture; - this.blendMode = PIXI.blendModes.NORMAL; - - try - { - this.uvs = new Float32Array([0, 1, - 1, 1, - 1, 0, 0,1]); - - this.verticies = new Float32Array([0, 0, - 0,0, - 0,0, 0, - 0, 0]); - - this.colors = new Float32Array([1, 1, 1, 1]); - - this.indices = new Uint16Array([0, 1, 2, 3]); - } - catch(error) - { - this.uvs = [0, 1, - 1, 1, - 1, 0, 0,1]; - - this.verticies = [0, 0, - 0,0, - 0,0, 0, - 0, 0]; - - this.colors = [1, 1, 1, 1]; - - this.indices = [0, 1, 2, 3]; - } - - - /* - this.uvs = new Float32Array() - this.verticies = new Float32Array() - this.colors = new Float32Array() - this.indices = new Uint16Array() -*/ - this.width = width; - this.height = height; - - // load the texture! - if(texture.baseTexture.hasLoaded) - { - this.width = this.texture.frame.width; - this.height = this.texture.frame.height; - this.updateFrame = true; - } - else - { - this.onTextureUpdateBind = this.onTextureUpdate.bind(this); - this.texture.addEventListener( 'update', this.onTextureUpdateBind ); - } - - this.renderable = true; -} - -// constructor -PIXI.Strip.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Strip.prototype.constructor = PIXI.Strip; - -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; -} - -PIXI.Strip.prototype.onTextureUpdate = function(event) -{ - this.updateFrame = true; -} -// some helper functions.. - - -/** - * @author Mat Groves http://matgroves.com/ - */ - - -PIXI.Rope = function(texture, points) -{ - PIXI.Strip.call( this, texture ); - this.points = points; - - try - { - this.verticies = new Float32Array( points.length * 4); - this.uvs = new Float32Array( points.length * 4); - this.colors = new Float32Array( points.length * 2); - this.indices = new Uint16Array( points.length * 2); - } - catch(error) - { - this.verticies = verticies - - this.uvs = uvs - this.colors = colors - this.indices = indices - } - - this.refresh(); -} - - -// constructor -PIXI.Rope.prototype = Object.create( PIXI.Strip.prototype ); -PIXI.Rope.prototype.constructor = PIXI.Rope; - -PIXI.Rope.prototype.refresh = function() -{ - var points = this.points; - if(points.length < 1)return; - - var uvs = this.uvs - var indices = this.indices; - var colors = this.colors; - - var lastPoint = points[0]; - var nextPoint; - var perp = {x:0, y:0}; - var point = points[0]; - - this.count-=0.2; - - - uvs[0] = 0 - uvs[1] = 1 - uvs[2] = 0 - uvs[3] = 1 - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length; - - for (var i = 1; i < total; i++) - { - - var point = points[i]; - var index = i * 4; - // time to do some smart drawing! - var 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; - } -} - -PIXI.Rope.prototype.updateTransform = function() -{ - - var points = this.points; - if(points.length < 1)return; - - var verticies = this.verticies - - var lastPoint = points[0]; - var nextPoint; - var perp = {x:0, y:0}; - var point = points[0]; - - this.count-=0.2; - - verticies[0] = point.x + perp.x - verticies[1] = point.y + perp.y //+ 200 - verticies[2] = point.x - perp.x - verticies[3] = point.y - perp.y//+200 - // time to do some smart drawing! - - var total = points.length; - - for (var i = 1; i < total; i++) - { - - var point = points[i]; - var 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; - - var ratio = (1 - (i / (total-1))) * 10; - if(ratio > 1)ratio = 1; - - var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); - var 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; - - verticies[index] = point.x + perp.x - verticies[index+1] = point.y + perp.y - verticies[index+2] = point.x - perp.x - verticies[index+3] = point.y - perp.y - - lastPoint = point; - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); -} - -PIXI.Rope.prototype.setTexture = function(texture) -{ - // stop current texture - this.texture = texture; - this.updateFrame = true; -} - - - - - -/** - * @author Mat Groves http://matgroves.com/ - */ - -/** - * A tiling sprite is a fast way of rendering a tiling image - * - * @class TilingSprite - * @extends DisplayObjectContainer - * @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.DisplayObjectContainer.call( this ); - - /** - * The texture that the sprite is using - * - * @property texture - * @type Texture - */ - this.texture = texture; - - /** - * The width of the tiling sprite - * - * @property width - * @type Number - */ - this.width = width; - - /** - * The height of the tiling sprite - * - * @property height - * @type Number - */ - this.height = height; - - /** - * The scaling of the image that is being tiled - * - * @property tileScale - * @type Point - */ - this.tileScale = 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); - - this.renderable = true; - - this.blendMode = PIXI.blendModes.NORMAL -} - -// constructor -PIXI.TilingSprite.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite; - -/** - * Sets the texture of the tiling sprite - * - * @method setTexture - * @param texture {Texture} The PIXI texture that is displayed by the sprite - */ -PIXI.TilingSprite.prototype.setTexture = function(texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - - // stop current texture - this.texture = texture; - this.updateFrame = true; -} - -/** - * When the texture is updated, this event will fire to update the frame - * - * @method onTextureUpdate - * @param event - * @private - */ -PIXI.TilingSprite.prototype.onTextureUpdate = function(event) -{ - this.updateFrame = true; -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * - * Awesome JS run time provided by EsotericSoftware - * https://github.com/EsotericSoftware/spine-runtimes - * - */ - -/** - * 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)) { - continue; - } - var spriteName = attachment.rendererObject.name; - var sprite = this.createSprite(slot, attachment.rendererObject); - slot.currentSprite = sprite; - slot.currentSpriteName = spriteName; - slotContainer.addChild(sprite); - } -}; - -PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); -PIXI.Spine.prototype.constructor = PIXI.Spine; - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.Spine.prototype.updateTransform = function () { - this.lastTime = this.lastTime || Date.now(); - var timeDelta = (Date.now() - this.lastTime) * 0.001; - this.lastTime = Date.now(); - this.state.update(timeDelta); - 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 instanceof spine.RegionAttachment)) { - slotContainer.visible = false; - continue; - } - - 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.rendererObject); - slotContainer.addChild(sprite); - } - slot.currentSprite = slot.sprites[spriteName]; - slot.currentSpriteName = spriteName; - } - } - slotContainer.visible = true; - - 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 * Math.PI / 180); - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -}; - - -PIXI.Spine.prototype.createSprite = function (slot, descriptor) { - var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); - sprite.scale = descriptor.scale; - sprite.rotation = descriptor.rotation; - sprite.anchor.x = sprite.anchor.y = 0.5; - - slot.sprites = slot.sprites || {}; - slot.sprites[descriptor.name] = sprite; - return sprite; -}; - -/* - * Awesome JS run time provided by EsotericSoftware - * - * https://github.com/EsotericSoftware/spine-runtimes - * - */ - -var spine = {}; - -spine.BoneData = function (name, parent) { - this.name = name; - this.parent = parent; -}; -spine.BoneData.prototype = { - length: 0, - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1 -}; - -spine.SlotData = function (name, boneData) { - this.name = name; - this.boneData = boneData; -}; -spine.SlotData.prototype = { - r: 1, g: 1, b: 1, a: 1, - attachmentName: null -}; - -spine.Bone = function (boneData, parent) { - this.data = boneData; - this.parent = parent; - this.setToSetupPose(); -}; -spine.Bone.yDown = false; -spine.Bone.prototype = { - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1, - m00: 0, m01: 0, worldX: 0, // a b x - m10: 0, m11: 0, worldY: 0, // c d y - worldRotation: 0, - worldScaleX: 1, worldScaleY: 1, - updateWorldTransform: function (flipX, flipY) { - var parent = this.parent; - if (parent != null) { - this.worldX = this.x * parent.m00 + this.y * parent.m01 + parent.worldX; - this.worldY = this.x * parent.m10 + this.y * parent.m11 + parent.worldY; - this.worldScaleX = parent.worldScaleX * this.scaleX; - this.worldScaleY = parent.worldScaleY * this.scaleY; - this.worldRotation = parent.worldRotation + this.rotation; - } else { - this.worldX = this.x; - this.worldY = this.y; - this.worldScaleX = this.scaleX; - this.worldScaleY = this.scaleY; - this.worldRotation = this.rotation; - } - var radians = this.worldRotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - this.m00 = cos * this.worldScaleX; - this.m10 = sin * this.worldScaleX; - this.m01 = -sin * this.worldScaleY; - this.m11 = cos * this.worldScaleY; - if (flipX) { - this.m00 = -this.m00; - this.m01 = -this.m01; - } - if (flipY) { - this.m10 = -this.m10; - this.m11 = -this.m11; - } - if (spine.Bone.yDown) { - this.m10 = -this.m10; - this.m11 = -this.m11; - } - }, - setToSetupPose: function () { - var data = this.data; - this.x = data.x; - this.y = data.y; - this.rotation = data.rotation; - this.scaleX = data.scaleX; - this.scaleY = data.scaleY; - } -}; - -spine.Slot = function (slotData, skeleton, bone) { - this.data = slotData; - this.skeleton = skeleton; - this.bone = bone; - this.setToSetupPose(); -}; -spine.Slot.prototype = { - r: 1, g: 1, b: 1, a: 1, - _attachmentTime: 0, - attachment: null, - setAttachment: function (attachment) { - this.attachment = attachment; - this._attachmentTime = this.skeleton.time; - }, - setAttachmentTime: function (time) { - this._attachmentTime = this.skeleton.time - time; - }, - getAttachmentTime: function () { - return this.skeleton.time - this._attachmentTime; - }, - setToSetupPose: function () { - var data = this.data; - this.r = data.r; - this.g = data.g; - this.b = data.b; - this.a = data.a; - - var slotDatas = this.skeleton.data.slots; - for (var i = 0, n = slotDatas.length; i < n; i++) { - if (slotDatas[i] == data) { - this.setAttachment(!data.attachmentName ? null : this.skeleton.getAttachmentBySlotIndex(i, data.attachmentName)); - break; - } - } - } -}; - -spine.Skin = function (name) { - this.name = name; - this.attachments = {}; -}; -spine.Skin.prototype = { - addAttachment: function (slotIndex, name, attachment) { - this.attachments[slotIndex + ":" + name] = attachment; - }, - getAttachment: function (slotIndex, name) { - return this.attachments[slotIndex + ":" + name]; - }, - _attachAll: function (skeleton, oldSkin) { - for (var key in oldSkin.attachments) { - var colon = key.indexOf(":"); - var slotIndex = parseInt(key.substring(0, colon)); - var name = key.substring(colon + 1); - var slot = skeleton.slots[slotIndex]; - if (slot.attachment && slot.attachment.name == name) { - var attachment = this.getAttachment(slotIndex, name); - if (attachment) slot.setAttachment(attachment); - } - } - } -}; - -spine.Animation = function (name, timelines, duration) { - this.name = name; - this.timelines = timelines; - this.duration = duration; -}; -spine.Animation.prototype = { - apply: function (skeleton, time, loop) { - if (loop && this.duration != 0) time %= this.duration; - var timelines = this.timelines; - for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, time, 1); - }, - mix: function (skeleton, time, loop, alpha) { - if (loop && this.duration != 0) time %= this.duration; - var timelines = this.timelines; - for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, time, alpha); - } -}; - -spine.binarySearch = function (values, target, step) { - var low = 0; - var high = Math.floor(values.length / step) - 2; - if (high == 0) return step; - var current = high >>> 1; - while (true) { - if (values[(current + 1) * step] <= target) - low = current + 1; - else - high = current; - if (low == high) return (low + 1) * step; - current = (low + high) >>> 1; - } -}; -spine.linearSearch = function (values, target, step) { - for (var i = 0, last = values.length - step; i <= last; i += step) - if (values[i] > target) return i; - return -1; -}; - -spine.Curves = function (frameCount) { - this.curves = []; // dfx, dfy, ddfx, ddfy, dddfx, dddfy, ... - this.curves.length = (frameCount - 1) * 6; -}; -spine.Curves.prototype = { - setLinear: function (frameIndex) { - this.curves[frameIndex * 6] = 0/*LINEAR*/; - }, - setStepped: function (frameIndex) { - this.curves[frameIndex * 6] = -1/*STEPPED*/; - }, - /** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next. - * cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of - * the difference between the keyframe's values. */ - setCurve: function (frameIndex, cx1, cy1, cx2, cy2) { - var subdiv_step = 1 / 10/*BEZIER_SEGMENTS*/; - var subdiv_step2 = subdiv_step * subdiv_step; - var subdiv_step3 = subdiv_step2 * subdiv_step; - var pre1 = 3 * subdiv_step; - var pre2 = 3 * subdiv_step2; - var pre4 = 6 * subdiv_step2; - var pre5 = 6 * subdiv_step3; - var tmp1x = -cx1 * 2 + cx2; - var tmp1y = -cy1 * 2 + cy2; - var tmp2x = (cx1 - cx2) * 3 + 1; - var tmp2y = (cy1 - cy2) * 3 + 1; - var i = frameIndex * 6; - var curves = this.curves; - curves[i] = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; - curves[i + 1] = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; - curves[i + 2] = tmp1x * pre4 + tmp2x * pre5; - curves[i + 3] = tmp1y * pre4 + tmp2y * pre5; - curves[i + 4] = tmp2x * pre5; - curves[i + 5] = tmp2y * pre5; - }, - getCurvePercent: function (frameIndex, percent) { - percent = percent < 0 ? 0 : (percent > 1 ? 1 : percent); - var curveIndex = frameIndex * 6; - var curves = this.curves; - var dfx = curves[curveIndex]; - if (!dfx/*LINEAR*/) return percent; - if (dfx == -1/*STEPPED*/) return 0; - var dfy = curves[curveIndex + 1]; - var ddfx = curves[curveIndex + 2]; - var ddfy = curves[curveIndex + 3]; - var dddfx = curves[curveIndex + 4]; - var dddfy = curves[curveIndex + 5]; - var x = dfx, y = dfy; - var i = 10/*BEZIER_SEGMENTS*/ - 2; - while (true) { - if (x >= percent) { - var lastX = x - dfx; - var lastY = y - dfy; - return lastY + (y - lastY) * (percent - lastX) / (x - lastX); - } - if (i == 0) break; - i--; - dfx += ddfx; - dfy += ddfy; - ddfx += dddfx; - ddfy += dddfy; - x += dfx; - y += dfy; - } - return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1. - } -}; - -spine.RotateTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, angle, ... - this.frames.length = frameCount * 2; -}; -spine.RotateTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 2; - }, - setFrame: function (frameIndex, time, angle) { - frameIndex *= 2; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = angle; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 2]) { // Time is after last frame. - var amount = bone.data.rotation + frames[frames.length - 1] - bone.rotation; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - bone.rotation += amount * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 2); - var lastFrameValue = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex - 2/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent); - - var amount = frames[frameIndex + 1/*FRAME_VALUE*/] - lastFrameValue; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - amount = bone.data.rotation + (lastFrameValue + amount * percent) - bone.rotation; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - bone.rotation += amount * alpha; - } -}; - -spine.TranslateTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, x, y, ... - this.frames.length = frameCount * 3; -}; -spine.TranslateTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 3; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 3; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = x; - this.frames[frameIndex + 2] = y; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 3]) { // Time is after last frame. - bone.x += (bone.data.x + frames[frames.length - 2] - bone.x) * alpha; - bone.y += (bone.data.y + frames[frames.length - 1] - bone.y) * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 3); - var lastFrameX = frames[frameIndex - 2]; - var lastFrameY = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); - - bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; - bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; - } -}; - -spine.ScaleTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, x, y, ... - this.frames.length = frameCount * 3; -}; -spine.ScaleTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 3; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 3; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = x; - this.frames[frameIndex + 2] = y; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 3]) { // Time is after last frame. - bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 3); - var lastFrameX = frames[frameIndex - 2]; - var lastFrameY = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); - - bone.scaleX += (bone.data.scaleX - 1 + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - 1 + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.scaleY) * alpha; - } -}; - -spine.ColorTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, r, g, b, a, ... - this.frames.length = frameCount * 5; -}; -spine.ColorTimeline.prototype = { - slotIndex: 0, - getFrameCount: function () { - return this.frames.length / 2; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 5; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = r; - this.frames[frameIndex + 2] = g; - this.frames[frameIndex + 3] = b; - this.frames[frameIndex + 4] = a; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var slot = skeleton.slots[this.slotIndex]; - - if (time >= frames[frames.length - 5]) { // Time is after last frame. - var i = frames.length - 1; - slot.r = frames[i - 3]; - slot.g = frames[i - 2]; - slot.b = frames[i - 1]; - slot.a = frames[i]; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 5); - var lastFrameR = frames[frameIndex - 4]; - var lastFrameG = frames[frameIndex - 3]; - var lastFrameB = frames[frameIndex - 2]; - var lastFrameA = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex - 5/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent); - - var r = lastFrameR + (frames[frameIndex + 1/*FRAME_R*/] - lastFrameR) * percent; - var g = lastFrameG + (frames[frameIndex + 2/*FRAME_G*/] - lastFrameG) * percent; - var b = lastFrameB + (frames[frameIndex + 3/*FRAME_B*/] - lastFrameB) * percent; - var a = lastFrameA + (frames[frameIndex + 4/*FRAME_A*/] - lastFrameA) * percent; - if (alpha < 1) { - slot.r += (r - slot.r) * alpha; - slot.g += (g - slot.g) * alpha; - slot.b += (b - slot.b) * alpha; - slot.a += (a - slot.a) * alpha; - } else { - slot.r = r; - slot.g = g; - slot.b = b; - slot.a = a; - } - } -}; - -spine.AttachmentTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, ... - this.frames.length = frameCount; - this.attachmentNames = []; // time, ... - this.attachmentNames.length = frameCount; -}; -spine.AttachmentTimeline.prototype = { - slotIndex: 0, - getFrameCount: function () { - return this.frames.length; - }, - setFrame: function (frameIndex, time, attachmentName) { - this.frames[frameIndex] = time; - this.attachmentNames[frameIndex] = attachmentName; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var frameIndex; - if (time >= frames[frames.length - 1]) // Time is after last frame. - frameIndex = frames.length - 1; - else - frameIndex = spine.binarySearch(frames, time, 1) - 1; - - var attachmentName = this.attachmentNames[frameIndex]; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); - } -}; - -spine.SkeletonData = function () { - this.bones = []; - this.slots = []; - this.skins = []; - this.animations = []; -}; -spine.SkeletonData.prototype = { - defaultSkin: null, - /** @return May be null. */ - findBone: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].name == boneName) return bones[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findBoneIndex: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].name == boneName) return i; - return -1; - }, - /** @return May be null. */ - findSlot: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) { - if (slots[i].name == slotName) return slot[i]; - } - return null; - }, - /** @return -1 if the bone was not found. */ - findSlotIndex: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].name == slotName) return i; - return -1; - }, - /** @return May be null. */ - findSkin: function (skinName) { - var skins = this.skins; - for (var i = 0, n = skins.length; i < n; i++) - if (skins[i].name == skinName) return skins[i]; - return null; - }, - /** @return May be null. */ - findAnimation: function (animationName) { - var animations = this.animations; - for (var i = 0, n = animations.length; i < n; i++) - if (animations[i].name == animationName) return animations[i]; - return null; - } -}; - -spine.Skeleton = function (skeletonData) { - this.data = skeletonData; - - this.bones = []; - for (var i = 0, n = skeletonData.bones.length; i < n; i++) { - var boneData = skeletonData.bones[i]; - var parent = !boneData.parent ? null : this.bones[skeletonData.bones.indexOf(boneData.parent)]; - this.bones.push(new spine.Bone(boneData, parent)); - } - - this.slots = []; - this.drawOrder = []; - for (var i = 0, n = skeletonData.slots.length; i < n; i++) { - var slotData = skeletonData.slots[i]; - var bone = this.bones[skeletonData.bones.indexOf(slotData.boneData)]; - var slot = new spine.Slot(slotData, this, bone); - this.slots.push(slot); - this.drawOrder.push(slot); - } -}; -spine.Skeleton.prototype = { - x: 0, y: 0, - skin: null, - r: 1, g: 1, b: 1, a: 1, - time: 0, - flipX: false, flipY: false, - /** Updates the world transform for each bone. */ - updateWorldTransform: function () { - var flipX = this.flipX; - var flipY = this.flipY; - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - bones[i].updateWorldTransform(flipX, flipY); - }, - /** Sets the bones and slots to their setup pose values. */ - setToSetupPose: function () { - this.setBonesToSetupPose(); - this.setSlotsToSetupPose(); - }, - setBonesToSetupPose: function () { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - bones[i].setToSetupPose(); - }, - setSlotsToSetupPose: function () { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - slots[i].setToSetupPose(i); - }, - /** @return May return null. */ - getRootBone: function () { - return this.bones.length == 0 ? null : this.bones[0]; - }, - /** @return May be null. */ - findBone: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].data.name == boneName) return bones[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findBoneIndex: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].data.name == boneName) return i; - return -1; - }, - /** @return May be null. */ - findSlot: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].data.name == slotName) return slots[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findSlotIndex: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].data.name == slotName) return i; - return -1; - }, - setSkinByName: function (skinName) { - var skin = this.data.findSkin(skinName); - if (!skin) throw "Skin not found: " + skinName; - this.setSkin(skin); - }, - /** Sets the skin used to look up attachments not found in the {@link SkeletonData#getDefaultSkin() default skin}. Attachments - * from the new skin are attached if the corresponding attachment from the old skin was attached. - * @param newSkin May be null. */ - setSkin: function (newSkin) { - if (this.skin && newSkin) newSkin._attachAll(this, this.skin); - this.skin = newSkin; - }, - /** @return May be null. */ - getAttachmentBySlotName: function (slotName, attachmentName) { - return this.getAttachmentBySlotIndex(this.data.findSlotIndex(slotName), attachmentName); - }, - /** @return May be null. */ - getAttachmentBySlotIndex: function (slotIndex, attachmentName) { - if (this.skin) { - var attachment = this.skin.getAttachment(slotIndex, attachmentName); - if (attachment) return attachment; - } - if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); - return null; - }, - /** @param attachmentName May be null. */ - setAttachment: function (slotName, attachmentName) { - var slots = this.slots; - for (var i = 0, n = slots.size; i < n; i++) { - var slot = slots[i]; - if (slot.data.name == slotName) { - var attachment = null; - if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); - if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; - } - slot.setAttachment(attachment); - return; - } - } - throw "Slot not found: " + slotName; - }, - update: function (delta) { - time += delta; - } -}; - -spine.AttachmentType = { - region: 0 -}; - -spine.RegionAttachment = function () { - this.offset = []; - this.offset.length = 8; - this.uvs = []; - this.uvs.length = 8; -}; -spine.RegionAttachment.prototype = { - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1, - width: 0, height: 0, - rendererObject: null, - regionOffsetX: 0, regionOffsetY: 0, - regionWidth: 0, regionHeight: 0, - regionOriginalWidth: 0, regionOriginalHeight: 0, - setUVs: function (u, v, u2, v2, rotate) { - var uvs = this.uvs; - if (rotate) { - uvs[2/*X2*/] = u; - uvs[3/*Y2*/] = v2; - uvs[4/*X3*/] = u; - uvs[5/*Y3*/] = v; - uvs[6/*X4*/] = u2; - uvs[7/*Y4*/] = v; - uvs[0/*X1*/] = u2; - uvs[1/*Y1*/] = v2; - } else { - uvs[0/*X1*/] = u; - uvs[1/*Y1*/] = v2; - uvs[2/*X2*/] = u; - uvs[3/*Y2*/] = v; - uvs[4/*X3*/] = u2; - uvs[5/*Y3*/] = v; - uvs[6/*X4*/] = u2; - uvs[7/*Y4*/] = v2; - } - }, - updateOffset: function () { - var regionScaleX = this.width / this.regionOriginalWidth * this.scaleX; - var regionScaleY = this.height / this.regionOriginalHeight * this.scaleY; - var localX = -this.width / 2 * this.scaleX + this.regionOffsetX * regionScaleX; - var localY = -this.height / 2 * this.scaleY + this.regionOffsetY * regionScaleY; - var localX2 = localX + this.regionWidth * regionScaleX; - var localY2 = localY + this.regionHeight * regionScaleY; - var radians = this.rotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - var localXCos = localX * cos + this.x; - var localXSin = localX * sin; - var localYCos = localY * cos + this.y; - var localYSin = localY * sin; - var localX2Cos = localX2 * cos + this.x; - var localX2Sin = localX2 * sin; - var localY2Cos = localY2 * cos + this.y; - var localY2Sin = localY2 * sin; - var offset = this.offset; - offset[0/*X1*/] = localXCos - localYSin; - offset[1/*Y1*/] = localYCos + localXSin; - offset[2/*X2*/] = localXCos - localY2Sin; - offset[3/*Y2*/] = localY2Cos + localXSin; - offset[4/*X3*/] = localX2Cos - localY2Sin; - offset[5/*Y3*/] = localY2Cos + localX2Sin; - offset[6/*X4*/] = localX2Cos - localYSin; - offset[7/*Y4*/] = localYCos + localX2Sin; - }, - computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; - y += bone.worldY; - var m00 = bone.m00; - var m01 = bone.m01; - var m10 = bone.m10; - var m11 = bone.m11; - var offset = this.offset; - vertices[0/*X1*/] = offset[0/*X1*/] * m00 + offset[1/*Y1*/] * m01 + x; - vertices[1/*Y1*/] = offset[0/*X1*/] * m10 + offset[1/*Y1*/] * m11 + y; - vertices[2/*X2*/] = offset[2/*X2*/] * m00 + offset[3/*Y2*/] * m01 + x; - vertices[3/*Y2*/] = offset[2/*X2*/] * m10 + offset[3/*Y2*/] * m11 + y; - vertices[4/*X3*/] = offset[4/*X3*/] * m00 + offset[5/*X3*/] * m01 + x; - vertices[5/*X3*/] = offset[4/*X3*/] * m10 + offset[5/*X3*/] * m11 + y; - vertices[6/*X4*/] = offset[6/*X4*/] * m00 + offset[7/*Y4*/] * m01 + x; - vertices[7/*Y4*/] = offset[6/*X4*/] * m10 + offset[7/*Y4*/] * m11 + y; - } -} - -spine.AnimationStateData = function (skeletonData) { - this.skeletonData = skeletonData; - this.animationToMixTime = {}; -}; -spine.AnimationStateData.prototype = { - defaultMix: 0, - setMixByName: function (fromName, toName, duration) { - var from = this.skeletonData.findAnimation(fromName); - if (!from) throw "Animation not found: " + fromName; - var to = this.skeletonData.findAnimation(toName); - if (!to) throw "Animation not found: " + toName; - this.setMix(from, to, duration); - }, - setMix: function (from, to, duration) { - this.animationToMixTime[from.name + ":" + to.name] = duration; - }, - getMix: function (from, to) { - var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : this.defaultMix; - } -}; - -spine.AnimationState = function (stateData) { - this.data = stateData; - this.queue = []; -}; -spine.AnimationState.prototype = { - current: null, - previous: null, - currentTime: 0, - previousTime: 0, - currentLoop: false, - previousLoop: false, - mixTime: 0, - mixDuration: 0, - update: function (delta) { - this.currentTime += delta; - this.previousTime += delta; - this.mixTime += delta; - - if (this.queue.length > 0) { - var entry = this.queue[0]; - if (this.currentTime >= entry.delay) { - this._setAnimation(entry.animation, entry.loop); - this.queue.shift(); - } - } - }, - apply: function (skeleton) { - if (!this.current) return; - if (this.previous) { - this.previous.apply(skeleton, this.previousTime, this.previousLoop); - var alpha = this.mixTime / this.mixDuration; - if (alpha >= 1) { - alpha = 1; - this.previous = null; - } - this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else - this.current.apply(skeleton, this.currentTime, this.currentLoop); - }, - clearAnimation: function () { - this.previous = null; - this.current = null; - this.queue.length = 0; - }, - _setAnimation: function (animation, loop) { - this.previous = null; - if (animation && this.current) { - this.mixDuration = this.data.getMix(this.current, animation); - if (this.mixDuration > 0) { - this.mixTime = 0; - this.previous = this.current; - this.previousTime = this.currentTime; - this.previousLoop = this.currentLoop; - } - } - this.current = animation; - this.currentLoop = loop; - this.currentTime = 0; - }, - /** @see #setAnimation(Animation, Boolean) */ - setAnimationByName: function (animationName, loop) { - var animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw "Animation not found: " + animationName; - this.setAnimation(animation, loop); - }, - /** Set the current animation. Any queued animations are cleared and the current animation time is set to 0. - * @param animation May be null. */ - setAnimation: function (animation, loop) { - this.queue.length = 0; - this._setAnimation(animation, loop); - }, - /** @see #addAnimation(Animation, Boolean, Number) */ - addAnimationByName: function (animationName, loop, delay) { - var animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw "Animation not found: " + animationName; - this.addAnimation(animation, loop, delay); - }, - /** Adds an animation to be played delay seconds after the current or last queued animation. - * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */ - addAnimation: function (animation, loop, delay) { - var entry = {}; - entry.animation = animation; - entry.loop = loop; - - if (!delay || delay <= 0) { - var previousAnimation = this.queue.length == 0 ? this.current : this.queue[this.queue.length - 1].animation; - if (previousAnimation != null) - delay = previousAnimation.duration - this.data.getMix(previousAnimation, animation) + (delay || 0); - else - delay = 0; - } - entry.delay = delay; - - this.queue.push(entry); - }, - /** Returns true if no animation is set or if the current time is greater than the animation duration, regardless of looping. */ - isComplete: function () { - return !this.current || this.currentTime >= this.current.duration; - } -}; - -spine.SkeletonJson = function (attachmentLoader) { - this.attachmentLoader = attachmentLoader; -}; -spine.SkeletonJson.prototype = { - scale: 1, - readSkeletonData: function (root) { - var skeletonData = new spine.SkeletonData(); - - // Bones. - var bones = root["bones"]; - for (var i = 0, n = bones.length; i < n; i++) { - var boneMap = bones[i]; - var parent = null; - if (boneMap["parent"]) { - parent = skeletonData.findBone(boneMap["parent"]); - if (!parent) throw "Parent bone not found: " + boneMap["parent"]; - } - var boneData = new spine.BoneData(boneMap["name"], parent); - boneData.length = (boneMap["length"] || 0) * this.scale; - boneData.x = (boneMap["x"] || 0) * this.scale; - boneData.y = (boneMap["y"] || 0) * this.scale; - boneData.rotation = (boneMap["rotation"] || 0); - boneData.scaleX = boneMap["scaleX"] || 1; - boneData.scaleY = boneMap["scaleY"] || 1; - skeletonData.bones.push(boneData); - } - - // Slots. - var slots = root["slots"]; - for (var i = 0, n = slots.length; i < n; i++) { - var slotMap = slots[i]; - var boneData = skeletonData.findBone(slotMap["bone"]); - if (!boneData) throw "Slot bone not found: " + slotMap["bone"]; - var slotData = new spine.SlotData(slotMap["name"], boneData); - - var color = slotMap["color"]; - if (color) { - slotData.r = spine.SkeletonJson.toColor(color, 0); - slotData.g = spine.SkeletonJson.toColor(color, 1); - slotData.b = spine.SkeletonJson.toColor(color, 2); - slotData.a = spine.SkeletonJson.toColor(color, 3); - } - - slotData.attachmentName = slotMap["attachment"]; - - skeletonData.slots.push(slotData); - } - - // Skins. - var skins = root["skins"]; - for (var skinName in skins) { - if (!skins.hasOwnProperty(skinName)) continue; - var skinMap = skins[skinName]; - var skin = new spine.Skin(skinName); - for (var slotName in skinMap) { - if (!skinMap.hasOwnProperty(slotName)) continue; - var slotIndex = skeletonData.findSlotIndex(slotName); - var slotEntry = skinMap[slotName]; - for (var attachmentName in slotEntry) { - if (!slotEntry.hasOwnProperty(attachmentName)) continue; - var attachment = this.readAttachment(skin, attachmentName, slotEntry[attachmentName]); - if (attachment != null) skin.addAttachment(slotIndex, attachmentName, attachment); - } - } - skeletonData.skins.push(skin); - if (skin.name == "default") skeletonData.defaultSkin = skin; - } - - // Animations. - var animations = root["animations"]; - for (var animationName in animations) { - if (!animations.hasOwnProperty(animationName)) continue; - this.readAnimation(animationName, animations[animationName], skeletonData); - } - - return skeletonData; - }, - readAttachment: function (skin, name, map) { - name = map["name"] || name; - - var type = spine.AttachmentType[map["type"] || "region"]; - - if (type == spine.AttachmentType.region) { - var attachment = new spine.RegionAttachment(); - attachment.x = (map["x"] || 0) * this.scale; - attachment.y = (map["y"] || 0) * this.scale; - attachment.scaleX = map["scaleX"] || 1; - attachment.scaleY = map["scaleY"] || 1; - attachment.rotation = map["rotation"] || 0; - attachment.width = (map["width"] || 32) * this.scale; - attachment.height = (map["height"] || 32) * this.scale; - attachment.updateOffset(); - - attachment.rendererObject = {}; - attachment.rendererObject.name = name; - attachment.rendererObject.scale = {}; - attachment.rendererObject.scale.x = attachment.scaleX; - attachment.rendererObject.scale.y = attachment.scaleY; - attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; - return attachment; - } - - throw "Unknown attachment type: " + type; - }, - - readAnimation: function (name, map, skeletonData) { - var timelines = []; - var duration = 0; - - var bones = map["bones"]; - for (var boneName in bones) { - if (!bones.hasOwnProperty(boneName)) continue; - var boneIndex = skeletonData.findBoneIndex(boneName); - if (boneIndex == -1) throw "Bone not found: " + boneName; - var boneMap = bones[boneName]; - - for (var timelineName in boneMap) { - if (!boneMap.hasOwnProperty(timelineName)) continue; - var values = boneMap[timelineName]; - if (timelineName == "rotate") { - var timeline = new spine.RotateTimeline(values.length); - timeline.boneIndex = boneIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - timeline.setFrame(frameIndex, valueMap["time"], valueMap["angle"]); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 2 - 2]); - - } else if (timelineName == "translate" || timelineName == "scale") { - var timeline; - var timelineScale = 1; - if (timelineName == "scale") - timeline = new spine.ScaleTimeline(values.length); - else { - timeline = new spine.TranslateTimeline(values.length); - timelineScale = this.scale; - } - timeline.boneIndex = boneIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - var x = (valueMap["x"] || 0) * timelineScale; - var y = (valueMap["y"] || 0) * timelineScale; - timeline.setFrame(frameIndex, valueMap["time"], x, y); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - - } else - throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; - } - } - var slots = map["slots"]; - for (var slotName in slots) { - if (!slots.hasOwnProperty(slotName)) continue; - var slotMap = slots[slotName]; - var slotIndex = skeletonData.findSlotIndex(slotName); - - for (var timelineName in slotMap) { - if (!slotMap.hasOwnProperty(timelineName)) continue; - var values = slotMap[timelineName]; - if (timelineName == "color") { - var timeline = new spine.ColorTimeline(values.length); - timeline.slotIndex = slotIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - var color = valueMap["color"]; - var r = spine.SkeletonJson.toColor(color, 0); - var g = spine.SkeletonJson.toColor(color, 1); - var b = spine.SkeletonJson.toColor(color, 2); - var a = spine.SkeletonJson.toColor(color, 3); - timeline.setFrame(frameIndex, valueMap["time"], r, g, b, a); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 5 - 5]); - - } else if (timelineName == "attachment") { - var timeline = new spine.AttachmentTimeline(values.length); - timeline.slotIndex = slotIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); - - } else - throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; - } - } - skeletonData.animations.push(new spine.Animation(name, timelines, duration)); - } -}; -spine.SkeletonJson.readCurve = function (timeline, frameIndex, valueMap) { - var curve = valueMap["curve"]; - if (!curve) return; - if (curve == "stepped") - timeline.curves.setStepped(frameIndex); - else if (curve instanceof Array) - timeline.curves.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); -}; -spine.SkeletonJson.toColor = function (hexString, colorIndex) { - if (hexString.length != 8) throw "Color hexidecimal length must be 8, recieved: " + hexString; - return parseInt(hexString.substring(colorIndex * 2, 2), 16) / 255; -}; - -spine.Atlas = function (atlasText, textureLoader) { - this.textureLoader = textureLoader; - this.pages = []; - this.regions = []; - - var reader = new spine.AtlasReader(atlasText); - var tuple = []; - tuple.length = 4; - var page = null; - while (true) { - var line = reader.readLine(); - if (line == null) break; - line = reader.trim(line); - if (line.length == 0) - page = null; - else if (!page) { - page = new spine.AtlasPage(); - page.name = line; - - page.format = spine.Atlas.Format[reader.readValue()]; - - reader.readTuple(tuple); - page.minFilter = spine.Atlas.TextureFilter[tuple[0]]; - page.magFilter = spine.Atlas.TextureFilter[tuple[1]]; - - var direction = reader.readValue(); - page.uWrap = spine.Atlas.TextureWrap.clampToEdge; - page.vWrap = spine.Atlas.TextureWrap.clampToEdge; - if (direction == "x") - page.uWrap = spine.Atlas.TextureWrap.repeat; - else if (direction == "y") - page.vWrap = spine.Atlas.TextureWrap.repeat; - else if (direction == "xy") - page.uWrap = page.vWrap = spine.Atlas.TextureWrap.repeat; - - textureLoader.load(page, line); - - this.pages.push(page); - - } else { - var region = new spine.AtlasRegion(); - region.name = line; - region.page = page; - - region.rotate = reader.readValue() == "true"; - - reader.readTuple(tuple); - var x = parseInt(tuple[0]); - var y = parseInt(tuple[1]); - - reader.readTuple(tuple); - var width = parseInt(tuple[0]); - var height = parseInt(tuple[1]); - - region.u = x / page.width; - region.v = y / page.height; - if (region.rotate) { - region.u2 = (x + height) / page.width; - region.v2 = (y + width) / page.height; - } else { - region.u2 = (x + width) / page.width; - region.v2 = (y + height) / page.height; - } - region.x = x; - region.y = y; - region.width = Math.abs(width); - region.height = Math.abs(height); - - if (reader.readTuple(tuple) == 4) { // split is optional - region.splits = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; - - if (reader.readTuple(tuple) == 4) { // pad is optional, but only present with splits - region.pads = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; - - reader.readTuple(tuple); - } - } - - region.originalWidth = parseInt(tuple[0]); - region.originalHeight = parseInt(tuple[1]); - - reader.readTuple(tuple); - region.offsetX = parseInt(tuple[0]); - region.offsetY = parseInt(tuple[1]); - - region.index = parseInt(reader.readValue()); - - this.regions.push(region); - } - } -}; -spine.Atlas.prototype = { - findRegion: function (name) { - var regions = this.regions; - for (var i = 0, n = regions.length; i < n; i++) - if (regions[i].name == name) return regions[i]; - return null; - }, - dispose: function () { - var pages = this.pages; - for (var i = 0, n = pages.length; i < n; i++) - this.textureLoader.unload(pages[i].rendererObject); - }, - updateUVs: function (page) { - var regions = this.regions; - for (var i = 0, n = regions.length; i < n; i++) { - var region = regions[i]; - if (region.page != page) continue; - region.u = region.x / page.width; - region.v = region.y / page.height; - if (region.rotate) { - region.u2 = (region.x + region.height) / page.width; - region.v2 = (region.y + region.width) / page.height; - } else { - region.u2 = (region.x + region.width) / page.width; - region.v2 = (region.y + region.height) / page.height; - } - } - } -}; - -spine.Atlas.Format = { - alpha: 0, - intensity: 1, - luminanceAlpha: 2, - rgb565: 3, - rgba4444: 4, - rgb888: 5, - rgba8888: 6 -}; - -spine.Atlas.TextureFilter = { - nearest: 0, - linear: 1, - mipMap: 2, - mipMapNearestNearest: 3, - mipMapLinearNearest: 4, - mipMapNearestLinear: 5, - mipMapLinearLinear: 6 -}; - -spine.Atlas.TextureWrap = { - mirroredRepeat: 0, - clampToEdge: 1, - repeat: 2 -}; - -spine.AtlasPage = function () {}; -spine.AtlasPage.prototype = { - name: null, - format: null, - minFilter: null, - magFilter: null, - uWrap: null, - vWrap: null, - rendererObject: null, - width: 0, - height: 0 -}; - -spine.AtlasRegion = function () {}; -spine.AtlasRegion.prototype = { - page: null, - name: null, - x: 0, y: 0, - width: 0, height: 0, - u: 0, v: 0, u2: 0, v2: 0, - offsetX: 0, offsetY: 0, - originalWidth: 0, originalHeight: 0, - index: 0, - rotate: false, - splits: null, - pads: null, -}; - -spine.AtlasReader = function (text) { - this.lines = text.split(/\r\n|\r|\n/); -}; -spine.AtlasReader.prototype = { - index: 0, - trim: function (value) { - return value.replace(/^\s+|\s+$/g, ""); - }, - readLine: function () { - if (this.index >= this.lines.length) return null; - return this.lines[this.index++]; - }, - readValue: function () { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) throw "Invalid line: " + line; - return this.trim(line.substring(colon + 1)); - }, - /** Returns the number of tuple values read (2 or 4). */ - readTuple: function (tuple) { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) throw "Invalid line: " + line; - var i = 0, lastMatch= colon + 1; - for (; i < 3; i++) { - var comma = line.indexOf(",", lastMatch); - if (comma == -1) { - if (i == 0) throw "Invalid line: " + line; - break; - } - tuple[i] = this.trim(line.substr(lastMatch, comma - lastMatch)); - lastMatch = comma + 1; - } - tuple[i] = this.trim(line.substring(lastMatch)); - return i + 1; - } -} - -spine.AtlasAttachmentLoader = function (atlas) { - this.atlas = atlas; -} -spine.AtlasAttachmentLoader.prototype = { - newAttachment: function (skin, type, name) { - switch (type) { - case spine.AttachmentType.region: - var region = this.atlas.findRegion(name); - if (!region) throw "Region not found in atlas: " + name + " (" + type + ")"; - var attachment = new spine.RegionAttachment(name); - attachment.rendererObject = region; - attachment.setUVs(region.u, region.v, region.u2, region.v2, region.rotate); - attachment.regionOffsetX = region.offsetX; - attachment.regionOffsetY = region.offsetY; - attachment.regionWidth = region.width; - attachment.regionHeight = region.height; - attachment.regionOriginalWidth = region.originalWidth; - attachment.regionOriginalHeight = region.originalHeight; - return attachment; - } - throw "Unknown attachment type: " + type; - } -} - -PIXI.AnimCache = {}; -spine.Bone.yDown = true; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * This object is one that will allow you to specify custom rendering functions based on render type - * - * @class CustomRenderable - * @extends DisplayObject - * @constructor - */ -PIXI.CustomRenderable = function() -{ - PIXI.DisplayObject.call( this ); - - this.renderable = true; -} - -// constructor -PIXI.CustomRenderable.prototype = Object.create( PIXI.DisplayObject.prototype ); -PIXI.CustomRenderable.prototype.constructor = PIXI.CustomRenderable; - -/** - * If this object is being rendered by a CanvasRenderer it will call this callback - * - * @method renderCanvas - * @param renderer {CanvasRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.renderCanvas = function(renderer) -{ - // override! -} - -/** - * If this object is being rendered by a WebGLRenderer it will call this callback to initialize - * - * @method initWebGL - * @param renderer {WebGLRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.initWebGL = function(renderer) -{ - // override! -} - -/** - * If this object is being rendered by a WebGLRenderer it will call this callback - * - * @method renderWebGL - * @param renderer {WebGLRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.renderWebGL = function(renderGroup, projectionMatrix) -{ - // not sure if both needed? but ya have for now! - // override! -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.BaseTextureCache = {}; -PIXI.texturesToUpdate = []; -PIXI.texturesToDestroy = []; - -/** - * A texture stores the information that represents an image. All textures have a base texture - * - * @class BaseTexture - * @uses EventTarget - * @constructor - * @param source {String} the source object (image or canvas) - */ -PIXI.BaseTexture = function(source) -{ - PIXI.EventTarget.call( this ); - - /** - * [read-only] The width of the base texture set when the image has loaded - * - * @property width - * @type Number - * @readOnly - */ - this.width = 100; - - /** - * [read-only] The height of the base texture set when the image has loaded - * - * @property height - * @type Number - * @readOnly - */ - this.height = 100; - - /** - * [read-only] Describes if the base texture has loaded or not - * - * @property hasLoaded - * @type Boolean - * @readOnly - */ - this.hasLoaded = false; - - /** - * The source that is loaded to create the texture - * - * @property source - * @type Image - */ - this.source = source; - - if(!source)return; - - if(this.source instanceof Image || this.source instanceof HTMLImageElement) - { - if(this.source.complete) - { - this.hasLoaded = true; - this.width = this.source.width; - this.height = this.source.height; - - PIXI.texturesToUpdate.push(this); - } - else - { - - var scope = this; - this.source.onload = function(){ - - scope.hasLoaded = true; - scope.width = scope.source.width; - scope.height = scope.source.height; - - // add it to somewhere... - PIXI.texturesToUpdate.push(scope); - scope.dispatchEvent( { type: 'loaded', content: scope } ); - } - // this.image.src = imageUrl; - } - } - else - { - this.hasLoaded = true; - this.width = this.source.width; - this.height = this.source.height; - - PIXI.texturesToUpdate.push(this); - } - - this._powerOf2 = false; -} - -PIXI.BaseTexture.prototype.constructor = PIXI.BaseTexture; - -/** - * Destroys this base texture - * - * @method destroy - */ -PIXI.BaseTexture.prototype.destroy = function() -{ - if(this.source instanceof Image) - { - this.source.src = null; - } - this.source = null; - PIXI.texturesToDestroy.push(this); -} - -/** - * Helper function that returns a base texture based on an image url - * If the image is not in the base texture cache it will be created and loaded - * - * @static - * @method fromImage - * @param imageUrl {String} The image url of the texture - * @return BaseTexture - */ -PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) -{ - var baseTexture = PIXI.BaseTextureCache[imageUrl]; - if(!baseTexture) - { - // new Image() breaks tex loading in some versions of Chrome. - // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); - if (crossorigin) - { - image.crossOrigin = ''; - } - image.src = imageUrl; - baseTexture = new PIXI.BaseTexture(image); - PIXI.BaseTextureCache[imageUrl] = baseTexture; - } - - return baseTexture; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.TextureCache = {}; -PIXI.FrameCache = {}; - -/** - * A texture stores the information that represents an image or part of an image. It cannot be added - * to the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used - * - * @class Texture - * @uses EventTarget - * @constructor - * @param baseTexture {BaseTexture} The base texture source to create the texture from - * @param frame {Rectangle} The rectangle frame of the texture to show - */ -PIXI.Texture = function(baseTexture, frame) -{ - PIXI.EventTarget.call( this ); - - if(!frame) - { - this.noFrame = true; - frame = new PIXI.Rectangle(0,0,1,1); - } - - if(baseTexture instanceof PIXI.Texture) - baseTexture = baseTexture.baseTexture; - - /** - * The base texture of this texture - * - * @property baseTexture - * @type BaseTexture - */ - this.baseTexture = baseTexture; - - /** - * The frame specifies the region of the base texture that this texture uses - * - * @property frame - * @type Rectangle - */ - this.frame = frame; - - /** - * The trim point - * - * @property trim - * @type Point - */ - this.trim = new PIXI.Point(); - - this.scope = this; - - if(baseTexture.hasLoaded) - { - if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); - //console.log(frame) - - this.setFrame(frame); - } - else - { - var scope = this; - baseTexture.addEventListener( 'loaded', function(){ scope.onBaseTextureLoaded()} ); - } -} - -PIXI.Texture.prototype.constructor = PIXI.Texture; - -/** - * Called when the base texture is loaded - * - * @method onBaseTextureLoaded - * @param event - * @private - */ -PIXI.Texture.prototype.onBaseTextureLoaded = function(event) -{ - var baseTexture = this.baseTexture; - baseTexture.removeEventListener( 'loaded', this.onLoaded ); - - if(this.noFrame)this.frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); - this.noFrame = false; - this.width = this.frame.width; - this.height = this.frame.height; - - this.scope.dispatchEvent( { type: 'update', content: this } ); -} - -/** - * Destroys this texture - * - * @method destroy - * @param destroyBase {Boolean} Whether to destroy the base texture as well - */ -PIXI.Texture.prototype.destroy = function(destroyBase) -{ - if(destroyBase)this.baseTexture.destroy(); -} - -/** - * Specifies the rectangle region of the baseTexture - * - * @method setFrame - * @param frame {Rectangle} The frame of the texture to set it to - */ -PIXI.Texture.prototype.setFrame = function(frame) -{ - this.frame = frame; - this.width = frame.width; - this.height = frame.height; - - if(frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height) - { - throw new Error("Texture Error: frame does not fit inside the base Texture dimensions " + this); - } - - this.updateFrame = true; - - PIXI.Texture.frameUpdates.push(this); - //this.dispatchEvent( { type: 'update', content: this } ); -} - -/** - * Helper function that returns a texture based on an image url - * If the image is not in the texture cache it will be created and loaded - * - * @static - * @method fromImage - * @param imageUrl {String} The image url of the texture - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - * @return Texture - */ -PIXI.Texture.fromImage = function(imageUrl, crossorigin) -{ - var texture = PIXI.TextureCache[imageUrl]; - - if(!texture) - { - texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); - PIXI.TextureCache[imageUrl] = texture; - } - - return texture; -} - -/** - * Helper function that returns a texture based on a frame id - * If the frame id is not in the texture cache an error will be thrown - * - * @static - * @method fromFrame - * @param frameId {String} The frame id of the texture - * @return Texture - */ -PIXI.Texture.fromFrame = function(frameId) -{ - var texture = PIXI.TextureCache[frameId]; - if(!texture)throw new Error("The frameId '"+ frameId +"' does not exist in the texture cache " + this); - return texture; -} - -/** - * Helper function that returns a texture based on a canvas element - * If the canvas is not in the texture cache it will be created and loaded - * - * @static - * @method fromCanvas - * @param canvas {Canvas} The canvas element source of the texture - * @return Texture - */ -PIXI.Texture.fromCanvas = function(canvas) -{ - var baseTexture = new PIXI.BaseTexture(canvas); - return new PIXI.Texture(baseTexture); -} - - -/** - * Adds a texture to the textureCache. - * - * @static - * @method addTextureToCache - * @param texture {Texture} - * @param id {String} the id that the texture will be stored against. - */ -PIXI.Texture.addTextureToCache = function(texture, id) -{ - PIXI.TextureCache[id] = texture; -} - -/** - * Remove a texture from the textureCache. - * - * @static - * @method removeTextureFromCache - * @param id {String} the id of the texture to be removed - * @return {Texture} the texture that was removed - */ -PIXI.Texture.removeTextureFromCache = function(id) -{ - var texture = PIXI.TextureCache[id] - PIXI.TextureCache[id] = null; - return texture; -} - -// this is more for webGL.. it contains updated frames.. -PIXI.Texture.frameUpdates = []; - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - A RenderTexture is a special texture that allows any pixi displayObject to be rendered to it. - - __Hint__: All DisplayObjects (exmpl. Sprites) that renders on RenderTexture should be preloaded. - Otherwise black rectangles will be drawn instead. - - RenderTexture takes snapshot of DisplayObject passed to render method. If DisplayObject is passed to render method, position and rotation of it will be ignored. For example: - - var renderTexture = new PIXI.RenderTexture(800, 600); - var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - sprite.position.x = 800/2; - sprite.position.y = 600/2; - sprite.anchor.x = 0.5; - sprite.anchor.y = 0.5; - renderTexture.render(sprite); - - Sprite in this case will be rendered to 0,0 position. To render this sprite at center DisplayObjectContainer should be used: - - var doc = new PIXI.DisplayObjectContainer(); - doc.addChild(sprite); - renderTexture.render(doc); // Renders to center of renderTexture - - @class RenderTexture - @extends Texture - @constructor - @param width {Number} The width of the render texture - @param height {Number} The height of the render texture - */ -PIXI.RenderTexture = function(width, height) -{ - PIXI.EventTarget.call( this ); - - this.width = width || 100; - this.height = height || 100; - - this.indetityMatrix = PIXI.mat3.create(); - - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); - - if(PIXI.gl) - { - this.initWebGL(); - } - else - { - this.initCanvas(); - } -} - -PIXI.RenderTexture.prototype = Object.create( PIXI.Texture.prototype ); -PIXI.RenderTexture.prototype.constructor = PIXI.RenderTexture; - -/** - * Initializes the webgl data for this texture - * - * @method initWebGL - * @private - */ -PIXI.RenderTexture.prototype.initWebGL = function() -{ - var gl = PIXI.gl; - this.glFramebuffer = gl.createFramebuffer(); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - - this.glFramebuffer.width = this.width; - this.glFramebuffer.height = this.height; - - this.baseTexture = new PIXI.BaseTexture(); - - this.baseTexture.width = this.width; - this.baseTexture.height = this.height; - - this.baseTexture._glTexture = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - - this.baseTexture.isRender = true; - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.baseTexture._glTexture, 0); - - // create a projection matrix.. - this.projection = new PIXI.Point(this.width/2 , -this.height/2); - - // set the correct render function.. - this.render = this.renderWebGL; -} - - -PIXI.RenderTexture.prototype.resize = function(width, height) -{ - - this.width = width; - this.height = height; - - if(PIXI.gl) - { - this.projection.x = this.width/2 - this.projection.y = -this.height/2; - - var gl = PIXI.gl; - gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - } - else - { - - this.frame.width = this.width - this.frame.height = this.height; - this.renderer.resize(this.width, this.height); - } -} - -/** - * Initializes the canvas data for this texture - * - * @method initCanvas - * @private - */ -PIXI.RenderTexture.prototype.initCanvas = function() -{ - this.renderer = new PIXI.CanvasRenderer(this.width, this.height, null, 0); - - this.baseTexture = new PIXI.BaseTexture(this.renderer.view); - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); - - this.render = this.renderCanvas; -} - -/** - * This function will draw the display object to the texture. - * - * @method renderWebGL - * @param displayObject {DisplayObject} The display object to render this texture on - * @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn - * @private - */ -PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, clear) -{ - var gl = PIXI.gl; - - // enable the alpha color mask.. - gl.colorMask(true, true, true, true); - - gl.viewport(0, 0, this.width, this.height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - - if(clear) - { - gl.clearColor(0,0,0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - } - - // THIS WILL MESS WITH HIT TESTING! - var children = displayObject.children; - - //TODO -? create a new one??? dont think so! - var originalWorldTransform = displayObject.worldTransform; - displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; - // modify to flip... - displayObject.worldTransform[4] = -1; - displayObject.worldTransform[5] = this.projection.y * -2; - - if(position) - { - displayObject.worldTransform[2] = position.x; - displayObject.worldTransform[5] -= position.y; - } - - PIXI.visibleCount++; - displayObject.vcount = PIXI.visibleCount; - - for(var i=0,j=children.length; i} assetURLs an array of image/sprite sheet urls that you would like loaded - * supported. Supported image formats include "jpeg", "jpg", "png", "gif". Supported - * sprite sheet data formats only include "JSON" at this time. Supported bitmap font - * data formats include "xml" and "fnt". - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.AssetLoader = function(assetURLs, crossorigin) -{ - PIXI.EventTarget.call(this); - - /** - * The array of asset URLs that are going to be loaded - * - * @property assetURLs - * @type Array - */ - this.assetURLs = assetURLs; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * Maps file extension to loader types - * - * @property loadersByType - * @type Object - */ - this.loadersByType = { - "jpg": PIXI.ImageLoader, - "jpeg": PIXI.ImageLoader, - "png": PIXI.ImageLoader, - "gif": PIXI.ImageLoader, - "json": PIXI.JsonLoader, - "anim": PIXI.SpineLoader, - "xml": PIXI.BitmapFontLoader, - "fnt": PIXI.BitmapFontLoader - }; - - -}; - -/** - * Fired when an item has loaded - * @event onProgress - */ - -/** - * Fired when all the assets have loaded - * @event onComplete - */ - -// constructor -PIXI.AssetLoader.prototype.constructor = PIXI.AssetLoader; - -/** - * Starts loading the assets sequentially - * - * @method load - */ -PIXI.AssetLoader.prototype.load = function() -{ - var scope = this; - - this.loadCount = this.assetURLs.length; - - for (var i=0; i < this.assetURLs.length; i++) - { - var fileName = this.assetURLs[i]; - var fileType = fileName.split(".").pop().toLowerCase(); - - var loaderClass = this.loadersByType[fileType]; - if(!loaderClass) - throw new Error(fileType + " is an unsupported file type"); - - var loader = new loaderClass(fileName, this.crossorigin); - - loader.addEventListener("loaded", function() - { - scope.onAssetLoaded(); - }); - loader.load(); - } -}; - -/** - * Invoked after each file is loaded - * - * @method onAssetLoaded - * @private - */ -PIXI.AssetLoader.prototype.onAssetLoaded = function() -{ - this.loadCount--; - this.dispatchEvent({type: "onProgress", content: this}); - if(this.onProgress) this.onProgress(); - - if(this.loadCount == 0) - { - this.dispatchEvent({type: "onComplete", content: this}); - if(this.onComplete) this.onComplete(); - } -}; - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The json file loader is used to load in JSON data and parsing it - * When loaded this class will dispatch a "loaded" event - * If load failed this class will dispatch a "error" event - * - * @class JsonLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the JSON file - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.JsonLoader = function (url, crossorigin) { - PIXI.EventTarget.call(this); - - /** - * The url of the bitmap font data - * - * @property url - * @type String - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * [read-only] The base url of the bitmap font data - * - * @property baseUrl - * @type String - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ""); - - /** - * [read-only] Whether the data has loaded yet - * - * @property loaded - * @type Boolean - * @readOnly - */ - this.loaded = false; - -}; - -// constructor -PIXI.JsonLoader.prototype.constructor = PIXI.JsonLoader; - -/** - * Loads the JSON data - * - * @method load - */ -PIXI.JsonLoader.prototype.load = function () { - this.ajaxRequest = new AjaxRequest(); - var scope = this; - this.ajaxRequest.onreadystatechange = function () { - scope.onJSONLoaded(); - }; - - this.ajaxRequest.open("GET", this.url, true); - if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/json"); - this.ajaxRequest.send(null); -}; - -/** - * Invoke when JSON file is loaded - * - * @method onJSONLoaded - * @private - */ -PIXI.JsonLoader.prototype.onJSONLoaded = function () { - if (this.ajaxRequest.readyState == 4) { - if (this.ajaxRequest.status == 200 || window.location.href.indexOf("http") == -1) { - this.json = JSON.parse(this.ajaxRequest.responseText); - - if(this.json.frames) - { - // sprite sheet - var scope = this; - var textureUrl = this.baseUrl + this.json.meta.image; - var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); - var frameData = this.json.frames; - - this.texture = image.texture.baseTexture; - image.addEventListener("loaded", function (event) { - scope.onLoaded(); - }); - - for (var i in frameData) { - var rect = frameData[i].frame; - if (rect) { - PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) { - //var realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) - // calculate the offset! - } - } - } - - image.load(); - - } - else if(this.json.bones) - { - // spine animation - var spineJsonParser = new spine.SkeletonJson(); - var skeletonData = spineJsonParser.readSkeletonData(this.json); - PIXI.AnimCache[this.url] = skeletonData; - this.onLoaded(); - } - else - { - this.onLoaded(); - } - } - else - { - this.onError(); - } - } -}; - -/** - * Invoke when json file loaded - * - * @method onLoaded - * @private - */ -PIXI.JsonLoader.prototype.onLoaded = function () { - this.loaded = true; - this.dispatchEvent({ - type: "loaded", - content: this - }); -}; - -/** - * Invoke when error occured - * - * @method onError - * @private - */ -PIXI.JsonLoader.prototype.onError = function () { - this.dispatchEvent({ - type: "error", - content: this - }); -}; -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The sprite sheet loader is used to load in JSON sprite sheet data - * To generate the data you can use http://www.codeandweb.com/texturepacker and publish the "JSON" format - * There is a free version so thats nice, although the paid version is great value for money. - * It is highly recommended to use Sprite sheets (also know as texture atlas") as it means sprite"s can be batched and drawn together for highly increased rendering speed. - * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() - * This loader will also load the image file that the Spritesheet points to as well as the data. - * When loaded this class will dispatch a "loaded" event - * - * @class SpriteSheetLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the sprite sheet JSON file - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ - -PIXI.SpriteSheetLoader = function (url, crossorigin) { - /* - * i use texture packer to load the assets.. - * http://www.codeandweb.com/texturepacker - * make sure to set the format as "JSON" - */ - PIXI.EventTarget.call(this); - - /** - * The url of the bitmap font data - * - * @property url - * @type String - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * [read-only] The base url of the bitmap font data - * - * @property baseUrl - * @type String - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ""); - - /** - * The texture being loaded - * - * @property texture - * @type Texture - */ - this.texture = null; - - /** - * The frames of the sprite sheet - * - * @property frames - * @type Object - */ - this.frames = {}; -}; - -// constructor -PIXI.SpriteSheetLoader.prototype.constructor = PIXI.SpriteSheetLoader; - -/** - * This will begin loading the JSON file - * - * @method load - */ -PIXI.SpriteSheetLoader.prototype.load = function () { - var scope = this; - var jsonLoader = new PIXI.JsonLoader(this.url, this.crossorigin); - jsonLoader.addEventListener("loaded", function (event) { - scope.json = event.content.json; - scope.onJSONLoaded(); - }); - jsonLoader.load(); -}; - -/** - * Invoke when JSON file is loaded - * - * @method onJSONLoaded - * @private - */ -PIXI.SpriteSheetLoader.prototype.onJSONLoaded = function () { - var scope = this; - var textureUrl = this.baseUrl + this.json.meta.image; - var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); - var frameData = this.json.frames; - - this.texture = image.texture.baseTexture; - image.addEventListener("loaded", function (event) { - scope.onLoaded(); - }); - - for (var i in frameData) { - var rect = frameData[i].frame; - if (rect) { - PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) { - //var realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) - // calculate the offset! - } - } - } - - image.load(); -}; -/** - * Invoke when all files are loaded (json and texture) - * - * @method onLoaded - * @private - */ -PIXI.SpriteSheetLoader.prototype.onLoaded = function () { - this.dispatchEvent({ - type: "loaded", - content: this - }); -}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The image loader class is responsible for loading images file formats ("jpeg", "jpg", "png" and "gif") - * Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() - * When loaded this class will dispatch a 'loaded' event - * - * @class ImageLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the image - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.ImageLoader = function(url, crossorigin) -{ - PIXI.EventTarget.call(this); - - /** - * The texture being loaded - * - * @property texture - * @type Texture - */ - this.texture = PIXI.Texture.fromImage(url, crossorigin); - - /** - * if the image is loaded with loadFramedSpriteSheet - * frames will contain the sprite sheet frames - * - */ - this.frames = []; -}; - -// constructor -PIXI.ImageLoader.prototype.constructor = PIXI.ImageLoader; - -/** - * Loads image or takes it from cache - * - * @method load - */ -PIXI.ImageLoader.prototype.load = function() -{ - if(!this.texture.baseTexture.hasLoaded) - { - var scope = this; - this.texture.baseTexture.addEventListener("loaded", function() - { - scope.onLoaded(); - }); - } - else - { - this.onLoaded(); - } -}; - -/** - * Invoked when image file is loaded or it is already cached and ready to use - * - * @method onLoaded - * @private - */ -PIXI.ImageLoader.prototype.onLoaded = function() -{ - this.dispatchEvent({type: "loaded", content: this}); -}; - -/** - * Loads image and split it to uniform sized frames - * - * - * @method loadFramedSpriteSheet - * @param frameWidth {Number} with of each frame - * @param frameHeight {Number} height of each frame - * @param textureName {String} if given, the frames will be cached in - format - */ -PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) -{ - this.frames = []; - var cols = Math.floor(this.texture.width / frameWidth); - var rows = Math.floor(this.texture.height / frameHeight); - - var i=0; - for (var y=0; y= x1 && x <= x1 + this.width) + { + var y1 = this.y; + + if(y >= y1 && y <= y1 + this.height) + { + return true; + } + } + + return false; +} + +// constructor +PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; + + +/** + * @author Adrien Brault + */ + +/** + * @class Polygon + * @constructor + * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, + * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be + * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the + * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are + * Numbers. + */ +PIXI.Polygon = function(points) +{ + //if points isn't an array, use arguments as the array + if(!(points instanceof Array)) + points = Array.prototype.slice.call(arguments); + + //if this is a flat array of numbers, convert it to points + if(typeof points[0] === 'number') { + var p = []; + for(var i = 0, il = points.length; i < il; i+=2) { + p.push( + new PIXI.Point(points[i], points[i + 1]) + ); + } + + points = p; + } + + this.points = points; +} + +/** + * Creates a clone of this polygon + * + * @method clone + * @return {Polygon} a copy of the polygon + */ +PIXI.Polygon.prototype.clone = function() +{ + var points = []; + for (var i=0; i y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + + if(intersect) inside = !inside; + } + + return inside; +} + +// constructor +PIXI.Polygon.prototype.constructor = PIXI.Polygon; + +/** + * @author Chad Engler + */ + +/** + * The Circle object can be used to specify a hit area for displayobjects + * + * @class Circle + * @constructor + * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle + * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle + * @param radius {Number} The radius of the circle + */ +PIXI.Circle = function(x, y, radius) +{ + /** + * @property x + * @type Number + * @default 0 + */ + this.x = x || 0; + + /** + * @property y + * @type Number + * @default 0 + */ + this.y = y || 0; + + /** + * @property radius + * @type Number + * @default 0 + */ + this.radius = radius || 0; +} + +/** + * Creates a clone of this Circle instance + * + * @method clone + * @return {Circle} a copy of the polygon + */ +PIXI.Circle.prototype.clone = function() +{ + return new PIXI.Circle(this.x, this.y, this.radius); +} + +/** + * Checks if the x, and y coords passed to this function are contained within this circle + * + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return {Boolean} if the x/y coords are within this polygon + */ +PIXI.Circle.prototype.contains = function(x, y) +{ + if(this.radius <= 0) + return false; + + var dx = (this.x - x), + dy = (this.y - y), + r2 = this.radius * this.radius; + + dx *= dx; + dy *= dy; + + return (dx + dy <= r2); +} + +// constructor +PIXI.Circle.prototype.constructor = PIXI.Circle; + + +/** + * @author Chad Engler + */ + +/** + * The Ellipse object can be used to specify a hit area for displayobjects + * + * @class Ellipse + * @constructor + * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse + * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse + * @param width {Number} The overall width of this ellipse + * @param height {Number} The overall height of this ellipse + */ +PIXI.Ellipse = function(x, y, width, height) +{ + /** + * @property x + * @type Number + * @default 0 + */ + this.x = x || 0; + + /** + * @property y + * @type Number + * @default 0 + */ + this.y = y || 0; + + /** + * @property width + * @type Number + * @default 0 + */ + this.width = width || 0; + + /** + * @property height + * @type Number + * @default 0 + */ + this.height = height || 0; +} + +/** + * Creates a clone of this Ellipse instance + * + * @method clone + * @return {Ellipse} a copy of the ellipse + */ +PIXI.Ellipse.prototype.clone = function() +{ + return new PIXI.Ellipse(this.x, this.y, this.width, this.height); +} + +/** + * Checks if the x, and y coords passed to this function are contained within this ellipse + * + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return {Boolean} if the x/y coords are within this ellipse + */ +PIXI.Ellipse.prototype.contains = function(x, y) +{ + if(this.width <= 0 || this.height <= 0) + return false; + + //normalize the coords to an ellipse with center 0,0 + //and a radius of 0.5 + var normx = ((x - this.x) / this.width) - 0.5, + normy = ((y - this.y) / this.height) - 0.5; + + normx *= normx; + normy *= normy; + + return (normx + normy < 0.25); +} + +PIXI.Ellipse.getBounds = function() +{ + return new PIXI.Rectangle(this.x, this.y, this.width, this.height); +} + +// constructor +PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; + + + +/* + * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV + * you both rock! + */ + +function determineMatrixArrayType() { + PIXI.Matrix = (typeof Float32Array !== 'undefined') ? Float32Array : Array; + return PIXI.Matrix; +} + +determineMatrixArrayType(); + +PIXI.mat3 = {}; + +PIXI.mat3.create = function() +{ + var matrix = new PIXI.Matrix(9); + + matrix[0] = 1; + matrix[1] = 0; + matrix[2] = 0; + matrix[3] = 0; + matrix[4] = 1; + matrix[5] = 0; + matrix[6] = 0; + matrix[7] = 0; + matrix[8] = 1; + + return matrix; +} + + +PIXI.mat3.identity = function(matrix) +{ + matrix[0] = 1; + matrix[1] = 0; + matrix[2] = 0; + matrix[3] = 0; + matrix[4] = 1; + matrix[5] = 0; + matrix[6] = 0; + matrix[7] = 0; + matrix[8] = 1; + + return matrix; +} + + +PIXI.mat4 = {}; + +PIXI.mat4.create = function() +{ + var matrix = new PIXI.Matrix(16); + + matrix[0] = 1; + matrix[1] = 0; + matrix[2] = 0; + matrix[3] = 0; + matrix[4] = 0; + matrix[5] = 1; + matrix[6] = 0; + matrix[7] = 0; + matrix[8] = 0; + matrix[9] = 0; + matrix[10] = 1; + matrix[11] = 0; + matrix[12] = 0; + matrix[13] = 0; + matrix[14] = 0; + matrix[15] = 1; + + return matrix; +} + +PIXI.mat3.multiply = function (mat, mat2, dest) +{ + if (!dest) { dest = mat; } + + // Cache the matrix values (makes for huge speed increases!) + var a00 = mat[0], a01 = mat[1], a02 = mat[2], + a10 = mat[3], a11 = mat[4], a12 = mat[5], + a20 = mat[6], a21 = mat[7], a22 = mat[8], + + b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], + b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], + b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; + + dest[0] = b00 * a00 + b01 * a10 + b02 * a20; + dest[1] = b00 * a01 + b01 * a11 + b02 * a21; + dest[2] = b00 * a02 + b01 * a12 + b02 * a22; + + dest[3] = b10 * a00 + b11 * a10 + b12 * a20; + dest[4] = b10 * a01 + b11 * a11 + b12 * a21; + dest[5] = b10 * a02 + b11 * a12 + b12 * a22; + + dest[6] = b20 * a00 + b21 * a10 + b22 * a20; + dest[7] = b20 * a01 + b21 * a11 + b22 * a21; + dest[8] = b20 * a02 + b21 * a12 + b22 * a22; + + return dest; +} + +PIXI.mat3.clone = function(mat) +{ + var matrix = new PIXI.Matrix(9); + + matrix[0] = mat[0]; + matrix[1] = mat[1]; + matrix[2] = mat[2]; + matrix[3] = mat[3]; + matrix[4] = mat[4]; + matrix[5] = mat[5]; + matrix[6] = mat[6]; + matrix[7] = mat[7]; + matrix[8] = mat[8]; + + return matrix; +} + +PIXI.mat3.transpose = function (mat, dest) +{ + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (!dest || mat === dest) { + var a01 = mat[1], a02 = mat[2], + a12 = mat[5]; + + mat[1] = mat[3]; + mat[2] = mat[6]; + mat[3] = a01; + mat[5] = mat[7]; + mat[6] = a02; + mat[7] = a12; + return mat; + } + + dest[0] = mat[0]; + dest[1] = mat[3]; + dest[2] = mat[6]; + dest[3] = mat[1]; + dest[4] = mat[4]; + dest[5] = mat[7]; + dest[6] = mat[2]; + dest[7] = mat[5]; + dest[8] = mat[8]; + return dest; +} + +PIXI.mat3.toMat4 = function (mat, dest) +{ + if (!dest) { dest = PIXI.mat4.create(); } + + dest[15] = 1; + dest[14] = 0; + dest[13] = 0; + dest[12] = 0; + + dest[11] = 0; + dest[10] = mat[8]; + dest[9] = mat[7]; + dest[8] = mat[6]; + + dest[7] = 0; + dest[6] = mat[5]; + dest[5] = mat[4]; + dest[4] = mat[3]; + + dest[3] = 0; + dest[2] = mat[2]; + dest[1] = mat[1]; + dest[0] = mat[0]; + + return dest; +} + + +///// + + +PIXI.mat4.create = function() +{ + var matrix = new PIXI.Matrix(16); + + matrix[0] = 1; + matrix[1] = 0; + matrix[2] = 0; + matrix[3] = 0; + matrix[4] = 0; + matrix[5] = 1; + matrix[6] = 0; + matrix[7] = 0; + matrix[8] = 0; + matrix[9] = 0; + matrix[10] = 1; + matrix[11] = 0; + matrix[12] = 0; + matrix[13] = 0; + matrix[14] = 0; + matrix[15] = 1; + + return matrix; +} + +PIXI.mat4.transpose = function (mat, dest) +{ + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (!dest || mat === dest) + { + var a01 = mat[1], a02 = mat[2], a03 = mat[3], + a12 = mat[6], a13 = mat[7], + a23 = mat[11]; + + mat[1] = mat[4]; + mat[2] = mat[8]; + mat[3] = mat[12]; + mat[4] = a01; + mat[6] = mat[9]; + mat[7] = mat[13]; + mat[8] = a02; + mat[9] = a12; + mat[11] = mat[14]; + mat[12] = a03; + mat[13] = a13; + mat[14] = a23; + return mat; + } + + dest[0] = mat[0]; + dest[1] = mat[4]; + dest[2] = mat[8]; + dest[3] = mat[12]; + dest[4] = mat[1]; + dest[5] = mat[5]; + dest[6] = mat[9]; + dest[7] = mat[13]; + dest[8] = mat[2]; + dest[9] = mat[6]; + dest[10] = mat[10]; + dest[11] = mat[14]; + dest[12] = mat[3]; + dest[13] = mat[7]; + dest[14] = mat[11]; + dest[15] = mat[15]; + return dest; +} + +PIXI.mat4.multiply = function (mat, mat2, dest) +{ + if (!dest) { dest = mat; } + + // Cache the matrix values (makes for huge speed increases!) + var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; + var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; + var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; + var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; + + // Cache only the current line of the second matrix + var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; + dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + dest[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = mat2[4]; + b1 = mat2[5]; + b2 = mat2[6]; + b3 = mat2[7]; + dest[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + dest[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + dest[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + dest[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = mat2[8]; + b1 = mat2[9]; + b2 = mat2[10]; + b3 = mat2[11]; + dest[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + dest[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + dest[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + dest[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = mat2[12]; + b1 = mat2[13]; + b2 = mat2[14]; + b3 = mat2[15]; + dest[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + dest[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + dest[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + dest[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + return dest; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * The base class for all objects that are rendered on the screen. + * + * @class DisplayObject + * @constructor + */ +PIXI.DisplayObject = function() +{ + this.last = this; + this.first = this; + /** + * The coordinate of the object relative to the local coordinates of the parent. + * + * @property position + * @type Point + */ + this.position = new PIXI.Point(); + + /** + * The scale factor of the object. + * + * @property scale + * @type Point + */ + this.scale = new PIXI.Point(1,1);//{x:1, y:1}; + + /** + * The pivot point of the displayObject that it rotates around + * + * @property pivot + * @type Point + */ + this.pivot = new PIXI.Point(0,0); + + /** + * The rotation of the object in radians. + * + * @property rotation + * @type Number + */ + this.rotation = 0; + + /** + * The opacity of the object. + * + * @property alpha + * @type Number + */ + this.alpha = 1; + + /** + * The visibility of the object. + * + * @property visible + * @type Boolean + */ + this.visible = true; + + /** + * This is the defined area that will pick up mouse / touch events. It is null by default. + * Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children) + * + * @property hitArea + * @type Rectangle|Circle|Ellipse|Polygon + */ + this.hitArea = null; + + /** + * This is used to indicate if the displayObject should display a mouse hand cursor on rollover + * + * @property buttonMode + * @type Boolean + */ + this.buttonMode = false; + + /** + * Can this object be rendered + * + * @property renderable + * @type Boolean + */ + this.renderable = false; + + /** + * [read-only] The display object container that contains this display object. + * + * @property parent + * @type DisplayObjectContainer + * @readOnly + */ + this.parent = null; + + /** + * [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage. + * + * @property stage + * @type Stage + * @readOnly + */ + this.stage = null; + + /** + * [read-only] The multiplied alpha of the displayobject + * + * @property worldAlpha + * @type Number + * @readOnly + */ + this.worldAlpha = 1; + + /** + * [read-only] Whether or not the object is interactive, do not toggle directly! use the `interactive` property + * + * @property _interactive + * @type Boolean + * @readOnly + * @private + */ + this._interactive = false; + + /** + * [read-only] Current transform of the object based on world (parent) factors + * + * @property worldTransform + * @type Mat3 + * @readOnly + * @private + */ + this.worldTransform = PIXI.mat3.create()//mat3.identity(); + + /** + * [read-only] Current transform of the object locally + * + * @property localTransform + * @type Mat3 + * @readOnly + * @private + */ + this.localTransform = PIXI.mat3.create()//mat3.identity(); + + /** + * [NYI] Unkown + * + * @property color + * @type Array<> + * @private + */ + this.color = []; + + /** + * [NYI] Holds whether or not this object is dynamic, for rendering optimization + * + * @property dynamic + * @type Boolean + * @private + */ + this.dynamic = true; + + // chach that puppy! + this._sr = 0; + this._cr = 1; + + + this.filterArea = new PIXI.Rectangle(0,0,1,1); + + /* + * MOUSE Callbacks + */ + + /** + * A callback that is used when the users clicks on the displayObject with their mouse + * @method click + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user clicks the mouse down over the sprite + * @method mousedown + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases the mouse that was over the displayObject + * for this callback to be fired the mouse must have been pressed down over the displayObject + * @method mouseup + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject + * for this callback to be fired, The touch must have started over the displayObject + * @method mouseupoutside + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the users mouse rolls over the displayObject + * @method mouseover + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the users mouse leaves the displayObject + * @method mouseout + * @param interactionData {InteractionData} + */ + + + /* + * TOUCH Callbacks + */ + + /** + * A callback that is used when the users taps on the sprite with their finger + * basically a touch version of click + * @method tap + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user touch's over the displayObject + * @method touchstart + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases a touch over the displayObject + * @method touchend + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases the touch that was over the displayObject + * for this callback to be fired, The touch must have started over the sprite + * @method touchendoutside + * @param interactionData {InteractionData} + */ +} + +// constructor +PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; + +/** + * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default + * Instead of using this function you can now simply set the interactive property to true or false + * + * @method setInteractive + * @param interactive {Boolean} + * @deprecated Simply set the `interactive` property directly + */ +PIXI.DisplayObject.prototype.setInteractive = function(interactive) +{ + this.interactive = interactive; +} + +/** + * Indicates if the sprite will have touch and mouse interactivity. It is false by default + * + * @property interactive + * @type Boolean + * @default false + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'interactive', { + get: function() { + return this._interactive; + }, + set: function(value) { + this._interactive = value; + + // TODO more to be done here.. + // need to sort out a re-crawl! + if(this.stage)this.stage.dirty = true; + } +}); + +/** + * Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. + * In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. + * To remove a mask, set this property to null. + * + * @property mask + * @type Graphics + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { + get: function() { + return this._mask; + }, + set: function(value) { + + + if(value) + { + if(this._mask) + { + value.start = this._mask.start; + value.end = this._mask.end; + } + else + { + this.addFilter(value); + value.renderable = false; + } + } + else + { + this.removeFilter(this._mask); + this._mask.renderable = true; + } + + this._mask = value; + } +}); + +/** + * Sets the filters for the displayObject. + * * IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer. + * To remove filters simply set this property to 'null' + * @property filters + * @type Array An array of filters + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { + get: function() { + return this._filters; + }, + set: function(value) { + + if(value) + { + if(this._filters)this.removeFilter(this._filters); + this.addFilter(value); + + // now put all the passes in one place.. + var passes = []; + for (var i = 0; i < value.length; i++) + { + var filterPasses = value[i].passes; + for (var j = 0; j < filterPasses.length; j++) + { + passes.push(filterPasses[j]); + }; + }; + + value.start.filterPasses = passes; + } + else + { + if(this._filters)this.removeFilter(this._filters); + } + + this._filters = value; + + + + + } +}); + +/* + * Adds a filter to this displayObject + * + * @method addFilter + * @param mask {Graphics} the graphics object to use as a filter + * @private + */ +PIXI.DisplayObject.prototype.addFilter = function(data) +{ + //if(this.filter)return; + //this.filter = true; +// data[0].target = this; + + + // insert a filter block.. + // TODO Onject pool thease bad boys.. + var start = new PIXI.FilterBlock(); + var end = new PIXI.FilterBlock(); + + data.start = start; + data.end = end; + + start.data = data; + end.data = data; + + start.first = start.last = this; + end.first = end.last = this; + + start.open = true; + + start.target = this; + + /* + * insert start + */ + + var childFirst = start + var childLast = start + var nextObject; + var previousObject; + + previousObject = this.first._iPrev; + + if(previousObject) + { + nextObject = previousObject._iNext; + childFirst._iPrev = previousObject; + previousObject._iNext = childFirst; + } + else + { + nextObject = this; + } + + if(nextObject) + { + nextObject._iPrev = childLast; + childLast._iNext = nextObject; + } + + + // now insert the end filter block.. + + /* + * insert end filter + */ + var childFirst = end + var childLast = end + var nextObject = null; + var previousObject = null; + + previousObject = this.last; + nextObject = previousObject._iNext; + + if(nextObject) + { + nextObject._iPrev = childLast; + childLast._iNext = nextObject; + } + + childFirst._iPrev = previousObject; + previousObject._iNext = childFirst; + + var updateLast = this; + + var prevLast = this.last; + while(updateLast) + { + if(updateLast.last == prevLast) + { + updateLast.last = end; + } + updateLast = updateLast.parent; + } + + this.first = start; + + // if webGL... + if(this.__renderGroup) + { + this.__renderGroup.addFilterBlocks(start, end); + } + +} + +/* + * Removes the filter to this displayObject + * + * @method removeFilter + * @private + */ +PIXI.DisplayObject.prototype.removeFilter = function(data) +{ + //if(!this.filter)return; + //this.filter = false; + // console.log("YUOIO") + // modify the list.. + var startBlock = data.start; + + + var nextObject = startBlock._iNext; + var previousObject = startBlock._iPrev; + + if(nextObject)nextObject._iPrev = previousObject; + if(previousObject)previousObject._iNext = nextObject; + + this.first = startBlock._iNext; + + // remove the end filter + var lastBlock = data.end; + + var nextObject = lastBlock._iNext; + var previousObject = lastBlock._iPrev; + + if(nextObject)nextObject._iPrev = previousObject; + previousObject._iNext = nextObject; + + // this is always true too! + var tempLast = lastBlock._iPrev; + // need to make sure the parents last is updated too + var updateLast = this; + while(updateLast.last == lastBlock) + { + updateLast.last = tempLast; + updateLast = updateLast.parent; + if(!updateLast)break; + } + + // if webGL... + if(this.__renderGroup) + { + this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); + } +} + +/* + * Updates the object transform for rendering + * + * @method updateTransform + * @private + */ +PIXI.DisplayObject.prototype.updateTransform = function() +{ + // TODO OPTIMIZE THIS!! with dirty + if(this.rotation !== this.rotationCache) + { + this.rotationCache = this.rotation; + this._sr = Math.sin(this.rotation); + this._cr = Math.cos(this.rotation); + } + + var localTransform = this.localTransform; + var parentTransform = this.parent.worldTransform; + var worldTransform = this.worldTransform; + //console.log(localTransform) + localTransform[0] = this._cr * this.scale.x; + localTransform[1] = -this._sr * this.scale.y + localTransform[3] = this._sr * this.scale.x; + localTransform[4] = this._cr * this.scale.y; + + // TODO --> do we even need a local matrix??? + + var px = this.pivot.x; + var py = this.pivot.y; + + // Cache the matrix values (makes for huge speed increases!) + var a00 = localTransform[0], a01 = localTransform[1], a02 = this.position.x - localTransform[0] * px - py * localTransform[1], + a10 = localTransform[3], a11 = localTransform[4], a12 = this.position.y - localTransform[4] * py - px * localTransform[3], + + b00 = parentTransform[0], b01 = parentTransform[1], b02 = parentTransform[2], + b10 = parentTransform[3], b11 = parentTransform[4], b12 = parentTransform[5]; + + localTransform[2] = a02 + localTransform[5] = a12 + + worldTransform[0] = b00 * a00 + b01 * a10; + worldTransform[1] = b00 * a01 + b01 * a11; + worldTransform[2] = b00 * a02 + b01 * a12 + b02; + + worldTransform[3] = b10 * a00 + b11 * a10; + worldTransform[4] = b10 * a01 + b11 * a11; + worldTransform[5] = b10 * a02 + b11 * a12 + b12; + + // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! + // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); + this.worldAlpha = this.alpha * this.parent.worldAlpha; + + this.vcount = PIXI.visibleCount; + +} + +PIXI.visibleCount = 0; +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * A DisplayObjectContainer represents a collection of display objects. + * It is the base class of all display objects that act as a container for other objects. + * + * @class DisplayObjectContainer + * @extends DisplayObject + * @constructor + */ +PIXI.DisplayObjectContainer = function() +{ + PIXI.DisplayObject.call( this ); + + /** + * [read-only] The of children of this container. + * + * @property children + * @type Array + * @readOnly + */ + this.children = []; +} + +// constructor +PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); +PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; + +/** + * Adds a child to the container. + * + * @method addChild + * @param child {DisplayObject} The DisplayObject to add to the container + */ +PIXI.DisplayObjectContainer.prototype.addChild = function(child) +{ + if(child.parent != undefined) + { + + //// COULD BE THIS??? + child.parent.removeChild(child); + // return; + } + + child.parent = this; + + this.children.push(child); + + // update the stage refference.. + + if(this.stage) + { + var tmpChild = child; + do + { + if(tmpChild.interactive)this.stage.dirty = true; + tmpChild.stage = this.stage; + tmpChild = tmpChild._iNext; + } + while(tmpChild) + } + + // LINKED LIST // + + // modify the list.. + var childFirst = child.first + var childLast = child.last; + var nextObject; + var previousObject; + + // this could be wrong if there is a filter?? + if(this._filters || this._mask) + { + previousObject = this.last._iPrev; + } + else + { + previousObject = this.last; + } + + nextObject = previousObject._iNext; + + // always true in this case + // need to make sure the parents last is updated too + var updateLast = this; + var prevLast = previousObject; + + while(updateLast) + { + if(updateLast.last == prevLast) + { + updateLast.last = child.last; + } + updateLast = updateLast.parent; + } + + if(nextObject) + { + nextObject._iPrev = childLast; + childLast._iNext = nextObject; + } + + childFirst._iPrev = previousObject; + previousObject._iNext = childFirst; + + // need to remove any render groups.. + if(this.__renderGroup) + { + // being used by a renderTexture.. if it exists then it must be from a render texture; + if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); + // add them to the new render group.. + this.__renderGroup.addDisplayObjectAndChildren(child); + } + +} + +/** + * Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown + * + * @method addChildAt + * @param child {DisplayObject} The child to add + * @param index {Number} The index to place the child in + */ +PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) +{ + if(index >= 0 && index <= this.children.length) + { + if(child.parent != undefined) + { + child.parent.removeChild(child); + } + child.parent = this; + + if(this.stage) + { + var tmpChild = child; + do + { + if(tmpChild.interactive)this.stage.dirty = true; + tmpChild.stage = this.stage; + tmpChild = tmpChild._iNext; + } + while(tmpChild) + } + + // modify the list.. + var childFirst = child.first; + var childLast = child.last; + var nextObject; + var previousObject; + + if(index == this.children.length) + { + previousObject = this.last; + var updateLast = this; + var prevLast = this.last; + while(updateLast) + { + if(updateLast.last == prevLast) + { + updateLast.last = child.last; + } + updateLast = updateLast.parent; + } + } + else if(index == 0) + { + previousObject = this; + } + else + { + previousObject = this.children[index-1].last; + } + + nextObject = previousObject._iNext; + + // always true in this case + if(nextObject) + { + nextObject._iPrev = childLast; + childLast._iNext = nextObject; + } + + childFirst._iPrev = previousObject; + previousObject._iNext = childFirst; + + this.children.splice(index, 0, child); + // need to remove any render groups.. + if(this.__renderGroup) + { + // being used by a renderTexture.. if it exists then it must be from a render texture; + if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); + // add them to the new render group.. + this.__renderGroup.addDisplayObjectAndChildren(child); + } + + } + else + { + throw new Error(child + " The index "+ index +" supplied is out of bounds " + this.children.length); + } +} + +/** + * [NYI] Swaps the depth of 2 displayObjects + * + * @method swapChildren + * @param child {DisplayObject} + * @param child2 {DisplayObject} + * @private + */ +PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2) +{ + /* + * this funtion needs to be recoded.. + * can be done a lot faster.. + */ + return; + + // need to fix this function :/ + /* + // TODO I already know this?? + var index = this.children.indexOf( child ); + var index2 = this.children.indexOf( child2 ); + + if ( index !== -1 && index2 !== -1 ) + { + // cool + + /* + if(this.stage) + { + // this is to satisfy the webGL batching.. + // TODO sure there is a nicer way to achieve this! + this.stage.__removeChild(child); + this.stage.__removeChild(child2); + + this.stage.__addChild(child); + this.stage.__addChild(child2); + } + + // swap the positions.. + this.children[index] = child2; + this.children[index2] = child; + + } + else + { + throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); + }*/ +} + +/** + * Returns the Child at the specified index + * + * @method getChildAt + * @param index {Number} The index to get the child from + */ +PIXI.DisplayObjectContainer.prototype.getChildAt = function(index) +{ + if(index >= 0 && index < this.children.length) + { + return this.children[index]; + } + else + { + throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); + } +} + +/** + * Removes a child from the container. + * + * @method removeChild + * @param child {DisplayObject} The DisplayObject to remove + */ +PIXI.DisplayObjectContainer.prototype.removeChild = function(child) +{ + var index = this.children.indexOf( child ); + if ( index !== -1 ) + { + // unlink // + // modify the list.. + var childFirst = child.first; + var childLast = child.last; + + var nextObject = childLast._iNext; + var previousObject = childFirst._iPrev; + + if(nextObject)nextObject._iPrev = previousObject; + previousObject._iNext = nextObject; + + if(this.last == childLast) + { + var tempLast = childFirst._iPrev; + // need to make sure the parents last is updated too + var updateLast = this; + while(updateLast.last == childLast.last) + { + updateLast.last = tempLast; + updateLast = updateLast.parent; + if(!updateLast)break; + } + } + + childLast._iNext = null; + childFirst._iPrev = null; + + // update the stage reference.. + if(this.stage) + { + var tmpChild = child; + do + { + if(tmpChild.interactive)this.stage.dirty = true; + tmpChild.stage = null; + tmpChild = tmpChild._iNext; + } + while(tmpChild) + } + + // webGL trim + if(child.__renderGroup) + { + child.__renderGroup.removeDisplayObjectAndChildren(child); + } + + child.parent = undefined; + this.children.splice( index, 1 ); + } + else + { + throw new Error(child + " The supplied DisplayObject must be a child of the caller " + this); + } +} + +/* + * Updates the container's children's transform for rendering + * + * @method updateTransform + * @private + */ +PIXI.DisplayObjectContainer.prototype.updateTransform = function() +{ + if(!this.visible)return; + + PIXI.DisplayObject.prototype.updateTransform.call( this ); + + for(var i=0,j=this.children.length; i} an array of {Texture} objects that make up the animation + */ +PIXI.MovieClip = function(textures) +{ + PIXI.Sprite.call(this, textures[0]); + + /** + * The array of textures that make up the animation + * + * @property textures + * @type Array + */ + this.textures = textures; + + /** + * The speed that the MovieClip will play at. Higher is faster, lower is slower + * + * @property animationSpeed + * @type Number + * @default 1 + */ + this.animationSpeed = 1; + + /** + * Whether or not the movie clip repeats after playing. + * + * @property loop + * @type Boolean + * @default true + */ + this.loop = true; + + /** + * Function to call when a MovieClip finishes playing + * + * @property onComplete + * @type Function + */ + this.onComplete = null; + + /** + * [read-only] The index MovieClips current frame (this may not have to be a whole number) + * + * @property currentFrame + * @type Number + * @default 0 + * @readOnly + */ + this.currentFrame = 0; + + /** + * [read-only] Indicates if the MovieClip is currently playing + * + * @property playing + * @type Boolean + * @readOnly + */ + this.playing = false; +} + +// constructor +PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); +PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; + +/** +* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures +* assigned to the MovieClip. +* +* @property totalFrames +* @type Number +* @default 0 +* @readOnly +*/ +Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { + get: function() { + + return this.textures.length; + } +}); + + +/** + * Stops the MovieClip + * + * @method stop + */ +PIXI.MovieClip.prototype.stop = function() +{ + this.playing = false; +} + +/** + * Plays the MovieClip + * + * @method play + */ +PIXI.MovieClip.prototype.play = function() +{ + this.playing = true; +} + +/** + * Stops the MovieClip and goes to a specific frame + * + * @method gotoAndStop + * @param frameNumber {Number} frame index to stop at + */ +PIXI.MovieClip.prototype.gotoAndStop = function(frameNumber) +{ + this.playing = false; + this.currentFrame = frameNumber; + var round = (this.currentFrame + 0.5) | 0; + this.setTexture(this.textures[round % this.textures.length]); +} + +/** + * Goes to a specific frame and begins playing the MovieClip + * + * @method gotoAndPlay + * @param frameNumber {Number} frame index to start at + */ +PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) +{ + this.currentFrame = frameNumber; + this.playing = true; +} + +/* + * Updates the object transform for rendering + * + * @method updateTransform + * @private + */ +PIXI.MovieClip.prototype.updateTransform = function() +{ + PIXI.Sprite.prototype.updateTransform.call(this); + + if(!this.playing)return; + + this.currentFrame += this.animationSpeed; + + var round = (this.currentFrame + 0.5) | 0; + + if(this.loop || round < this.textures.length) + { + this.setTexture(this.textures[round % this.textures.length]); + } + else if(round >= this.textures.length) + { + this.gotoAndStop(this.textures.length - 1); + if(this.onComplete) + { + this.onComplete(); + } + } +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + + +PIXI.FilterBlock = function() +{ + this.visible = true; + this.renderable = true; +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * A Text Object will create a line(s) of text to split a line you can use "\n" + * + * @class Text + * @extends Sprite + * @constructor + * @param text {String} The copy that you would like the text to display + * @param [style] {Object} The style parameters + * @param [style.font] {String} default "bold 20pt Arial" The style and size of the font + * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") + * @param [style.stroke] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" + * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) + * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used + * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap + */ +PIXI.Text = function(text, style) +{ + this.canvas = document.createElement("canvas"); + this.context = this.canvas.getContext("2d"); + PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas)); + + this.setText(text); + this.setStyle(style); + + this.updateText(); + this.dirty = false; +}; + +// constructor +PIXI.Text.prototype = Object.create(PIXI.Sprite.prototype); +PIXI.Text.prototype.constructor = PIXI.Text; + +/** + * Set the style of the text + * + * @method setStyle + * @param [style] {Object} The style parameters + * @param [style.font="bold 20pt Arial"] {String} The style and size of the font + * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") + * @param [style.stroke="black"] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" + * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) + * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used + * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap + */ +PIXI.Text.prototype.setStyle = function(style) +{ + style = style || {}; + style.font = style.font || "bold 20pt Arial"; + style.fill = style.fill || "black"; + style.align = style.align || "left"; + style.stroke = style.stroke || "black"; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136 + style.strokeThickness = style.strokeThickness || 0; + style.wordWrap = style.wordWrap || false; + style.wordWrapWidth = style.wordWrapWidth || 100; + this.style = style; + this.dirty = true; +}; + +/** + * Set the copy for the text object. To split a line you can use "\n" + * + * @methos setText + * @param {String} text The copy that you would like the text to display + */ +PIXI.Text.prototype.setText = function(text) +{ + this.text = text.toString() || " "; + this.dirty = true; +}; + +/** + * Renders text + * + * @method updateText + * @private + */ +PIXI.Text.prototype.updateText = function() +{ + this.context.font = this.style.font; + + var outputText = this.text; + + // word wrap + // preserve original text + if(this.style.wordWrap)outputText = this.wordWrap(this.text); + + //split text into lines + var lines = outputText.split(/(?:\r\n|\r|\n)/); + + //calculate text width + var lineWidths = []; + var maxLineWidth = 0; + for (var i = 0; i < lines.length; i++) + { + var lineWidth = this.context.measureText(lines[i]).width; + lineWidths[i] = lineWidth; + maxLineWidth = Math.max(maxLineWidth, lineWidth); + } + this.canvas.width = maxLineWidth + this.style.strokeThickness; + + //calculate text height + var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; + this.canvas.height = lineHeight * lines.length; + + //set canvas text styles + this.context.fillStyle = this.style.fill; + this.context.font = this.style.font; + + this.context.strokeStyle = this.style.stroke; + this.context.lineWidth = this.style.strokeThickness; + + this.context.textBaseline = "top"; + + //draw lines line by line + for (i = 0; i < lines.length; i++) + { + var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); + + if(this.style.align == "right") + { + linePosition.x += maxLineWidth - lineWidths[i]; + } + else if(this.style.align == "center") + { + linePosition.x += (maxLineWidth - lineWidths[i]) / 2; + } + + if(this.style.stroke && this.style.strokeThickness) + { + this.context.strokeText(lines[i], linePosition.x, linePosition.y); + } + + if(this.style.fill) + { + this.context.fillText(lines[i], linePosition.x, linePosition.y); + } + } + + this.updateTexture(); +}; + +/** + * Updates texture size based on canvas size + * + * @method updateTexture + * @private + */ +PIXI.Text.prototype.updateTexture = function() +{ + this.texture.baseTexture.width = this.canvas.width; + this.texture.baseTexture.height = this.canvas.height; + this.texture.frame.width = this.canvas.width; + this.texture.frame.height = this.canvas.height; + + this._width = this.canvas.width; + this._height = this.canvas.height; + + PIXI.texturesToUpdate.push(this.texture.baseTexture); +}; + +/** + * Updates the transfor of this object + * + * @method updateTransform + * @private + */ +PIXI.Text.prototype.updateTransform = function() +{ + if(this.dirty) + { + this.updateText(); + this.dirty = false; + } + + PIXI.Sprite.prototype.updateTransform.call(this); +}; + +/* + * http://stackoverflow.com/users/34441/ellisbben + * great solution to the problem! + * + * @method determineFontHeight + * @param fontStyle {Object} + * @private + */ +PIXI.Text.prototype.determineFontHeight = function(fontStyle) +{ + // build a little reference dictionary so if the font style has been used return a + // cached version... + var result = PIXI.Text.heightCache[fontStyle]; + + if(!result) + { + var body = document.getElementsByTagName("body")[0]; + var dummy = document.createElement("div"); + var dummyText = document.createTextNode("M"); + dummy.appendChild(dummyText); + dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); + body.appendChild(dummy); + + result = dummy.offsetHeight; + PIXI.Text.heightCache[fontStyle] = result; + + body.removeChild(dummy); + } + + return result; +}; + +/** + * Applies newlines to a string to have it optimally fit into the horizontal + * bounds set by the Text object's wordWrapWidth property. + * + * @method wordWrap + * @param text {String} + * @private + */ +PIXI.Text.prototype.wordWrap = function(text) +{ + // Greedy wrapping algorithm that will wrap words as the line grows longer + // than its horizontal bounds. + var result = ""; + var lines = text.split("\n"); + for (var i = 0; i < lines.length; i++) + { + var spaceLeft = this.style.wordWrapWidth; + var words = lines[i].split(" "); + for (var j = 0; j < words.length; j++) + { + var wordWidth = this.context.measureText(words[j]).width; + var wordWidthWithSpace = wordWidth + this.context.measureText(" ").width; + if(wordWidthWithSpace > spaceLeft) + { + // Skip printing the newline if it's the first word of the line that is + // greater than the word wrap width. + if(j > 0) + { + result += "\n"; + } + result += words[j] + " "; + spaceLeft = this.style.wordWrapWidth - wordWidth; + } + else + { + spaceLeft -= wordWidthWithSpace; + result += words[j] + " "; + } + } + result += "\n"; + } + return result; +}; + +/** + * Destroys this text object + * + * @method destroy + * @param destroyTexture {Boolean} + */ +PIXI.Text.prototype.destroy = function(destroyTexture) +{ + if(destroyTexture) + { + this.texture.destroy(); + } + +}; + +PIXI.Text.heightCache = {}; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" + * You can generate the fnt files using + * http://www.angelcode.com/products/bmfont/ for windows or + * http://www.bmglyph.com/ for mac. + * + * @class BitmapText + * @extends DisplayObjectContainer + * @constructor + * @param text {String} The copy that you would like the text to display + * @param style {Object} The style parameters + * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") + */ +PIXI.BitmapText = function(text, style) +{ + PIXI.DisplayObjectContainer.call(this); + + this.setText(text); + this.setStyle(style); + this.updateText(); + this.dirty = false + +}; + +// constructor +PIXI.BitmapText.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); +PIXI.BitmapText.prototype.constructor = PIXI.BitmapText; + +/** + * Set the copy for the text object + * + * @method setText + * @param text {String} The copy that you would like the text to display + */ +PIXI.BitmapText.prototype.setText = function(text) +{ + this.text = text || " "; + this.dirty = true; +}; + +/** + * Set the style of the text + * + * @method setStyle + * @param style {Object} The style parameters + * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") + */ +PIXI.BitmapText.prototype.setStyle = function(style) +{ + style = style || {}; + style.align = style.align || "left"; + this.style = style; + + var font = style.font.split(" "); + this.fontName = font[font.length - 1]; + this.fontSize = font.length >= 2 ? parseInt(font[font.length - 2], 10) : PIXI.BitmapText.fonts[this.fontName].size; + + this.dirty = true; +}; + +/** + * Renders text + * + * @method updateText + * @private + */ +PIXI.BitmapText.prototype.updateText = function() +{ + var data = PIXI.BitmapText.fonts[this.fontName]; + var pos = new PIXI.Point(); + var prevCharCode = null; + var chars = []; + var maxLineWidth = 0; + var lineWidths = []; + var line = 0; + var scale = this.fontSize / data.size; + for(var i = 0; i < this.text.length; i++) + { + var charCode = this.text.charCodeAt(i); + if(/(?:\r\n|\r|\n)/.test(this.text.charAt(i))) + { + lineWidths.push(pos.x); + maxLineWidth = Math.max(maxLineWidth, pos.x); + line++; + + pos.x = 0; + pos.y += data.lineHeight; + prevCharCode = null; + continue; + } + + var charData = data.chars[charCode]; + if(!charData) continue; + + if(prevCharCode && charData[prevCharCode]) + { + pos.x += charData.kerning[prevCharCode]; + } + chars.push({texture:charData.texture, line: line, charCode: charCode, position: new PIXI.Point(pos.x + charData.xOffset, pos.y + charData.yOffset)}); + pos.x += charData.xAdvance; + + prevCharCode = charCode; + } + + lineWidths.push(pos.x); + maxLineWidth = Math.max(maxLineWidth, pos.x); + + var lineAlignOffsets = []; + for(i = 0; i <= line; i++) + { + var alignOffset = 0; + if(this.style.align == "right") + { + alignOffset = maxLineWidth - lineWidths[i]; + } + else if(this.style.align == "center") + { + alignOffset = (maxLineWidth - lineWidths[i]) / 2; + } + lineAlignOffsets.push(alignOffset); + } + + for(i = 0; i < chars.length; i++) + { + var c = new PIXI.Sprite(chars[i].texture)//PIXI.Sprite.fromFrame(chars[i].charCode); + c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale; + c.position.y = chars[i].position.y * scale; + c.scale.x = c.scale.y = scale; + this.addChild(c); + } + + this.width = pos.x * scale; + this.height = (pos.y + data.lineHeight) * scale; +}; + +/** + * Updates the transfor of this object + * + * @method updateTransform + * @private + */ +PIXI.BitmapText.prototype.updateTransform = function() +{ + if(this.dirty) + { + while(this.children.length > 0) + { + this.removeChild(this.getChildAt(0)); + } + this.updateText(); + + this.dirty = false; + } + + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); +}; + +PIXI.BitmapText.fonts = {}; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + /** + * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive + * This manager also supports multitouch. + * + * @class InteractionManager + * @constructor + * @param stage {Stage} The stage to handle interactions + */ +PIXI.InteractionManager = function(stage) +{ + /** + * a refference to the stage + * + * @property stage + * @type Stage + */ + this.stage = stage; + + /** + * the mouse data + * + * @property mouse + * @type InteractionData + */ + this.mouse = new PIXI.InteractionData(); + + /** + * an object that stores current touches (InteractionData) by id reference + * + * @property touchs + * @type Object + */ + this.touchs = {}; + + + + // helpers + this.tempPoint = new PIXI.Point(); + //this.tempMatrix = mat3.create(); + + this.mouseoverEnabled = true; + + //tiny little interactiveData pool! + this.pool = []; + + this.interactiveItems = []; + this.interactionDOMElement = null; + + //this will make it so that you dont have to call bind all the time + this.onMouseMove = this.onMouseMove.bind( this ); + this.onMouseDown = this.onMouseDown.bind(this); + this.onMouseOut = this.onMouseOut.bind(this); + this.onMouseUp = this.onMouseUp.bind(this); + + this.onTouchStart = this.onTouchStart.bind(this); + this.onTouchEnd = this.onTouchEnd.bind(this); + this.onTouchMove = this.onTouchMove.bind(this); + + + this.last = 0; +} + +// constructor +PIXI.InteractionManager.prototype.constructor = PIXI.InteractionManager; + +/** + * Collects an interactive sprite recursively to have their interactions managed + * + * @method collectInteractiveSprite + * @param displayObject {DisplayObject} the displayObject to collect + * @param iParent {DisplayObject} + * @private + */ +PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObject, iParent) +{ + var children = displayObject.children; + var length = children.length; + + /// make an interaction tree... {item.__interactiveParent} + for (var i = length-1; i >= 0; i--) + { + var child = children[i]; + +// if(child.visible) { + // push all interactive bits + if(child.interactive) + { + iParent.interactiveChildren = true; + //child.__iParent = iParent; + this.interactiveItems.push(child); + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, child); + } + } + else + { + child.__iParent = null; + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, iParent); + } + } +// } + } +} + +/** + * Sets the target for event delegation + * + * @method setTarget + * @param target {WebGLRenderer|CanvasRenderer} the renderer to bind events to + * @private + */ +PIXI.InteractionManager.prototype.setTarget = function(target) +{ + this.target = target; + + //check if the dom element has been set. If it has don't do anything + if( this.interactionDOMElement === null ) { + + this.setTargetDomElement( target.view ); + } + + document.body.addEventListener('mouseup', this.onMouseUp, true); +} + + +/** + * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM + * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element + * to receive those events + * + * @method setTargetDomElement + * @param domElement {DOMElement} the dom element which will receive mouse and touch events + * @private + */ +PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) +{ + //remove previouse listeners + if( this.interactionDOMElement !== null ) + { + this.interactionDOMElement.style['-ms-content-zooming'] = ''; + this.interactionDOMElement.style['-ms-touch-action'] = ''; + + this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); + this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); + this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); + this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); + this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); + } + + + if (window.navigator.msPointerEnabled) + { + // time to remove some of that zoom in ja.. + domElement.style['-ms-content-zooming'] = 'none'; + domElement.style['-ms-touch-action'] = 'none'; + + // DO some window specific touch! + } + + this.interactionDOMElement = domElement; + + domElement.addEventListener('mousemove', this.onMouseMove, true); + domElement.addEventListener('mousedown', this.onMouseDown, true); + domElement.addEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + domElement.addEventListener('touchstart', this.onTouchStart, true); + domElement.addEventListener('touchend', this.onTouchEnd, true); + domElement.addEventListener('touchmove', this.onTouchMove, true); +} + + +/** + * updates the state of interactive objects + * + * @method update + * @private + */ +PIXI.InteractionManager.prototype.update = function() +{ + if(!this.target)return; + + // frequency of 30fps?? + var now = Date.now(); + var diff = now - this.last; + diff = (diff * 30) / 1000; + if(diff < 1)return; + this.last = now; + // + + // ok.. so mouse events?? + // yes for now :) + // OPTIMSE - how often to check?? + if(this.dirty) + { + this.dirty = false; + + var len = this.interactiveItems.length; + + for (var i=0; i < len; i++) { + this.interactiveItems[i].interactiveChildren = false; + } + + this.interactiveItems = []; + + if(this.stage.interactive)this.interactiveItems.push(this.stage); + // go through and collect all the objects that are interactive.. + this.collectInteractiveSprite(this.stage, this.stage); + } + + // loop through interactive objects! + var length = this.interactiveItems.length; + + this.interactionDOMElement.style.cursor = "default"; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + + //if(!item.visible)continue; + + // OPTIMISATION - only calculate every time if the mousemove function exists.. + // OK so.. does the object have any other interactive functions? + // hit-test the clip! + + + if(item.mouseover || item.mouseout || item.buttonMode) + { + // ok so there are some functions so lets hit test it.. + item.__hit = this.hitTest(item, this.mouse); + this.mouse.target = item; + // ok so deal with interactions.. + // loks like there was a hit! + if(item.__hit) + { + if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; + + if(!item.__isOver) + { + + if(item.mouseover)item.mouseover(this.mouse); + item.__isOver = true; + } + } + else + { + if(item.__isOver) + { + // roll out! + if(item.mouseout)item.mouseout(this.mouse); + item.__isOver = false; + } + } + } + + // ---> + } +} + +/** + * Is called when the mouse moves accross the renderer element + * + * @method onMouseMove + * @param event {Event} The DOM event of the mouse moving + * @private + */ +PIXI.InteractionManager.prototype.onMouseMove = function(event) +{ + this.mouse.originalEvent = event || window.event; //IE uses window.event + // TODO optimize by not check EVERY TIME! maybe half as often? // + var rect = this.interactionDOMElement.getBoundingClientRect(); + + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + + var length = this.interactiveItems.length; + var global = this.mouse.global; + + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.mousemove) + { + //call the function! + item.mousemove(this.mouse); + } + } +} + +/** + * Is called when the mouse button is pressed down on the renderer element + * + * @method onMouseDown + * @param event {Event} The DOM event of a mouse button being pressed down + * @private + */ +PIXI.InteractionManager.prototype.onMouseDown = function(event) +{ + this.mouse.originalEvent = event || window.event; //IE uses window.event + + // loop through inteaction tree... + // hit test each item! -> + // get interactive items under point?? + //stage.__i + var length = this.interactiveItems.length; + var global = this.mouse.global; + + var index = 0; + var parent = this.stage; + + // while + // hit test + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.mousedown || item.click) + { + item.__mouseIsDown = true; + item.__hit = this.hitTest(item, this.mouse); + + if(item.__hit) + { + //call the function! + if(item.mousedown)item.mousedown(this.mouse); + item.__isDown = true; + + // just the one! + if(!item.interactiveChildren)break; + } + } + } +} + + +PIXI.InteractionManager.prototype.onMouseOut = function(event) +{ + var length = this.interactiveItems.length; + + this.interactionDOMElement.style.cursor = "default"; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.__isOver) + { + this.mouse.target = item; + if(item.mouseout)item.mouseout(this.mouse); + item.__isOver = false; + } + } +} + +/** + * Is called when the mouse button is released on the renderer element + * + * @method onMouseUp + * @param event {Event} The DOM event of a mouse button being released + * @private + */ +PIXI.InteractionManager.prototype.onMouseUp = function(event) +{ + this.mouse.originalEvent = event || window.event; //IE uses window.event + + var global = this.mouse.global; + + + var length = this.interactiveItems.length; + var up = false; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.mouseup || item.mouseupoutside || item.click) + { + item.__hit = this.hitTest(item, this.mouse); + + if(item.__hit && !up) + { + //call the function! + if(item.mouseup) + { + item.mouseup(this.mouse); + } + if(item.__isDown) + { + if(item.click)item.click(this.mouse); + } + + if(!item.interactiveChildren)up = true; + } + else + { + if(item.__isDown) + { + if(item.mouseupoutside)item.mouseupoutside(this.mouse); + } + } + + item.__isDown = false; + } + } +} + +/** + * Tests if the current mouse coords hit a sprite + * + * @method hitTest + * @param item {DisplayObject} The displayObject to test for a hit + * @param interactionData {InteractionData} The interactiondata object to update in the case of a hit + * @private + */ +PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) +{ + var global = interactionData.global; + + if(item.vcount !== PIXI.visibleCount)return false; + + var isSprite = (item instanceof PIXI.Sprite), + worldTransform = item.worldTransform, + a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], + a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], + id = 1 / (a00 * a11 + a01 * -a10), + x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, + y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; + + interactionData.target = item; + + //a sprite or display object with a hit area defined + if(item.hitArea && item.hitArea.contains) { + if(item.hitArea.contains(x, y)) { + //if(isSprite) + interactionData.target = item; + + return true; + } + + return false; + } + // a sprite with no hitarea defined + else if(isSprite) + { + var width = item.texture.frame.width, + height = item.texture.frame.height, + x1 = -width * item.anchor.x, + y1; + + if(x > x1 && x < x1 + width) + { + y1 = -height * item.anchor.y; + + if(y > y1 && y < y1 + height) + { + // set the target property if a hit is true! + interactionData.target = item + return true; + } + } + } + + var length = item.children.length; + + for (var i = 0; i < length; i++) + { + var tempItem = item.children[i]; + var hit = this.hitTest(tempItem, interactionData); + if(hit) + { + // hmm.. TODO SET CORRECT TARGET? + interactionData.target = item + return true; + } + } + + return false; +} + +/** + * Is called when a touch is moved accross the renderer element + * + * @method onTouchMove + * @param event {Event} The DOM event of a touch moving accross the renderer view + * @private + */ +PIXI.InteractionManager.prototype.onTouchMove = function(event) +{ + var rect = this.interactionDOMElement.getBoundingClientRect(); + var changedTouches = event.changedTouches; + + for (var i=0; i < changedTouches.length; i++) + { + var touchEvent = changedTouches[i]; + var touchData = this.touchs[touchEvent.identifier]; + touchData.originalEvent = event || window.event; + + // update the touch position + touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); + touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + } + + var length = this.interactiveItems.length; + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + if(item.touchmove)item.touchmove(touchData); + } +} + +/** + * Is called when a touch is started on the renderer element + * + * @method onTouchStart + * @param event {Event} The DOM event of a touch starting on the renderer view + * @private + */ +PIXI.InteractionManager.prototype.onTouchStart = function(event) +{ + var rect = this.interactionDOMElement.getBoundingClientRect(); + + var changedTouches = event.changedTouches; + for (var i=0; i < changedTouches.length; i++) + { + var touchEvent = changedTouches[i]; + + var touchData = this.pool.pop(); + if(!touchData)touchData = new PIXI.InteractionData(); + + touchData.originalEvent = event || window.event; + + this.touchs[touchEvent.identifier] = touchData; + touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); + touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + + var length = this.interactiveItems.length; + + for (var j = 0; j < length; j++) + { + var item = this.interactiveItems[j]; + + if(item.touchstart || item.tap) + { + item.__hit = this.hitTest(item, touchData); + + if(item.__hit) + { + //call the function! + if(item.touchstart)item.touchstart(touchData); + item.__isDown = true; + item.__touchData = touchData; + + if(!item.interactiveChildren)break; + } + } + } + } +} + +/** + * Is called when a touch is ended on the renderer element + * + * @method onTouchEnd + * @param event {Event} The DOM event of a touch ending on the renderer view + * @private + */ +PIXI.InteractionManager.prototype.onTouchEnd = function(event) +{ + //this.mouse.originalEvent = event || window.event; //IE uses window.event + var rect = this.interactionDOMElement.getBoundingClientRect(); + var changedTouches = event.changedTouches; + + for (var i=0; i < changedTouches.length; i++) + { + var touchEvent = changedTouches[i]; + var touchData = this.touchs[touchEvent.identifier]; + var up = false; + touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); + touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + + var length = this.interactiveItems.length; + for (var j = 0; j < length; j++) + { + var item = this.interactiveItems[j]; + var itemTouchData = item.__touchData; // <-- Here! + item.__hit = this.hitTest(item, touchData); + + if(itemTouchData == touchData) + { + // so this one WAS down... + touchData.originalEvent = event || window.event; + // hitTest?? + + if(item.touchend || item.tap) + { + if(item.__hit && !up) + { + if(item.touchend)item.touchend(touchData); + if(item.__isDown) + { + if(item.tap)item.tap(touchData); + } + + if(!item.interactiveChildren)up = true; + } + else + { + if(item.__isDown) + { + if(item.touchendoutside)item.touchendoutside(touchData); + } + } + + item.__isDown = false; + } + + item.__touchData = null; + + } + else + { + + } + } + // remove the touch.. + this.pool.push(touchData); + this.touchs[touchEvent.identifier] = null; + } +} + +/** + * Holds all information related to an Interaction event + * + * @class InteractionData + * @constructor + */ +PIXI.InteractionData = function() +{ + /** + * This point stores the global coords of where the touch/mouse event happened + * + * @property global + * @type Point + */ + this.global = new PIXI.Point(); + + // this is here for legacy... but will remove + this.local = new PIXI.Point(); + + /** + * The target Sprite that was interacted with + * + * @property target + * @type Sprite + */ + this.target; + + /** + * When passed to an event handler, this will be the original DOM Event that was captured + * + * @property originalEvent + * @type Event + */ + this.originalEvent; +} + +/** + * This will return the local coords of the specified displayObject for this InteractionData + * + * @method getLocalPosition + * @param displayObject {DisplayObject} The DisplayObject that you would like the local coords off + * @return {Point} A point containing the coords of the InteractionData position relative to the DisplayObject + */ +PIXI.InteractionData.prototype.getLocalPosition = function(displayObject) +{ + var worldTransform = displayObject.worldTransform; + var global = this.global; + + // do a cheeky transform to get the mouse coords; + var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], + a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], + id = 1 / (a00 * a11 + a01 * -a10); + // set the mouse coords... + return new PIXI.Point(a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, + a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id) +} + +// constructor +PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * A Stage represents the root of the display tree. Everything connected to the stage is rendered + * + * @class Stage + * @extends DisplayObjectContainer + * @constructor + * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format + * like: 0xFFFFFF for white + */ +PIXI.Stage = function(backgroundColor) +{ + PIXI.DisplayObjectContainer.call( this ); + + /** + * [read-only] Current transform of the object based on world (parent) factors + * + * @property worldTransform + * @type Mat3 + * @readOnly + * @private + */ + this.worldTransform = PIXI.mat3.create(); + + /** + * Whether or not the stage is interactive + * + * @property interactive + * @type Boolean + */ + this.interactive = true; + + /** + * The interaction manage for this stage, manages all interactive activity on the stage + * + * @property interactive + * @type InteractionManager + */ + this.interactionManager = new PIXI.InteractionManager(this); + + /** + * Whether the stage is dirty and needs to have interactions updated + * + * @property dirty + * @type Boolean + * @private + */ + this.dirty = true; + + this.__childrenAdded = []; + this.__childrenRemoved = []; + + //the stage is it's own stage + this.stage = this; + + //optimize hit detection a bit + this.stage.hitArea = new PIXI.Rectangle(0,0,100000, 100000); + + this.setBackgroundColor(backgroundColor); + this.worldVisible = true; +} + +// constructor +PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); +PIXI.Stage.prototype.constructor = PIXI.Stage; + +/** + * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. + * This is useful for when you have other DOM elements ontop of the Canvas element. + * + * @method setInteractionDelegate + * @param domElement {DOMElement} This new domElement which will receive mouse/touch events + */ +PIXI.Stage.prototype.setInteractionDelegate = function(domElement) +{ + this.interactionManager.setTargetDomElement( domElement ); +} + +/* + * Updates the object transform for rendering + * + * @method updateTransform + * @private + */ +PIXI.Stage.prototype.updateTransform = function() +{ + this.worldAlpha = 1; + this.vcount = PIXI.visibleCount; + + for(var i=0,j=this.children.length; i> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; +} + +/** + * A polyfill for Function.prototype.bind + * + * @method bind + */ +if (typeof Function.prototype.bind != 'function') { + Function.prototype.bind = (function () { + var slice = Array.prototype.slice; + return function (thisArg) { + var target = this, boundArgs = slice.call(arguments, 1); + + if (typeof target != 'function') throw new TypeError(); + + function bound() { + var args = boundArgs.concat(slice.call(arguments)); + target.apply(this instanceof bound ? this : thisArg, args); + } + + bound.prototype = (function F(proto) { + proto && (F.prototype = proto); + if (!(this instanceof F)) return new F; + })(target.prototype); + + return bound; + }; + })(); +} + +/** + * A wrapper for ajax requests to be handled cross browser + * + * @class AjaxRequest + * @constructor + */ +var AjaxRequest = PIXI.AjaxRequest = function() +{ + var activexmodes = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Microsoft.XMLHTTP"] //activeX versions to check for in IE + + if (window.ActiveXObject) + { //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken) + for (var i=0; i>>>>>>>>") + console.log("_") + var safe = 0; + var tmp = item.first; + console.log(tmp); + + while(tmp._iNext) + { + safe++; + tmp = tmp._iNext; + console.log(tmp); + // console.log(tmp); + + if(safe > 100) + { + console.log("BREAK") + break + } + } +} + + + + + + +/** + * https://github.com/mrdoob/eventtarget.js/ + * THankS mr DOob! + */ + +/** + * Adds event emitter functionality to a class + * + * @class EventTarget + * @example + * function MyEmitter() { + * PIXI.EventTarget.call(this); //mixes in event target stuff + * } + * + * var em = new MyEmitter(); + * em.emit({ type: 'eventName', data: 'some data' }); + */ +PIXI.EventTarget = function () { + + var listeners = {}; + + this.addEventListener = this.on = function ( type, listener ) { + + + if ( listeners[ type ] === undefined ) { + + listeners[ type ] = []; + + } + + if ( listeners[ type ].indexOf( listener ) === - 1 ) { + + listeners[ type ].push( listener ); + } + + }; + + this.dispatchEvent = this.emit = function ( event ) { + + if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { + + return; + + } + + for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { + + listeners[ event.type ][ i ]( event ); + + } + + }; + + this.removeEventListener = this.off = function ( type, listener ) { + + var index = listeners[ type ].indexOf( listener ); + + if ( index !== - 1 ) { + + listeners[ type ].splice( index, 1 ); + + } + + }; + +}; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * This helper function will automatically detect which renderer you should be using. + * WebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by + * the browser then this function will return a canvas renderer + * + * @method autoDetectRenderer + * @static + * @param width {Number} the width of the renderers view + * @param height {Number} the height of the renderers view + * @param view {Canvas} the canvas to use as a view, optional + * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) + * + * antialias + */ +PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) +{ + if(!width)width = 800; + if(!height)height = 600; + + // BORROWED from Mr Doob (mrdoob.com) + var webgl = ( function () { try { var canvas = document.createElement( 'canvas' ); return !! window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ); } catch( e ) { return false; } } )(); + + if(webgl) + { + var ie = (navigator.userAgent.toLowerCase().indexOf('msie') != -1); + webgl = !ie; + } + + //console.log(webgl); + if( webgl ) + { + return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); + } + + return new PIXI.CanvasRenderer(width, height, view, transparent); +}; + + + +/* + PolyK library + url: http://polyk.ivank.net + Released under MIT licence. + + Copyright (c) 2012 Ivan Kuckir + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + This is an amazing lib! + + slightly modified by mat groves (matgroves.com); +*/ + +PIXI.PolyK = {}; + +/** + * Triangulates shapes for webGL graphic fills + * + * @method Triangulate + * @namespace PolyK + * @constructor + */ +PIXI.PolyK.Triangulate = function(p) +{ + var sign = true; + + var n = p.length>>1; + if(n<3) return []; + var tgs = []; + var avl = []; + for(var i=0; i 3) + { + var i0 = avl[(i+0)%al]; + var i1 = avl[(i+1)%al]; + var i2 = avl[(i+2)%al]; + + var ax = p[2*i0], ay = p[2*i0+1]; + var bx = p[2*i1], by = p[2*i1+1]; + var cx = p[2*i2], cy = p[2*i2+1]; + + var earFound = false; + if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) + { + earFound = true; + for(var j=0; j 3*al) + { + // need to flip flip reverse it! + // reset! + if(sign) + { + var tgs = []; + avl = []; + for(var i=0; i= 0) && (v >= 0) && (u + v < 1); +} + +/** + * Checks if a shape is convex + * + * @class _convex + * @namespace PolyK + * @private + */ +PIXI.PolyK._convex = function(ax, ay, bx, by, cx, cy, sign) +{ + return ((ay-by)*(cx-bx) + (bx-ax)*(cy-by) >= 0) == sign; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.initDefaultShaders = function() +{ + PIXI.primitiveShader = new PIXI.PrimitiveShader(); + PIXI.primitiveShader.init(); + + PIXI.stripShader = new PIXI.StripShader(); + PIXI.stripShader.init(); + + PIXI.defaultShader = new PIXI.PixiShader(); + PIXI.defaultShader.init(); + + var gl = PIXI.gl; + var shaderProgram = PIXI.defaultShader.program; + + + gl.useProgram(shaderProgram); + + gl.enableVertexAttribArray(PIXI.defaultShader.aVertexPosition); + gl.enableVertexAttribArray(PIXI.defaultShader.colorAttribute); + gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord); +} + +PIXI.activatePrimitiveShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.primitiveShader.program); + + gl.disableVertexAttribArray(PIXI.defaultShader.aVertexPosition); + gl.disableVertexAttribArray(PIXI.defaultShader.colorAttribute); + gl.disableVertexAttribArray(PIXI.defaultShader.aTextureCoord); + + gl.enableVertexAttribArray(PIXI.primitiveShader.aVertexPosition); + gl.enableVertexAttribArray(PIXI.primitiveShader.colorAttribute); +} + +PIXI.deactivatePrimitiveShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.defaultShader.program); + + gl.disableVertexAttribArray(PIXI.primitiveShader.aVertexPosition); + gl.disableVertexAttribArray(PIXI.primitiveShader.colorAttribute); + + gl.enableVertexAttribArray(PIXI.defaultShader.aVertexPosition); + gl.enableVertexAttribArray(PIXI.defaultShader.colorAttribute); + gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord); + +} + +PIXI.activateStripShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.stripShader.program); + // gl.disableVertexAttribArray(PIXI.defaultShader.aTextureCoord); +} + +PIXI.deactivateStripShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.defaultShader.program); + //gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord); +} + +/* + +SHADER COMPILER HELPERS +*/ + +PIXI.CompileVertexShader = function(gl, shaderSrc) +{ + return PIXI._CompileShader(gl, shaderSrc, gl.VERTEX_SHADER); +} + +PIXI.CompileFragmentShader = function(gl, shaderSrc) +{ + return PIXI._CompileShader(gl, shaderSrc, gl.FRAGMENT_SHADER); +} + +PIXI._CompileShader = function(gl, shaderSrc, shaderType) +{ + var src = shaderSrc.join("\n"); + var shader = gl.createShader(shaderType); + gl.shaderSource(shader, src); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + console.log(gl.getShaderInfoLog(shader)); + return null; + } + + return shader; +} + + +PIXI.compileProgram = function(vertexSrc, fragmentSrc) +{ + var gl = PIXI.gl; + var fragmentShader = PIXI.CompileFragmentShader(gl, fragmentSrc); + var vertexShader = PIXI.CompileVertexShader(gl, vertexSrc); + + var shaderProgram = gl.createProgram(); + + gl.attachShader(shaderProgram, vertexShader); + gl.attachShader(shaderProgram, fragmentShader); + gl.linkProgram(shaderProgram); + + if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { + console.log("Could not initialise shaders"); + } + + return shaderProgram; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + * @author Richard Davey http://www.photonstorm.com @photonstorm + */ + +/** +* @class PIXI.PixiShader +* @constructor +*/ +PIXI.PixiShader = function() +{ + /** + * @property {any} program - The WebGL program. + */ + this.program; + + /** + * @property {array} fragmentSrc - The fragment shader. + */ + this.fragmentSrc = [ + "precision lowp float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", + "}" + ]; + + /** + * @property {number} textureCount - A local texture counter for multi-texture shaders. + */ + this.textureCount = 0; + +} + +/** +* @method PIXI.PixiShader#init +*/ +PIXI.PixiShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc || PIXI.PixiShader.defaultVertexSrc, this.fragmentSrc) + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get and store the uniforms for the shader + this.uSampler = gl.getUniformLocation(program, "uSampler"); + this.projectionVector = gl.getUniformLocation(program, "projectionVector"); + this.offsetVector = gl.getUniformLocation(program, "offsetVector"); + //this.dimensions = gl.getUniformLocation(this.program, "dimensions"); + + // get and store the attributes + this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); + this.colorAttribute = gl.getAttribLocation(program, "aColor"); + this.aTextureCoord = gl.getAttribLocation(program, "aTextureCoord"); + + // add those custom shaders! + for (var key in this.uniforms) + { + // get the uniform locations.. + this.uniforms[key].uniformLocation = gl.getUniformLocation(program, key); + } + + this.program = program; +} + +/** +* Updates the shader uniform values. +* Uniforms are specified in the GLSL_ES Specification: http://www.khronos.org/registry/webgl/specs/latest/1.0/ +* http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf +* +* @method PIXI.PixiShader#syncUniforms +*/ +PIXI.PixiShader.prototype.syncUniforms = function() +{ + this.textureCount = 1; + + var gl = PIXI.gl; + + for (var key in this.uniforms) + { + var type = this.uniforms[key].type; + var transpose = false; + + if (this.uniforms[key].transpose) + { + transpose = this.uniforms[key].transpose; + } + + if (type == "1f") + { + // void uniform1f(WebGLUniformLocation? location, GLfloat x); + gl.uniform1f(this.uniforms[key].uniformLocation, this.uniforms[key].value); + } + else if (type == "1fv") + { + // void uniform1fv(WebGLUniformLocation? location, Float32Array v); + // void uniform1fv(WebGLUniformLocation? location, sequence v); + gl.uniform1fv(this.uniforms[key].uniformLocation, this.uniforms[key].value); + } + else if (type == "1i") + { + // void uniform1i(WebGLUniformLocation? location, GLint x); + gl.uniform1i(this.uniforms[key].uniformLocation, this.uniforms[key].value); + } + else if (type == "1iv") + { + // void uniform1iv(WebGLUniformLocation? location, Int32Array v); + // void uniform1iv(WebGLUniformLocation? location, sequence v); + gl.uniform1i(this.uniforms[key].uniformLocation, this.uniforms[key].value); + } + else if (type == "2f") + { + // void uniform2f(WebGLUniformLocation? location, GLfloat x, GLfloat y); + gl.uniform2f(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y); + } + else if (type == "2fv") + { + // void uniform2fv(WebGLUniformLocation? location, Float32Array v); + // void uniform2fv(WebGLUniformLocation? location, sequence v); + gl.uniform2fv(this.uniforms[key].uniformLocation, this.uniforms[key].value); + } + else if (type == "2i") + { + // void uniform2i(WebGLUniformLocation? location, GLint x, GLint y); + gl.uniform2i(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y); + } + else if (type == "2iv") + { + // void uniform2iv(WebGLUniformLocation? location, Int32Array v); + // void uniform2iv(WebGLUniformLocation? location, sequence v); + gl.uniform2iv(this.uniforms[key].uniformLocation, this.uniforms[key].value); + } + else if (type == "3f") + { + // void uniform3f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z); + gl.uniform3f(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y, this.uniforms[key].value.z); + } + else if (type == "3fv") + { + // void uniform3fv(WebGLUniformLocation? location, Float32Array v); + // void uniform3fv(WebGLUniformLocation? location, sequence v); + gl.uniform3fv(this.uniforms[key].uniformLocation, this.uniforms[key].value); + } + else if (type == "3i") + { + // void uniform3i(WebGLUniformLocation? location, GLint x, GLint y, GLint z); + gl.uniform3i(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y, this.uniforms[key].value.z); + } + else if (type == "3iv") + { + // void uniform3iv(WebGLUniformLocation? location, Int32Array v); + // void uniform3iv(WebGLUniformLocation? location, sequence v); + gl.uniform3iv(this.uniforms[key].uniformLocation, this.uniforms[key].value); + } + else if (type == "4f") + { + // void uniform4f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + gl.uniform4f(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y, this.uniforms[key].value.z, this.uniforms[key].value.w); + } + else if (type == "4fv") + { + // void uniform4fv(WebGLUniformLocation? location, Float32Array v); + // void uniform4fv(WebGLUniformLocation? location, sequence v); + gl.uniform4fv(this.uniforms[key].uniformLocation, this.uniforms[key].value); + } + else if (type == "4i") + { + // void uniform4i(WebGLUniformLocation? location, GLint x, GLint y, GLint z, GLint w); + gl.uniform4i(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y, this.uniforms[key].value.z, this.uniforms[key].value.w); + } + else if (type == "4iv") + { + // void uniform4iv(WebGLUniformLocation? location, Int32Array v); + // void uniform4iv(WebGLUniformLocation? location, sequence v); + gl.uniform4iv(this.uniforms[key].uniformLocation, this.uniforms[key].value); + } + else if (type == "mat2") + { + // void uniformMatrix2fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array value); + // void uniformMatrix2fv(WebGLUniformLocation? location, GLboolean transpose, sequence value); + gl.uniformMatrix2fv(this.uniforms[key].uniformLocation, transpose, this.uniforms[key].value); + } + else if (type == "mat3") + { + // void uniformMatrix3fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array value); + // void uniformMatrix3fv(WebGLUniformLocation? location, GLboolean transpose, sequence value); + gl.uniformMatrix3fv(this.uniforms[key].uniformLocation, transpose, this.uniforms[key].value); + } + else if (type == "mat4") + { + // void uniformMatrix4fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array value); + // void uniformMatrix4fv(WebGLUniformLocation? location, GLboolean transpose, sequence value); + gl.uniformMatrix4fv(this.uniforms[key].uniformLocation, transpose, this.uniforms[key].value); + } + else if (type == "sampler2D") + { + if (this.uniforms[key].value.baseTexture.hasLoaded) + { + var texture = this.uniforms[key].value.baseTexture._glTexture; + var image = this.uniforms[key].value.baseTexture.source; + var format = gl.RGBA; + + if (this.uniforms[key].format && this.uniforms[key].format == 'luminance') + { + format = gl.LUMINANCE; + } + + gl.activeTexture(gl['TEXTURE' + this.textureCount]); + + if (this.uniforms[key].wrap) + { + if (this.uniforms[key].wrap == 'no-repeat' || this.uniforms[key].wrap === false) + { + this.createGLTextureLinear(gl, image, texture); + } + else if (this.uniforms[key].wrap == 'repeat' || this.uniforms[key].wrap === true) + { + this.createGLTexture(gl, image, format, texture); + } + else if (this.uniforms[key].wrap == 'nearest-repeat') + { + this.createGLTextureNearestRepeat(gl, image, texture); + } + else if (this.uniforms[key].wrap == 'nearest') + { + this.createGLTextureNearest(gl, image, texture); + } + else if (this.uniforms[key].wrap == 'audio') + { + this.createAudioTexture(gl, texture); + } + else if (this.uniforms[key].wrap == 'keyboard') + { + this.createKeyboardTexture(gl, texture); + } + } + else + { + this.createGLTextureLinear(gl, image, texture); + } + + gl.uniform1i(this.uniforms[key].uniformLocation, this.textureCount); + + this.textureCount++; + } + } + } + +}; + +/** +* Binds the given texture and image data. The texture is set to REPEAT. +* Code based on Effects.js from ShaderToy.com +* @method PIXI.PixiShader#createGLTexture +*/ +PIXI.PixiShader.prototype.createGLTexture = function(gl, image, format, texture) +{ + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, image); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); + gl.generateMipmap(gl.TEXTURE_2D); +} + +/** +* Binds the given texture and image data. The texture is set to CLAMP_TO_EDGE. +* Code based on Effects.js from ShaderToy.com +* @method PIXI.PixiShader#createGLTextureLinear +*/ +PIXI.PixiShader.prototype.createGLTextureLinear = function(gl, image, texture) +{ + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); +} + +/** +* Binds the given texture and image data. The texture is set to REPEAT with NEAREST. +* Code based on Effects.js from ShaderToy.com +* @method PIXI.PixiShader#createGLTextureNearestRepeat +*/ +PIXI.PixiShader.prototype.createGLTextureNearestRepeat = function(gl, image, texture) +{ + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); +} + +/** +* Binds the given texture and image data. The texture is set to CLAMP_TO_EDGE with NEAREST. +* Code based on Effects.js from ShaderToy.com +* @method PIXI.PixiShader#createGLTextureNearest +*/ +PIXI.PixiShader.prototype.createGLTextureNearest = function(gl, image, texture) +{ + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); +} + +/** +* Binds the given texture data. The texture is set to CLAMP_TO_EDGE with LUMINANCE. Designed for use with real-time audio data. +* Code based on Effects.js from ShaderToy.com +* @method PIXI.PixiShader#createAudioTexture +*/ +PIXI.PixiShader.prototype.createAudioTexture = function(gl, texture) +{ + gl.bindTexture(gl.TEXTURE_2D, texture ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) ; + gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, 512, 2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, null); +} + +/** +* Binds the given texture data. The texture is set to CLAMP_TO_EDGE with LUMINANCE. Designed for use with keyboard input data. +* Code based on Effects.js from ShaderToy.com +* @method PIXI.PixiShader#createKeyboardTexture +*/ +PIXI.PixiShader.prototype.createKeyboardTexture = function(gl, texture) +{ + gl.bindTexture(gl.TEXTURE_2D, texture ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) ; + gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, 256, 2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, null); +} + +PIXI.PixiShader.defaultVertexSrc = [ + + "attribute vec2 aVertexPosition;", + "attribute vec2 aTextureCoord;", + "attribute float aColor;", + + "uniform vec2 projectionVector;", + "uniform vec2 offsetVector;", + "varying vec2 vTextureCoord;", + + "varying float vColor;", + + "const vec2 center = vec2(-1.0, 1.0);", + + "void main(void) {", + "gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);", + "vTextureCoord = aTextureCoord;", + "vColor = aColor;", + "}" +]; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.StripShader = function() +{ + // the webGL program.. + this.program; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float alpha;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", + "gl_FragColor = gl_FragColor * alpha;", + "}" + ]; + + this.vertexSrc = [ + "attribute vec2 aVertexPosition;", + "attribute vec2 aTextureCoord;", + "attribute float aColor;", + "uniform mat3 translationMatrix;", + "uniform vec2 projectionVector;", + "varying vec2 vTextureCoord;", + "varying vec2 offsetVector;", + "varying float vColor;", + "void main(void) {", + "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", + "v -= offsetVector.xyx;", + "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);", + "vTextureCoord = aTextureCoord;", + "vColor = aColor;", + "}" + ]; +} + +PIXI.StripShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc, this.fragmentSrc) + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get and store the uniforms for the shader + this.uSampler = gl.getUniformLocation(program, "uSampler"); + this.projectionVector = gl.getUniformLocation(program, "projectionVector"); + this.offsetVector = gl.getUniformLocation(program, "offsetVector"); + this.colorAttribute = gl.getAttribLocation(program, "aColor"); + //this.dimensions = gl.getUniformLocation(this.program, "dimensions"); + + // get and store the attributes + this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); + this.aTextureCoord = gl.getAttribLocation(program, "aTextureCoord"); + + this.translationMatrix = gl.getUniformLocation(program, "translationMatrix"); + this.alpha = gl.getUniformLocation(program, "alpha"); + + this.program = program; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.PrimitiveShader = function() +{ + // the webGL program.. + this.program; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec4 vColor;", + "void main(void) {", + "gl_FragColor = vColor;", + "}" + ]; + + this.vertexSrc = [ + "attribute vec2 aVertexPosition;", + "attribute vec4 aColor;", + "uniform mat3 translationMatrix;", + "uniform vec2 projectionVector;", + "uniform vec2 offsetVector;", + "uniform float alpha;", + "varying vec4 vColor;", + "void main(void) {", + "vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);", + "v -= offsetVector.xyx;", + "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", + "vColor = aColor * alpha;", + "}" + ]; + +} + +PIXI.PrimitiveShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc, this.fragmentSrc); + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get and store the uniforms for the shader + this.projectionVector = gl.getUniformLocation(program, "projectionVector"); + this.offsetVector = gl.getUniformLocation(program, "offsetVector"); + + // get and store the attributes + this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); + this.colorAttribute = gl.getAttribLocation(program, "aColor"); + + this.translationMatrix = gl.getUniformLocation(program, "translationMatrix"); + this.alpha = gl.getUniformLocation(program, "alpha"); + + this.program = program; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * A set of functions used by the webGL renderer to draw the primitive graphics data + * + * @class CanvasGraphics + */ +PIXI.WebGLGraphics = function() +{ + +} + +/** + * Renders the graphics object + * + * @static + * @private + * @method renderGraphics + * @param graphics {Graphics} + * @param projection {Object} + */ +PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) +{ + var gl = PIXI.gl; + + if(!graphics._webGL)graphics._webGL = {points:[], indices:[], lastIndex:0, + buffer:gl.createBuffer(), + indexBuffer:gl.createBuffer()}; + + if(graphics.dirty) + { + graphics.dirty = false; + + if(graphics.clearDirty) + { + graphics.clearDirty = false; + + graphics._webGL.lastIndex = 0; + graphics._webGL.points = []; + graphics._webGL.indices = []; + + } + + PIXI.WebGLGraphics.updateGraphics(graphics); + } + + PIXI.activatePrimitiveShader(); + + // This could be speeded up fo sure! + var m = PIXI.mat3.clone(graphics.worldTransform); + + PIXI.mat3.transpose(m); + + // set the matrix transform for the + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + + gl.uniformMatrix3fv(PIXI.primitiveShader.translationMatrix, false, m); + + gl.uniform2f(PIXI.primitiveShader.projectionVector, projection.x, -projection.y); + gl.uniform2f(PIXI.primitiveShader.offsetVector, -PIXI.offset.x, -PIXI.offset.y); + + gl.uniform1f(PIXI.primitiveShader.alpha, graphics.worldAlpha); + gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); + + gl.vertexAttribPointer(PIXI.primitiveShader.aVertexPosition, 2, gl.FLOAT, false, 4 * 6, 0); + gl.vertexAttribPointer(PIXI.primitiveShader.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4); + + // set the index buffer! + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); + + + gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); + + PIXI.deactivatePrimitiveShader(); + + + // return to default shader... +// PIXI.activateShader(PIXI.defaultShader); +} + +/** + * Updates the graphics object + * + * @static + * @private + * @method updateGraphics + * @param graphics {Graphics} + */ +PIXI.WebGLGraphics.updateGraphics = function(graphics) +{ + for (var i=graphics._webGL.lastIndex; i < graphics.graphicsData.length; i++) + { + var data = graphics.graphicsData[i]; + + if(data.type == PIXI.Graphics.POLY) + { + if(data.fill) + { + if(data.points.length>3) + PIXI.WebGLGraphics.buildPoly(data, graphics._webGL); + } + + if(data.lineWidth > 0) + { + PIXI.WebGLGraphics.buildLine(data, graphics._webGL); + } + } + else if(data.type == PIXI.Graphics.RECT) + { + PIXI.WebGLGraphics.buildRectangle(data, graphics._webGL); + } + else if(data.type == PIXI.Graphics.CIRC || data.type == PIXI.Graphics.ELIP) + { + PIXI.WebGLGraphics.buildCircle(data, graphics._webGL); + } + }; + + graphics._webGL.lastIndex = graphics.graphicsData.length; + + var gl = PIXI.gl; + + graphics._webGL.glPoints = new Float32Array(graphics._webGL.points); + + gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); + gl.bufferData(gl.ARRAY_BUFFER, graphics._webGL.glPoints, gl.STATIC_DRAW); + + graphics._webGL.glIndicies = new Uint16Array(graphics._webGL.indices); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.glIndicies, gl.STATIC_DRAW); +} + +/** + * Builds a rectangle to draw + * + * @static + * @private + * @method buildRectangle + * @param graphics {Graphics} + * @param webGLData {Object} + */ +PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData) +{ + // --- // + // need to convert points to a nice regular data + // + var rectData = graphicsData.points; + var x = rectData[0]; + var y = rectData[1]; + var width = rectData[2]; + var height = rectData[3]; + + + if(graphicsData.fill) + { + var color = HEXtoRGB(graphicsData.fillColor); + var alpha = graphicsData.fillAlpha; + + var r = color[0] * alpha; + var g = color[1] * alpha; + var b = color[2] * alpha; + + var verts = webGLData.points; + var indices = webGLData.indices; + + var vertPos = verts.length/6; + + // start + verts.push(x, y); + verts.push(r, g, b, alpha); + + verts.push(x + width, y); + verts.push(r, g, b, alpha); + + verts.push(x , y + height); + verts.push(r, g, b, alpha); + + verts.push(x + width, y + height); + verts.push(r, g, b, alpha); + + // insert 2 dead triangles.. + indices.push(vertPos, vertPos, vertPos+1, vertPos+2, vertPos+3, vertPos+3) + } + + if(graphicsData.lineWidth) + { + graphicsData.points = [x, y, + x + width, y, + x + width, y + height, + x, y + height, + x, y]; + + PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); + } + +} + +/** + * Builds a circle to draw + * + * @static + * @private + * @method buildCircle + * @param graphics {Graphics} + * @param webGLData {Object} + */ +PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData) +{ + // --- // + // need to convert points to a nice regular data + // + var rectData = graphicsData.points; + var x = rectData[0]; + var y = rectData[1]; + var width = rectData[2]; + var height = rectData[3]; + + var totalSegs = 40; + var seg = (Math.PI * 2) / totalSegs ; + + if(graphicsData.fill) + { + var color = HEXtoRGB(graphicsData.fillColor); + var alpha = graphicsData.fillAlpha; + + var r = color[0] * alpha; + var g = color[1] * alpha; + var b = color[2] * alpha; + + var verts = webGLData.points; + var indices = webGLData.indices; + + var vecPos = verts.length/6; + + indices.push(vecPos); + + for (var i=0; i < totalSegs + 1 ; i++) + { + verts.push(x,y, r, g, b, alpha); + + verts.push(x + Math.sin(seg * i) * width, + y + Math.cos(seg * i) * height, + r, g, b, alpha); + + indices.push(vecPos++, vecPos++); + }; + + indices.push(vecPos-1); + } + + if(graphicsData.lineWidth) + { + graphicsData.points = []; + + for (var i=0; i < totalSegs + 1; i++) + { + graphicsData.points.push(x + Math.sin(seg * i) * width, + y + Math.cos(seg * i) * height) + }; + + PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); + } + +} + +/** + * Builds a line to draw + * + * @static + * @private + * @method buildLine + * @param graphics {Graphics} + * @param webGLData {Object} + */ +PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) +{ + // TODO OPTIMISE! + + var wrap = true; + var points = graphicsData.points; + if(points.length == 0)return; + + // if the line width is an odd number add 0.5 to align to a whole pixel + if(graphicsData.lineWidth%2) + { + for (var i = 0; i < points.length; i++) { + points[i] += 0.5; + }; + } + + // get first and last point.. figure out the middle! + var firstPoint = new PIXI.Point( points[0], points[1] ); + var lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); + + // if the first point is the last point - goona have issues :) + if(firstPoint.x == lastPoint.x && firstPoint.y == lastPoint.y) + { + points.pop(); + points.pop(); + + lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); + + var midPointX = lastPoint.x + (firstPoint.x - lastPoint.x) *0.5; + var midPointY = lastPoint.y + (firstPoint.y - lastPoint.y) *0.5; + + points.unshift(midPointX, midPointY); + points.push(midPointX, midPointY) + } + + var verts = webGLData.points; + var indices = webGLData.indices; + var length = points.length / 2; + var indexCount = points.length; + var indexStart = verts.length/6; + + // DRAW the Line + var width = graphicsData.lineWidth / 2; + + // sort color + var color = HEXtoRGB(graphicsData.lineColor); + var alpha = graphicsData.lineAlpha; + var r = color[0] * alpha; + var g = color[1] * alpha; + var b = color[2] * alpha; + + var p1x, p1y, p2x, p2y, p3x, p3y; + var perpx, perpy, perp2x, perp2y, perp3x, perp3y; + var ipx, ipy; + var a1, b1, c1, a2, b2, c2; + var denom, pdist, dist; + + p1x = points[0]; + p1y = points[1]; + + p2x = points[2]; + p2y = points[3]; + + perpx = -(p1y - p2y); + perpy = p1x - p2x; + + dist = Math.sqrt(perpx*perpx + perpy*perpy); + + perpx /= dist; + perpy /= dist; + perpx *= width; + perpy *= width; + + // start + verts.push(p1x - perpx , p1y - perpy, + r, g, b, alpha); + + verts.push(p1x + perpx , p1y + perpy, + r, g, b, alpha); + + for (var i = 1; i < length-1; i++) + { + p1x = points[(i-1)*2]; + p1y = points[(i-1)*2 + 1]; + + p2x = points[(i)*2] + p2y = points[(i)*2 + 1] + + p3x = points[(i+1)*2]; + p3y = points[(i+1)*2 + 1]; + + perpx = -(p1y - p2y); + perpy = p1x - p2x; + + dist = Math.sqrt(perpx*perpx + perpy*perpy); + perpx /= dist; + perpy /= dist; + perpx *= width; + perpy *= width; + + perp2x = -(p2y - p3y); + perp2y = p2x - p3x; + + dist = Math.sqrt(perp2x*perp2x + perp2y*perp2y); + perp2x /= dist; + perp2y /= dist; + perp2x *= width; + perp2y *= width; + + a1 = (-perpy + p1y) - (-perpy + p2y); + b1 = (-perpx + p2x) - (-perpx + p1x); + c1 = (-perpx + p1x) * (-perpy + p2y) - (-perpx + p2x) * (-perpy + p1y); + a2 = (-perp2y + p3y) - (-perp2y + p2y); + b2 = (-perp2x + p2x) - (-perp2x + p3x); + c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y); + + denom = a1*b2 - a2*b1; + + if(Math.abs(denom) < 0.1 ) + { + + denom+=10.1; + verts.push(p2x - perpx , p2y - perpy, + r, g, b, alpha); + + verts.push(p2x + perpx , p2y + perpy, + r, g, b, alpha); + + continue; + } + + px = (b1*c2 - b2*c1)/denom; + py = (a2*c1 - a1*c2)/denom; + + + pdist = (px -p2x) * (px -p2x) + (py -p2y) + (py -p2y); + + + if(pdist > 140 * 140) + { + perp3x = perpx - perp2x; + perp3y = perpy - perp2y; + + dist = Math.sqrt(perp3x*perp3x + perp3y*perp3y); + perp3x /= dist; + perp3y /= dist; + perp3x *= width; + perp3y *= width; + + verts.push(p2x - perp3x, p2y -perp3y); + verts.push(r, g, b, alpha); + + verts.push(p2x + perp3x, p2y +perp3y); + verts.push(r, g, b, alpha); + + verts.push(p2x - perp3x, p2y -perp3y); + verts.push(r, g, b, alpha); + + indexCount++; + } + else + { + + verts.push(px , py); + verts.push(r, g, b, alpha); + + verts.push(p2x - (px-p2x), p2y - (py - p2y)); + verts.push(r, g, b, alpha); + } + } + + p1x = points[(length-2)*2] + p1y = points[(length-2)*2 + 1] + + p2x = points[(length-1)*2] + p2y = points[(length-1)*2 + 1] + + perpx = -(p1y - p2y) + perpy = p1x - p2x; + + dist = Math.sqrt(perpx*perpx + perpy*perpy); + perpx /= dist; + perpy /= dist; + perpx *= width; + perpy *= width; + + verts.push(p2x - perpx , p2y - perpy) + verts.push(r, g, b, alpha); + + verts.push(p2x + perpx , p2y + perpy) + verts.push(r, g, b, alpha); + + indices.push(indexStart); + + for (var i=0; i < indexCount; i++) + { + indices.push(indexStart++); + }; + + indices.push(indexStart-1); +} + +/** + * Builds a polygon to draw + * + * @static + * @private + * @method buildPoly + * @param graphics {Graphics} + * @param webGLData {Object} + */ +PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData) +{ + var points = graphicsData.points; + if(points.length < 6)return; + + // get first and last point.. figure out the middle! + var verts = webGLData.points; + var indices = webGLData.indices; + + var length = points.length / 2; + + // sort color + var color = HEXtoRGB(graphicsData.fillColor); + var alpha = graphicsData.fillAlpha; + var r = color[0] * alpha; + var g = color[1] * alpha; + var b = color[2] * alpha; + + var triangles = PIXI.PolyK.Triangulate(points); + + var vertPos = verts.length / 6; + + for (var i=0; i < triangles.length; i+=3) + { + indices.push(triangles[i] + vertPos); + indices.push(triangles[i] + vertPos); + indices.push(triangles[i+1] + vertPos); + indices.push(triangles[i+2] +vertPos); + indices.push(triangles[i+2] + vertPos); + }; + + for (var i = 0; i < length; i++) + { + verts.push(points[i * 2], points[i * 2 + 1], + r, g, b, alpha); + }; +} + +function HEXtoRGB(hex) { + return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; +} + + + + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI._defaultFrame = new PIXI.Rectangle(0,0,1,1); + +// an instance of the gl context.. +// only one at the moment :/ +PIXI.gl; + +/** + * the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer + * should be used for browsers support webGL. This Render works by automatically managing webGLBatchs. + * So no need for Sprite Batch's or Sprite Cloud's + * Dont forget to add the view to your DOM or you will not see anything :) + * + * @class WebGLRenderer + * @constructor + * @param width=0 {Number} the width of the canvas view + * @param height=0 {Number} the height of the canvas view + * @param view {Canvas} the canvas to use as a view, optional + * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) + * + */ +PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) +{ + // do a catch.. only 1 webGL renderer.. + + this.transparent = !!transparent; + + this.width = width || 800; + this.height = height || 600; + + this.view = view || document.createElement( 'canvas' ); + this.view.width = this.width; + this.view.height = this.height; + + // deal with losing context.. + var scope = this; + this.view.addEventListener('webglcontextlost', function(event) { scope.handleContextLost(event); }, false) + this.view.addEventListener('webglcontextrestored', function(event) { scope.handleContextRestored(event); }, false) + + this.batchs = []; + + var options = { + alpha: this.transparent, + antialias:!!antialias, // SPEED UP?? + premultipliedAlpha:false, + stencil:true + } + + //try 'experimental-webgl' + try { + PIXI.gl = this.gl = this.view.getContext("experimental-webgl", options); + } catch (e) { + //try 'webgl' + try { + PIXI.gl = this.gl = this.view.getContext("webgl", options); + } catch (e) { + // fail, not able to get a context + throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); + } + } + + PIXI.initDefaultShaders(); + + + + + // PIXI.activateDefaultShader(); + + var gl = this.gl; + + gl.useProgram(PIXI.defaultShader.program); + + + PIXI.WebGLRenderer.gl = gl; + + this.batch = new PIXI.WebGLBatch(gl); + gl.disable(gl.DEPTH_TEST); + gl.disable(gl.CULL_FACE); + + gl.enable(gl.BLEND); + gl.colorMask(true, true, true, this.transparent); + + PIXI.projection = new PIXI.Point(400, 300); + PIXI.offset = new PIXI.Point(0, 0); + + // TODO remove thease globals.. + + this.resize(this.width, this.height); + this.contextLost = false; + + //PIXI.pushShader(PIXI.defaultShader); + + this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl, this.transparent); + // this.stageRenderGroup. = this.transparent +} + +// constructor +PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; + +/** + * Gets a new WebGLBatch from the pool + * + * @static + * @method getBatch + * @return {WebGLBatch} + * @private + */ +PIXI.WebGLRenderer.getBatch = function() +{ + if(PIXI._batchs.length == 0) + { + return new PIXI.WebGLBatch(PIXI.WebGLRenderer.gl); + } + else + { + return PIXI._batchs.pop(); + } +} + +/** + * Puts a batch back into the pool + * + * @static + * @method returnBatch + * @param batch {WebGLBatch} The batch to return + * @private + */ +PIXI.WebGLRenderer.returnBatch = function(batch) +{ + batch.clean(); + PIXI._batchs.push(batch); +} + +/** + * Renders the stage to its webGL view + * + * @method render + * @param stage {Stage} the Stage element to be rendered + */ +PIXI.WebGLRenderer.prototype.render = function(stage) +{ + if(this.contextLost)return; + + + // if rendering a new stage clear the batchs.. + if(this.__stage !== stage) + { + // TODO make this work + // dont think this is needed any more? + this.__stage = stage; + this.stageRenderGroup.setRenderable(stage); + } + + // update any textures + PIXI.WebGLRenderer.updateTextures(); + + // update the scene graph + PIXI.visibleCount++; + stage.updateTransform(); + + var gl = this.gl; + + // -- Does this need to be set every frame? -- // + gl.colorMask(true, true, true, this.transparent); + gl.viewport(0, 0, this.width, this.height); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); + gl.clear(gl.COLOR_BUFFER_BIT); + + // HACK TO TEST + + this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; + + PIXI.projection.x = this.width/2; + PIXI.projection.y = -this.height/2; + + this.stageRenderGroup.render(PIXI.projection); + + // interaction + // run interaction! + if(stage.interactive) + { + //need to add some events! + if(!stage._interactiveEventsAdded) + { + stage._interactiveEventsAdded = true; + stage.interactionManager.setTarget(this); + } + } + + // after rendering lets confirm all frames that have been uodated.. + if(PIXI.Texture.frameUpdates.length > 0) + { + for (var i=0; i < PIXI.Texture.frameUpdates.length; i++) + { + PIXI.Texture.frameUpdates[i].updateFrame = false; + }; + + PIXI.Texture.frameUpdates = []; + } +} + +/** + * Updates the textures loaded into this webgl renderer + * + * @static + * @method updateTextures + * @private + */ +PIXI.WebGLRenderer.updateTextures = function() +{ + //TODO break this out into a texture manager... + for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); + for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); + PIXI.texturesToUpdate = []; + PIXI.texturesToDestroy = []; +} + +/** + * Updates a loaded webgl texture + * + * @static + * @method updateTexture + * @param texture {Texture} The texture to update + * @private + */ +PIXI.WebGLRenderer.updateTexture = function(texture) +{ + //TODO break this out into a texture manager... + var gl = PIXI.gl; + + if(!texture._glTexture) + { + texture._glTexture = gl.createTexture(); + } + + if(texture.hasLoaded) + { + gl.bindTexture(gl.TEXTURE_2D, texture._glTexture); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); + + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + + // reguler... + + if(!texture._powerOf2) + { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + else + { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); + } + + gl.bindTexture(gl.TEXTURE_2D, null); + } +} + +/** + * Destroys a loaded webgl texture + * + * @method destroyTexture + * @param texture {Texture} The texture to update + * @private + */ +PIXI.WebGLRenderer.destroyTexture = function(texture) +{ + //TODO break this out into a texture manager... + var gl = PIXI.gl; + + if(texture._glTexture) + { + texture._glTexture = gl.createTexture(); + gl.deleteTexture(gl.TEXTURE_2D, texture._glTexture); + } +} + +/** + * resizes the webGL view to the specified width and height + * + * @method resize + * @param width {Number} the new width of the webGL view + * @param height {Number} the new height of the webGL view + */ +PIXI.WebGLRenderer.prototype.resize = function(width, height) +{ + this.width = width; + this.height = height; + + this.view.width = width; + this.view.height = height; + + this.gl.viewport(0, 0, this.width, this.height); + + //var projectionMatrix = this.projectionMatrix; + + PIXI.projection.x = this.width/2; + PIXI.projection.y = -this.height/2; + + //PIXI.size.x = this.width/2; + //PIXI.size.y = -this.height/2; + +// projectionMatrix[0] = 2/this.width; +// projectionMatrix[5] = -2/this.height; +// projectionMatrix[12] = -1; +// projectionMatrix[13] = 1; +} + +/** + * Handles a lost webgl context + * + * @method handleContextLost + * @param event {Event} + * @private + */ +PIXI.WebGLRenderer.prototype.handleContextLost = function(event) +{ + event.preventDefault(); + this.contextLost = true; +} + +/** + * Handles a restored webgl context + * + * @method handleContextRestored + * @param event {Event} + * @private + */ +PIXI.WebGLRenderer.prototype.handleContextRestored = function(event) +{ + this.gl = this.view.getContext("experimental-webgl", { + alpha: true + }); + + this.initShaders(); + + for(var key in PIXI.TextureCache) + { + var texture = PIXI.TextureCache[key].baseTexture; + texture._glTexture = null; + PIXI.WebGLRenderer.updateTexture(texture); + }; + + for (var i=0; i < this.batchs.length; i++) + { + this.batchs[i].restoreLostContext(this.gl)// + this.batchs[i].dirty = true; + }; + + PIXI._restoreBatchs(this.gl); + + this.contextLost = false; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI._batchs = []; + +/** + * @private + */ +PIXI._getBatch = function(gl) +{ + if(PIXI._batchs.length == 0) + { + return new PIXI.WebGLBatch(gl); + } + else + { + return PIXI._batchs.pop(); + } +} + +/** + * @private + */ +PIXI._returnBatch = function(batch) +{ + batch.clean(); + PIXI._batchs.push(batch); +} + +/** + * @private + */ +PIXI._restoreBatchs = function(gl) +{ + for (var i=0; i < PIXI._batchs.length; i++) + { + PIXI._batchs[i].restoreLostContext(gl); + }; +} + +/** + * A WebGLBatch Enables a group of sprites to be drawn using the same settings. + * if a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch. + * All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites + * in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled + * automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster + * the webGL renderer will run. + * + * @class WebGLBatch + * @constructor + * @param gl {WebGLContext} an instance of the webGL context + */ +PIXI.WebGLBatch = function(gl) +{ + this.gl = gl; + + this.size = 0; + + this.vertexBuffer = gl.createBuffer(); + this.indexBuffer = gl.createBuffer(); + this.uvBuffer = gl.createBuffer(); + this.colorBuffer = gl.createBuffer(); + this.blendMode = PIXI.blendModes.NORMAL; + this.dynamicSize = 1; +} + +// constructor +PIXI.WebGLBatch.prototype.constructor = PIXI.WebGLBatch; + +/** + * Cleans the batch so that is can be returned to an object pool and reused + * + * @method clean + */ +PIXI.WebGLBatch.prototype.clean = function() +{ + this.verticies = []; + this.uvs = []; + this.indices = []; + this.colors = []; + this.dynamicSize = 1; + this.texture = null; + this.last = null; + this.size = 0; + this.head; + this.tail; +} + +/** + * Recreates the buffers in the event of a context loss + * + * @method restoreLostContext + * @param gl {WebGLContext} + */ +PIXI.WebGLBatch.prototype.restoreLostContext = function(gl) +{ + this.gl = gl; + this.vertexBuffer = gl.createBuffer(); + this.indexBuffer = gl.createBuffer(); + this.uvBuffer = gl.createBuffer(); + this.colorBuffer = gl.createBuffer(); +} + +/** + * inits the batch's texture and blend mode based if the supplied sprite + * + * @method init + * @param sprite {Sprite} the first sprite to be added to the batch. Only sprites with + * the same base texture and blend mode will be allowed to be added to this batch + */ +PIXI.WebGLBatch.prototype.init = function(sprite) +{ + sprite.batch = this; + this.dirty = true; + this.blendMode = sprite.blendMode; + this.texture = sprite.texture.baseTexture; + this.head = sprite; + this.tail = sprite; + this.size = 1; + + this.growBatch(); +} + +/** + * inserts a sprite before the specified sprite + * + * @method insertBefore + * @param sprite {Sprite} the sprite to be added + * @param nextSprite {nextSprite} the first sprite will be inserted before this sprite + */ +PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) +{ + this.size++; + + sprite.batch = this; + this.dirty = true; + var tempPrev = nextSprite.__prev; + nextSprite.__prev = sprite; + sprite.__next = nextSprite; + + if(tempPrev) + { + sprite.__prev = tempPrev; + tempPrev.__next = sprite; + } + else + { + this.head = sprite; + } +} + +/** + * inserts a sprite after the specified sprite + * + * @method insertAfter + * @param sprite {Sprite} the sprite to be added + * @param previousSprite {Sprite} the first sprite will be inserted after this sprite + */ +PIXI.WebGLBatch.prototype.insertAfter = function(sprite, previousSprite) +{ + this.size++; + + sprite.batch = this; + this.dirty = true; + + var tempNext = previousSprite.__next; + previousSprite.__next = sprite; + sprite.__prev = previousSprite; + + if(tempNext) + { + sprite.__next = tempNext; + tempNext.__prev = sprite; + } + else + { + this.tail = sprite + } +} + +/** + * removes a sprite from the batch + * + * @method remove + * @param sprite {Sprite} the sprite to be removed + */ +PIXI.WebGLBatch.prototype.remove = function(sprite) +{ + this.size--; + + if(this.size == 0) + { + sprite.batch = null; + sprite.__prev = null; + sprite.__next = null; + return; + } + + if(sprite.__prev) + { + sprite.__prev.__next = sprite.__next; + } + else + { + this.head = sprite.__next; + this.head.__prev = null; + } + + if(sprite.__next) + { + sprite.__next.__prev = sprite.__prev; + } + else + { + this.tail = sprite.__prev; + this.tail.__next = null + } + + sprite.batch = null; + sprite.__next = null; + sprite.__prev = null; + this.dirty = true; +} + +/** + * Splits the batch into two with the specified sprite being the start of the new batch. + * + * @method split + * @param sprite {Sprite} the sprite that indicates where the batch should be split + * @return {WebGLBatch} the new batch + */ +PIXI.WebGLBatch.prototype.split = function(sprite) +{ + this.dirty = true; + + var batch = new PIXI.WebGLBatch(this.gl); + batch.init(sprite); + batch.texture = this.texture; + batch.tail = this.tail; + + this.tail = sprite.__prev; + this.tail.__next = null; + + sprite.__prev = null; + // return a splite batch! + + // TODO this size is wrong! + // need to recalculate :/ problem with a linked list! + // unless it gets calculated in the "clean"? + + // need to loop through items as there is no way to know the length on a linked list :/ + var tempSize = 0; + while(sprite) + { + tempSize++; + sprite.batch = batch; + sprite = sprite.__next; + } + + batch.size = tempSize; + this.size -= tempSize; + + return batch; +} + +/** + * Merges two batchs together + * + * @method merge + * @param batch {WebGLBatch} the batch that will be merged + */ +PIXI.WebGLBatch.prototype.merge = function(batch) +{ + this.dirty = true; + + this.tail.__next = batch.head; + batch.head.__prev = this.tail; + + this.size += batch.size; + + this.tail = batch.tail; + + var sprite = batch.head; + while(sprite) + { + sprite.batch = this; + sprite = sprite.__next; + } +} + +/** + * Grows the size of the batch. As the elements in the batch cannot have a dynamic size this + * function is used to increase the size of the batch. It also creates a little extra room so + * that the batch does not need to be resized every time a sprite is added + * + * @method growBatch + */ +PIXI.WebGLBatch.prototype.growBatch = function() +{ + var gl = this.gl; + if( this.size == 1) + { + this.dynamicSize = 1; + } + else + { + this.dynamicSize = this.size * 1.5 + } + // grow verts + this.verticies = new Float32Array(this.dynamicSize * 8); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); + + this.uvs = new Float32Array( this.dynamicSize * 8 ); + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); + + this.dirtyUVS = true; + + this.colors = new Float32Array( this.dynamicSize * 4 ); + gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); + + this.dirtyColors = true; + + this.indices = new Uint16Array(this.dynamicSize * 6); + var length = this.indices.length/6; + + for (var i=0; i < length; i++) + { + var index2 = i * 6; + var index3 = i * 4; + this.indices[index2 + 0] = index3 + 0; + this.indices[index2 + 1] = index3 + 1; + this.indices[index2 + 2] = index3 + 2; + this.indices[index2 + 3] = index3 + 0; + this.indices[index2 + 4] = index3 + 2; + this.indices[index2 + 5] = index3 + 3; + }; + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); +} + +/** + * Refresh's all the data in the batch and sync's it with the webGL buffers + * + * @method refresh + */ +PIXI.WebGLBatch.prototype.refresh = function() +{ + var gl = this.gl; + + if (this.dynamicSize < this.size) + { + this.growBatch(); + } + + var indexRun = 0; + var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index; + var a, b, c, d, tx, ty; + + var displayObject = this.head; + + while(displayObject) + { + index = indexRun * 8; + + var texture = displayObject.texture; + + var frame = texture.frame; + var tw = texture.baseTexture.width; + var th = texture.baseTexture.height; + + this.uvs[index + 0] = frame.x / tw; + this.uvs[index +1] = frame.y / th; + + this.uvs[index +2] = (frame.x + frame.width) / tw; + this.uvs[index +3] = frame.y / th; + + this.uvs[index +4] = (frame.x + frame.width) / tw; + this.uvs[index +5] = (frame.y + frame.height) / th; + + this.uvs[index +6] = frame.x / tw; + this.uvs[index +7] = (frame.y + frame.height) / th; + + displayObject.updateFrame = false; + + colorIndex = indexRun * 4; + this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; + + displayObject = displayObject.__next; + + indexRun ++; + } + + this.dirtyUVS = true; + this.dirtyColors = true; +} + +/** + * Updates all the relevant geometry and uploads the data to the GPU + * + * @method update + */ +PIXI.WebGLBatch.prototype.update = function() +{ + var gl = this.gl; + var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index, index2, index3 + + var a, b, c, d, tx, ty; + + var indexRun = 0; + + var displayObject = this.head; + var verticies = this.verticies; + var uvs = this.uvs; + var colors = this.colors; + + while(displayObject) + { + if(displayObject.vcount === PIXI.visibleCount) + { + width = displayObject.texture.frame.width; + height = displayObject.texture.frame.height; + + // TODO trim?? + aX = displayObject.anchor.x;// - displayObject.texture.trim.x + aY = displayObject.anchor.y; //- displayObject.texture.trim.y + w0 = width * (1-aX); + w1 = width * -aX; + + h0 = height * (1-aY); + h1 = height * -aY; + + index = indexRun * 8; + + worldTransform = displayObject.worldTransform; + + a = worldTransform[0]; + b = worldTransform[3]; + c = worldTransform[1]; + d = worldTransform[4]; + tx = worldTransform[2]; + ty = worldTransform[5]; + + verticies[index + 0 ] = a * w1 + c * h1 + tx; + verticies[index + 1 ] = d * h1 + b * w1 + ty; + + verticies[index + 2 ] = a * w0 + c * h1 + tx; + verticies[index + 3 ] = d * h1 + b * w0 + ty; + + verticies[index + 4 ] = a * w0 + c * h0 + tx; + verticies[index + 5 ] = d * h0 + b * w0 + ty; + + verticies[index + 6] = a * w1 + c * h0 + tx; + verticies[index + 7] = d * h0 + b * w1 + ty; + + if(displayObject.updateFrame || displayObject.texture.updateFrame) + { + this.dirtyUVS = true; + + var texture = displayObject.texture; + + var frame = texture.frame; + var tw = texture.baseTexture.width; + var th = texture.baseTexture.height; + + uvs[index + 0] = frame.x / tw; + uvs[index +1] = frame.y / th; + + uvs[index +2] = (frame.x + frame.width) / tw; + uvs[index +3] = frame.y / th; + + uvs[index +4] = (frame.x + frame.width) / tw; + uvs[index +5] = (frame.y + frame.height) / th; + + uvs[index +6] = frame.x / tw; + uvs[index +7] = (frame.y + frame.height) / th; + + displayObject.updateFrame = false; + } + + // TODO this probably could do with some optimisation.... + if(displayObject.cacheAlpha != displayObject.worldAlpha) + { + displayObject.cacheAlpha = displayObject.worldAlpha; + + var colorIndex = indexRun * 4; + colors[colorIndex] = colors[colorIndex + 1] = colors[colorIndex + 2] = colors[colorIndex + 3] = displayObject.worldAlpha; + this.dirtyColors = true; + } + } + else + { + index = indexRun * 8; + + verticies[index + 0 ] = verticies[index + 1 ] = verticies[index + 2 ] = verticies[index + 3 ] = verticies[index + 4 ] = verticies[index + 5 ] = verticies[index + 6] = verticies[index + 7] = 0; + } + + indexRun++; + displayObject = displayObject.__next; + } +} + +/** + * Draws the batch to the frame buffer + * + * @method render + */ +PIXI.WebGLBatch.prototype.render = function(start, end) +{ + start = start || 0; + + if(end == undefined)end = this.size; + + if(this.dirty) + { + this.refresh(); + this.dirty = false; + } + + if (this.size == 0)return; + + this.update(); + var gl = this.gl; + + //TODO optimize this! + + var shaderProgram = PIXI.defaultShader; + + //gl.useProgram(shaderProgram); + + // update the verts.. + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + // ok.. + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) + gl.vertexAttribPointer(shaderProgram.aVertexPosition, 2, gl.FLOAT, false, 0, 0); + // update the uvs + //var isDefault = (shaderProgram == PIXI.shaderProgram) + + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); + + if(this.dirtyUVS) + { + this.dirtyUVS = false; + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvs); + } + + gl.vertexAttribPointer(shaderProgram.aTextureCoord, 2, gl.FLOAT, false, 0, 0); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, this.texture._glTexture); + + // update color! + gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); + + if(this.dirtyColors) + { + this.dirtyColors = false; + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.colors); + } + + gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); + // dont need to upload! + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + + var len = end - start; + + // DRAW THAT this! + gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * A WebGLBatch Enables a group of sprites to be drawn using the same settings. + * if a group of sprites all have the same baseTexture and blendMode then they can be + * grouped into a batch. All the sprites in a batch can then be drawn in one go by the + * GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch + * even if the batch only contains one sprite. Batching is handled automatically by the + * webGL renderer. A good tip is: the smaller the number of batchs there are, the faster + * the webGL renderer will run. + * + * @class WebGLBatch + * @contructor + * @param gl {WebGLContext} An instance of the webGL context + */ +PIXI.WebGLRenderGroup = function(gl, transparent) +{ + this.gl = gl; + this.root; + + this.backgroundColor; + this.transparent = transparent == undefined ? true : transparent; + + this.batchs = []; + this.toRemove = []; + console.log(this.transparent) + this.filterManager = new PIXI.WebGLFilterManager(this.transparent); +} + +// constructor +PIXI.WebGLRenderGroup.prototype.constructor = PIXI.WebGLRenderGroup; + +/** + * Add a display object to the webgl renderer + * + * @method setRenderable + * @param displayObject {DisplayObject} + * @private + */ +PIXI.WebGLRenderGroup.prototype.setRenderable = function(displayObject) +{ + // has this changed?? + if(this.root)this.removeDisplayObjectAndChildren(this.root); + + displayObject.worldVisible = displayObject.visible; + + // soooooo // + // to check if any batchs exist already?? + + // TODO what if its already has an object? should remove it + this.root = displayObject; + this.addDisplayObjectAndChildren(displayObject); +} + +/** + * Renders the stage to its webgl view + * + * @method render + * @param projection {Object} + */ +PIXI.WebGLRenderGroup.prototype.render = function(projection, buffer) +{ + PIXI.WebGLRenderer.updateTextures(); + + var gl = this.gl; + gl.uniform2f(PIXI.defaultShader.projectionVector, projection.x, projection.y); + + this.filterManager.begin(projection, buffer); + + + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + // will render all the elements in the group + var renderable; + + for (var i=0; i < this.batchs.length; i++) + { + + renderable = this.batchs[i]; + if(renderable instanceof PIXI.WebGLBatch) + { + this.batchs[i].render(); + continue; + } + + // render special + this.renderSpecial(renderable, projection); + } + +} + +/** + * Renders a specific displayObject + * + * @method renderSpecific + * @param displayObject {DisplayObject} + * @param projection {Object} + * @private + */ +PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection, buffer) +{ + PIXI.WebGLRenderer.updateTextures(); + var gl = this.gl; + + gl.uniform2f(PIXI.defaultShader.projectionVector, projection.x, projection.y); + + this.filterManager.begin(projection, buffer); + + // to do! + // render part of the scene... + + var startIndex; + var startBatchIndex; + + var endIndex; + var endBatchIndex; + + /* + * LOOK FOR THE NEXT SPRITE + * This part looks for the closest next sprite that can go into a batch + * it keeps looking until it finds a sprite or gets to the end of the display + * scene graph + */ + var nextRenderable = displayObject.first; + while(nextRenderable._iNext) + { + if(nextRenderable.renderable && nextRenderable.__renderGroup)break; + nextRenderable = nextRenderable._iNext; + } + var startBatch = nextRenderable.batch; + //console.log(nextRenderable); + + //console.log(renderable) + if(nextRenderable instanceof PIXI.Sprite) + { + startBatch = nextRenderable.batch; + + var head = startBatch.head; + var next = head; + + // ok now we have the batch.. need to find the start index! + if(head == nextRenderable) + { + startIndex = 0; + } + else + { + startIndex = 1; + + while(head.__next != nextRenderable) + { + startIndex++; + head = head.__next; + } + } + } + else + { + startBatch = nextRenderable; + } + + // Get the LAST renderable object + var lastRenderable = displayObject.last; + while(lastRenderable._iPrev) + { + if(lastRenderable.renderable && lastRenderable.__renderGroup)break; + lastRenderable = lastRenderable._iNext; + } + + if(lastRenderable instanceof PIXI.Sprite) + { + endBatch = lastRenderable.batch; + + var head = endBatch.head; + + if(head == lastRenderable) + { + endIndex = 0; + } + else + { + endIndex = 1; + + while(head.__next != lastRenderable) + { + endIndex++; + head = head.__next; + } + } + } + else + { + endBatch = lastRenderable; + } + + //console.log(endBatch); + // TODO - need to fold this up a bit! + + if(startBatch == endBatch) + { + if(startBatch instanceof PIXI.WebGLBatch) + { + startBatch.render(startIndex, endIndex+1); + } + else + { + this.renderSpecial(startBatch, projection); + } + return; + } + + // now we have first and last! + startBatchIndex = this.batchs.indexOf(startBatch); + endBatchIndex = this.batchs.indexOf(endBatch); + + // DO the first batch + if(startBatch instanceof PIXI.WebGLBatch) + { + startBatch.render(startIndex); + } + else + { + this.renderSpecial(startBatch, projection); + } + + // DO the middle batchs.. + for (var i=startBatchIndex+1; i < endBatchIndex; i++) + { + renderable = this.batchs[i]; + + if(renderable instanceof PIXI.WebGLBatch) + { + this.batchs[i].render(); + } + else + { + this.renderSpecial(renderable, projection); + } + } + + // DO the last batch.. + if(endBatch instanceof PIXI.WebGLBatch) + { + endBatch.render(0, endIndex+1); + } + else + { + this.renderSpecial(endBatch, projection); + } +} + +/** + * Renders a specific renderable + * + * @method renderSpecial + * @param renderable {DisplayObject} + * @param projection {Object} + * @private + */ +PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) +{ + + var worldVisible = renderable.vcount === PIXI.visibleCount + + + if(renderable instanceof PIXI.TilingSprite) + { + if(worldVisible)this.renderTilingSprite(renderable, projection); + } + else if(renderable instanceof PIXI.Strip) + { + if(worldVisible)this.renderStrip(renderable, projection); + } + else if(renderable instanceof PIXI.CustomRenderable) + { + if(worldVisible) renderable.renderWebGL(this, projection); + } + else if(renderable instanceof PIXI.Graphics) + { + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); + } + else if(renderable instanceof PIXI.FilterBlock) + { + this.handleFilterBlock(renderable, projection); + } +} + +flip = false; +var maskStack = []; +var maskPosition = 0; + +//var usedMaskStack = []; + +PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(filterBlock, projection) +{ + /* + * for now only masks are supported.. + */ + var gl = PIXI.gl; + + if(filterBlock.open) + { + if(filterBlock.data instanceof Array) + { + this.filterManager.pushFilter(filterBlock); + // ok so.. + + } + else + { + maskPosition++; + + maskStack.push(filterBlock) + + gl.enable(gl.STENCIL_TEST); + + gl.colorMask(false, false, false, false); + + gl.stencilFunc(gl.ALWAYS,1,1); + gl.stencilOp(gl.KEEP,gl.KEEP,gl.INCR); + + PIXI.WebGLGraphics.renderGraphics(filterBlock.data, projection); + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.NOTEQUAL,0,maskStack.length); + gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); + } + } + else + { + if(filterBlock.data instanceof Array) + { + this.filterManager.popFilter(); + } + else + { + var maskData = maskStack.pop(filterBlock) + + + if(maskData) + { + gl.colorMask(false, false, false, false); + + gl.stencilFunc(gl.ALWAYS,1,1); + gl.stencilOp(gl.KEEP,gl.KEEP,gl.DECR); + + PIXI.WebGLGraphics.renderGraphics(maskData.data, projection); + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.NOTEQUAL,0,maskStack.length); + gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); + }; + + gl.disable(gl.STENCIL_TEST); + } + } +} + +/** + * Updates a webgl texture + * + * @method updateTexture + * @param displayObject {DisplayObject} + * @private + */ +PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject) +{ + + // TODO definitely can optimse this function.. + + this.removeObject(displayObject); + + /* + * LOOK FOR THE PREVIOUS RENDERABLE + * This part looks for the closest previous sprite that can go into a batch + * It keeps going back until it finds a sprite or the stage + */ + var previousRenderable = displayObject.first; + while(previousRenderable != this.root) + { + previousRenderable = previousRenderable._iPrev; + if(previousRenderable.renderable && previousRenderable.__renderGroup)break; + } + + /* + * LOOK FOR THE NEXT SPRITE + * This part looks for the closest next sprite that can go into a batch + * it keeps looking until it finds a sprite or gets to the end of the display + * scene graph + */ + var nextRenderable = displayObject.last; + while(nextRenderable._iNext) + { + nextRenderable = nextRenderable._iNext; + if(nextRenderable.renderable && nextRenderable.__renderGroup)break; + } + + this.insertObject(displayObject, previousRenderable, nextRenderable); +} + +/** + * Adds filter blocks + * + * @method addFilterBlocks + * @param start {FilterBlock} + * @param end {FilterBlock} + * @private + */ +PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) +{ + start.__renderGroup = this; + end.__renderGroup = this; + /* + * LOOK FOR THE PREVIOUS RENDERABLE + * This part looks for the closest previous sprite that can go into a batch + * It keeps going back until it finds a sprite or the stage + */ + var previousRenderable = start; + while(previousRenderable != this.root.first) + { + previousRenderable = previousRenderable._iPrev; + if(previousRenderable.renderable && previousRenderable.__renderGroup)break; + } + this.insertAfter(start, previousRenderable); + + /* + * LOOK FOR THE NEXT SPRITE + * This part looks for the closest next sprite that can go into a batch + * it keeps looking until it finds a sprite or gets to the end of the display + * scene graph + */ + var previousRenderable2 = end; + while(previousRenderable2 != this.root.first) + { + previousRenderable2 = previousRenderable2._iPrev; + if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; + } + this.insertAfter(end, previousRenderable2); +} + +/** + * Remove filter blocks + * + * @method removeFilterBlocks + * @param start {FilterBlock} + * @param end {FilterBlock} + * @private + */ +PIXI.WebGLRenderGroup.prototype.removeFilterBlocks = function(start, end) +{ + this.removeObject(start); + this.removeObject(end); +} + +/** + * Adds a display object and children to the webgl context + * + * @method addDisplayObjectAndChildren + * @param displayObject {DisplayObject} + * @private + */ +PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayObject) +{ + if(displayObject.__renderGroup)displayObject.__renderGroup.removeDisplayObjectAndChildren(displayObject); + + /* + * LOOK FOR THE PREVIOUS RENDERABLE + * This part looks for the closest previous sprite that can go into a batch + * It keeps going back until it finds a sprite or the stage + */ + + var previousRenderable = displayObject.first; + while(previousRenderable != this.root.first) + { + previousRenderable = previousRenderable._iPrev; + if(previousRenderable.renderable && previousRenderable.__renderGroup)break; + } + + /* + * LOOK FOR THE NEXT SPRITE + * This part looks for the closest next sprite that can go into a batch + * it keeps looking until it finds a sprite or gets to the end of the display + * scene graph + */ + var nextRenderable = displayObject.last; + while(nextRenderable._iNext) + { + nextRenderable = nextRenderable._iNext; + if(nextRenderable.renderable && nextRenderable.__renderGroup)break; + } + + // one the display object hits this. we can break the loop + + var tempObject = displayObject.first; + var testObject = displayObject.last._iNext; + do + { + tempObject.__renderGroup = this; + + if(tempObject.renderable) + { + + this.insertObject(tempObject, previousRenderable, nextRenderable); + previousRenderable = tempObject; + } + + tempObject = tempObject._iNext; + } + while(tempObject != testObject) +} + +/** + * Removes a display object and children to the webgl context + * + * @method removeDisplayObjectAndChildren + * @param displayObject {DisplayObject} + * @private + */ +PIXI.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren = function(displayObject) +{ + if(displayObject.__renderGroup != this)return; + +// var displayObject = displayObject.first; + var lastObject = displayObject.last; + do + { + displayObject.__renderGroup = null; + if(displayObject.renderable)this.removeObject(displayObject); + displayObject = displayObject._iNext; + } + while(displayObject) +} + +/** + * Inserts a displayObject into the linked list + * + * @method insertObject + * @param displayObject {DisplayObject} + * @param previousObject {DisplayObject} + * @param nextObject {DisplayObject} + * @private + */ +PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousObject, nextObject) +{ + // while looping below THE OBJECT MAY NOT HAVE BEEN ADDED + var previousSprite = previousObject; + var nextSprite = nextObject; + + /* + * so now we have the next renderable and the previous renderable + * + */ + if(displayObject instanceof PIXI.Sprite) + { + var previousBatch + var nextBatch + + if(previousSprite instanceof PIXI.Sprite) + { + previousBatch = previousSprite.batch; + if(previousBatch) + { + if(previousBatch.texture == displayObject.texture.baseTexture && previousBatch.blendMode == displayObject.blendMode) + { + previousBatch.insertAfter(displayObject, previousSprite); + return; + } + } + } + else + { + // TODO reword! + previousBatch = previousSprite; + } + + if(nextSprite) + { + if(nextSprite instanceof PIXI.Sprite) + { + nextBatch = nextSprite.batch; + + //batch may not exist if item was added to the display list but not to the webGL + if(nextBatch) + { + if(nextBatch.texture == displayObject.texture.baseTexture && nextBatch.blendMode == displayObject.blendMode) + { + nextBatch.insertBefore(displayObject, nextSprite); + return; + } + else + { + if(nextBatch == previousBatch) + { + // THERE IS A SPLIT IN THIS BATCH! // + var splitBatch = previousBatch.split(nextSprite); + // COOL! + // add it back into the array + /* + * OOPS! + * seems the new sprite is in the middle of a batch + * lets split it.. + */ + var batch = PIXI.WebGLRenderer.getBatch(); + + var index = this.batchs.indexOf( previousBatch ); + batch.init(displayObject); + this.batchs.splice(index+1, 0, batch, splitBatch); + + return; + } + } + } + } + else + { + // TODO re-word! + + nextBatch = nextSprite; + } + } + + /* + * looks like it does not belong to any batch! + * but is also not intersecting one.. + * time to create anew one! + */ + + var batch = PIXI.WebGLRenderer.getBatch(); + batch.init(displayObject); + + if(previousBatch) // if this is invalid it means + { + var index = this.batchs.indexOf( previousBatch ); + this.batchs.splice(index+1, 0, batch); + } + else + { + this.batchs.push(batch); + } + + return; + } + else if(displayObject instanceof PIXI.TilingSprite) + { + + // add to a batch!! + this.initTilingSprite(displayObject); + // this.batchs.push(displayObject); + + } + else if(displayObject instanceof PIXI.Strip) + { + // add to a batch!! + this.initStrip(displayObject); + // this.batchs.push(displayObject); + } + else if(displayObject)// instanceof PIXI.Graphics) + { + //displayObject.initWebGL(this); + + // add to a batch!! + //this.initStrip(displayObject); + //this.batchs.push(displayObject); + } + + this.insertAfter(displayObject, previousSprite); + + // insert and SPLIT! + +} + +/** + * Inserts a displayObject into the linked list + * + * @method insertAfter + * @param item {DisplayObject} + * @param displayObject {DisplayObject} The object to insert + * @private + */ +PIXI.WebGLRenderGroup.prototype.insertAfter = function(item, displayObject) +{ + if(displayObject instanceof PIXI.Sprite) + { + var previousBatch = displayObject.batch; + + if(previousBatch) + { + // so this object is in a batch! + + // is it not? need to split the batch + if(previousBatch.tail == displayObject) + { + // is it tail? insert in to batchs + var index = this.batchs.indexOf( previousBatch ); + this.batchs.splice(index+1, 0, item); + } + else + { + // TODO MODIFY ADD / REMOVE CHILD TO ACCOUNT FOR FILTERS (also get prev and next) // + + // THERE IS A SPLIT IN THIS BATCH! // + var splitBatch = previousBatch.split(displayObject.__next); + + // COOL! + // add it back into the array + /* + * OOPS! + * seems the new sprite is in the middle of a batch + * lets split it.. + */ + var index = this.batchs.indexOf( previousBatch ); + this.batchs.splice(index+1, 0, item, splitBatch); + } + } + else + { + this.batchs.push(item); + } + } + else + { + var index = this.batchs.indexOf( displayObject ); + this.batchs.splice(index+1, 0, item); + } +} + +/** + * Removes a displayObject from the linked list + * + * @method removeObject + * @param displayObject {DisplayObject} The object to remove + * @private + */ +PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) +{ + // loop through children.. + // display object // + + // add a child from the render group.. + // remove it and all its children! + //displayObject.cacheVisible = false;//displayObject.visible; + + /* + * removing is a lot quicker.. + * + */ + var batchToRemove; + + if(displayObject instanceof PIXI.Sprite) + { + // should always have a batch! + var batch = displayObject.batch; + if(!batch)return; // this means the display list has been altered befre rendering + + batch.remove(displayObject); + + if(batch.size==0) + { + batchToRemove = batch; + } + } + else + { + batchToRemove = displayObject; + } + + /* + * Looks like there is somthing that needs removing! + */ + if(batchToRemove) + { + var index = this.batchs.indexOf( batchToRemove ); + if(index == -1)return;// this means it was added then removed before rendered + + // ok so.. check to see if you adjacent batchs should be joined. + // TODO may optimise? + if(index == 0 || index == this.batchs.length-1) + { + // wha - eva! just get of the empty batch! + this.batchs.splice(index, 1); + if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); + + return; + } + + if(this.batchs[index-1] instanceof PIXI.WebGLBatch && this.batchs[index+1] instanceof PIXI.WebGLBatch) + { + if(this.batchs[index-1].texture == this.batchs[index+1].texture && this.batchs[index-1].blendMode == this.batchs[index+1].blendMode) + { + //console.log("MERGE") + this.batchs[index-1].merge(this.batchs[index+1]); + + if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); + PIXI.WebGLRenderer.returnBatch(this.batchs[index+1]); + this.batchs.splice(index, 2); + return; + } + } + + this.batchs.splice(index, 1); + if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); + } +} + + +/** + * Initializes a tiling sprite + * + * @method initTilingSprite + * @param sprite {TilingSprite} The tiling sprite to initialize + * @private + */ +PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) +{ + var gl = this.gl; + + // make the texture tilable.. + + sprite.verticies = new Float32Array([0, 0, + sprite.width, 0, + sprite.width, sprite.height, + 0, sprite.height]); + + sprite.uvs = new Float32Array([0, 0, + 1, 0, + 1, 1, + 0, 1]); + + sprite.colors = new Float32Array([1,1,1,1]); + + sprite.indices = new Uint16Array([0, 1, 3,2])//, 2]); + + sprite._vertexBuffer = gl.createBuffer(); + sprite._indexBuffer = gl.createBuffer(); + sprite._uvBuffer = gl.createBuffer(); + sprite._colorBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, sprite._vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, sprite.verticies, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, sprite.uvs, gl.DYNAMIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, sprite._colorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, sprite.colors, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sprite._indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sprite.indices, gl.STATIC_DRAW); + +// return ( (x > 0) && ((x & (x - 1)) == 0) ); + + if(sprite.texture.baseTexture._glTexture) + { + gl.bindTexture(gl.TEXTURE_2D, sprite.texture.baseTexture._glTexture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); + sprite.texture.baseTexture._powerOf2 = true; + } + else + { + sprite.texture.baseTexture._powerOf2 = true; + } +} + +/** + * Renders a Strip + * + * @method renderStrip + * @param strip {Strip} The strip to render + * @param projection {Object} + * @private + */ +PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) +{ + var gl = this.gl; + + PIXI.activateStripShader(); + + var shader = PIXI.stripShader; + + var program = shader.program; + + var m = PIXI.mat3.clone(strip.worldTransform); + + PIXI.mat3.transpose(m); + +// console.log(projection) + // set the matrix transform for the + gl.uniformMatrix3fv(shader.translationMatrix, false, m); + gl.uniform2f(shader.projectionVector, projection.x, projection.y); + gl.uniform2f(shader.offsetVector, -PIXI.offset.x, -PIXI.offset.y); + + gl.uniform1f(shader.alpha, strip.worldAlpha); + + /* + if(strip.blendMode == PIXI.blendModes.NORMAL) + { + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + } + else + { + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR); + } + */ + + //console.log("!!") + if(!strip.dirty) + { + gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); + gl.bufferSubData(gl.ARRAY_BUFFER, 0, strip.verticies) + gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0); + + // update the uvs + gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); + gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); + gl.vertexAttribPointer(shader.colorAttribute, 1, gl.FLOAT, false, 0, 0); + + // dont need to upload! + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); + } + else + { + strip.dirty = false; + gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.STATIC_DRAW) + gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0); + + // update the uvs + gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW) + gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); + // console.log(strip.texture.baseTexture._glTexture) + gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW) + gl.vertexAttribPointer(shader.colorAttribute, 1, gl.FLOAT, false, 0, 0); + + // dont need to upload! + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); + + } + + gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); + + PIXI.deactivateStripShader(); + //gl.useProgram(PIXI.currentProgram); +} + +/** + * Renders a TilingSprite + * + * @method renderTilingSprite + * @param sprite {TilingSprite} The tiling sprite to render + * @param projectionMatrix {Object} + * @private + */ +PIXI.WebGLRenderGroup.prototype.renderTilingSprite = function(sprite, projectionMatrix) +{ + var gl = this.gl; + + + var shaderProgram = PIXI.shaderProgram; + + var tilePosition = sprite.tilePosition; + var tileScale = sprite.tileScale; + + var offsetX = tilePosition.x/sprite.texture.baseTexture.width; + var offsetY = tilePosition.y/sprite.texture.baseTexture.height; + + var scaleX = (sprite.width / sprite.texture.baseTexture.width) / tileScale.x; + var scaleY = (sprite.height / sprite.texture.baseTexture.height) / tileScale.y; + + sprite.uvs[0] = 0 - offsetX; + sprite.uvs[1] = 0 - offsetY; + + sprite.uvs[2] = (1 * scaleX) -offsetX; + sprite.uvs[3] = 0 - offsetY; + + sprite.uvs[4] = (1 *scaleX) - offsetX; + sprite.uvs[5] = (1 *scaleY) - offsetY; + + sprite.uvs[6] = 0 - offsetX; + sprite.uvs[7] = (1 *scaleY) - offsetY; + + gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); + gl.bufferSubData(gl.ARRAY_BUFFER, 0, sprite.uvs) + + this.renderStrip(sprite, projectionMatrix); +} + +/** + * Initializes a strip to be rendered + * + * @method initStrip + * @param strip {Strip} The strip to initialize + * @private + */ +PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) +{ + // build the strip! + var gl = this.gl; + var shaderProgram = this.shaderProgram; + + strip._vertexBuffer = gl.createBuffer(); + strip._indexBuffer = gl.createBuffer(); + strip._uvBuffer = gl.createBuffer(); + strip._colorBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.DYNAMIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW); + + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); +} + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.WebGLFilterManager = function(transparent) +{ + this.transparent = transparent; + + this.filterStack = []; + this.texturePool = []; + + this.offsetX = 0; + this.offsetY = 0; + + this.initShaderBuffers(); +} + +// API + +PIXI.WebGLFilterManager.prototype.begin = function(projection, buffer) +{ + this.width = projection.x * 2; + this.height = -projection.y * 2; + this.buffer = buffer; +} + +PIXI.WebGLFilterManager.prototype.pushFilter = function(filterBlock) +{ + var gl = PIXI.gl; + + // filter program + // OPTIMISATION - the first filter is free if its a simple color change? + this.filterStack.push(filterBlock); + + var filter = filterBlock.filterPasses[0]; + + + + this.offsetX += filterBlock.target.filterArea.x; + this.offsetY += filterBlock.target.filterArea.y; + + + + + + var texture = this.texturePool.pop(); + if(!texture)texture = new PIXI.FilterTexture(this.width, this.height); + + gl.bindTexture(gl.TEXTURE_2D, texture.texture); + + this.getBounds(filterBlock.target); + + // addpadding? + //displayObject.filterArea.x + + var filterArea = filterBlock.target.filterArea; + + var padidng = filter.padding; + filterArea.x -= padidng; + filterArea.y -= padidng; + filterArea.width += padidng * 2; + filterArea.height += padidng * 2; + + // cap filter to screen size.. + if(filterArea.x < 0)filterArea.x = 0; + if(filterArea.width > this.width)filterArea.width = this.width; + if(filterArea.y < 0)filterArea.y = 0; + if(filterArea.height > this.height)filterArea.height = this.height; + + + //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, filterArea.width, filterArea.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.bindFramebuffer(gl.FRAMEBUFFER, texture.frameBuffer); + + // console.log(filterArea) + // set view port + gl.viewport(0, 0, filterArea.width, filterArea.height); + + PIXI.projection.x = filterArea.width/2; + PIXI.projection.y = -filterArea.height/2; + + PIXI.offset.x = -filterArea.x; + PIXI.offset.y = -filterArea.y; + + //console.log(PIXI.defaultShader.projectionVector) + // update projection + gl.uniform2f(PIXI.defaultShader.projectionVector, filterArea.width/2, -filterArea.height/2); + gl.uniform2f(PIXI.defaultShader.offsetVector, -filterArea.x, -filterArea.y); + //PIXI.primitiveProgram + + gl.colorMask(true, true, true, true); + gl.clearColor(0,0,0, 0); + gl.clear(gl.COLOR_BUFFER_BIT); + + //filter.texture = texture; + filterBlock._glFilterTexture = texture; + + //console.log("PUSH") +} + + +PIXI.WebGLFilterManager.prototype.popFilter = function() +{ + + var gl = PIXI.gl; + + var filterBlock = this.filterStack.pop(); + + + + var filterArea = filterBlock.target.filterArea; + + var texture = filterBlock._glFilterTexture; + + if(filterBlock.filterPasses.length > 1) + { + gl.viewport(0, 0, filterArea.width, filterArea.height); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + + this.vertexArray[0] = 0; + this.vertexArray[1] = filterArea.height; + + this.vertexArray[2] = filterArea.width; + this.vertexArray[3] = filterArea.height; + + this.vertexArray[4] = 0; + this.vertexArray[5] = 0; + + this.vertexArray[6] = filterArea.width; + this.vertexArray[7] = 0; + + + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray); + + + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); + // nnow set the uvs.. + this.uvArray[2] = filterArea.width/this.width; + this.uvArray[5] = filterArea.height/this.height; + this.uvArray[6] = filterArea.width/this.width; + this.uvArray[7] = filterArea.height/this.height; + + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray); + + var inputTexture = texture; + var outputTexture = this.texturePool.pop(); + if(!outputTexture)outputTexture = new PIXI.FilterTexture(this.width, this.height); + + // need to clear this FBO as it may have some left over elements from a prvious filter. + gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer ); + gl.clear(gl.COLOR_BUFFER_BIT); + + gl.disable(gl.BLEND); + + for (var i = 0; i < filterBlock.filterPasses.length-1; i++) + { + var filterPass = filterBlock.filterPasses[i]; + + gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer ); + + // set texture + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, inputTexture.texture); + + // draw texture.. + //filterPass.applyFilterPass(filterArea.width, filterArea.height); + this.applyFilterPass(filterPass, filterArea, filterArea.width, filterArea.height); + + // swap the textures.. + var temp = inputTexture; + inputTexture = outputTexture; + outputTexture = temp; + + }; + + gl.enable(gl.BLEND); + + texture = inputTexture; + this.texturePool.push(outputTexture); + } + + var filter = filterBlock.filterPasses[filterBlock.filterPasses.length-1]; + + this.offsetX -= filterArea.x; + this.offsetY -= filterArea.y; + + + var sizeX = this.width; + var sizeY = this.height; + + var offsetX = 0; + var offsetY = 0; + + var buffer = this.buffer; + + // time to render the filters texture to the previous scene + if(this.filterStack.length === 0) + { + gl.colorMask(true, true, true, this.transparent); + } + else + { + var currentFilter = this.filterStack[this.filterStack.length-1]; + var filterArea = currentFilter.target.filterArea; + + sizeX = filterArea.width; + sizeY = filterArea.height; + + offsetX = filterArea.x; + offsetY = filterArea.y; + + buffer = currentFilter._glFilterTexture.frameBuffer; + } + + + + // TODO need toremove thease global elements.. + PIXI.projection.x = sizeX/2; + PIXI.projection.y = -sizeY/2; + + PIXI.offset.x = offsetX; + PIXI.offset.y = offsetY; + + + var filterArea = filterBlock.target.filterArea; + var x = filterArea.x-offsetX; + var y = filterArea.y-offsetY; + + // update the buffers.. + // make sure to flip the y! + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + + this.vertexArray[0] = x; + this.vertexArray[1] = y + filterArea.height; + + this.vertexArray[2] = x + filterArea.width; + this.vertexArray[3] = y + filterArea.height; + + this.vertexArray[4] = x; + this.vertexArray[5] = y; + + this.vertexArray[6] = x + filterArea.width; + this.vertexArray[7] = y; + + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); + + this.uvArray[2] = filterArea.width/this.width; + this.uvArray[5] = filterArea.height/this.height; + this.uvArray[6] = filterArea.width/this.width; + this.uvArray[7] = filterArea.height/this.height; + + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray); + + gl.viewport(0, 0, sizeX, sizeY); + // bind the buffer + gl.bindFramebuffer(gl.FRAMEBUFFER, buffer ); + + // set texture + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, texture.texture); + + // apply! + //filter.applyFilterPass(sizeX, sizeY); + this.applyFilterPass(filter, filterArea, sizeX, sizeY); + + // now restore the regular shader.. + gl.useProgram(PIXI.defaultShader.program); + gl.uniform2f(PIXI.defaultShader.projectionVector, sizeX/2, -sizeY/2); + gl.uniform2f(PIXI.defaultShader.offsetVector, -offsetX, -offsetY); + + // return the texture to the pool + this.texturePool.push(texture); + filterBlock._glFilterTexture = null; +} + +PIXI.WebGLFilterManager.prototype.applyFilterPass = function(filter, filterArea, width, height) +{ + // use program + var gl = PIXI.gl; + + if(!filter.shader) + { + var shader = new PIXI.PixiShader(); + + shader.fragmentSrc = filter.fragmentSrc; + shader.uniforms = filter.uniforms; + shader.init(); + + filter.shader = shader; + } + + var shader = filter.shader; + + // set the shader + gl.useProgram(shader.program); + + gl.uniform2f(shader.projectionVector, width/2, -height/2); + gl.uniform2f(shader.offsetVector, 0,0) + + if(filter.uniforms.dimensions) + { + //console.log(filter.uniforms.dimensions) + filter.uniforms.dimensions.value[0] = this.width;//width; + filter.uniforms.dimensions.value[1] = this.height;//height; + filter.uniforms.dimensions.value[2] = this.vertexArray[0]; + filter.uniforms.dimensions.value[3] = this.vertexArray[5];//filterArea.height; + // console.log(this.vertexArray[5]) + } + + shader.syncUniforms(); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); + gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + + // draw the filter... + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); +} + +PIXI.WebGLFilterManager.prototype.initShaderBuffers = function() +{ + var gl = PIXI.gl; + + // create some buffers + this.vertexBuffer = gl.createBuffer(); + this.uvBuffer = gl.createBuffer(); + this.indexBuffer = gl.createBuffer(); + + // bind and upload the vertexs.. + // keep a refferance to the vertexFloatData.. + this.vertexArray = new Float32Array([0.0, 0.0, + 1.0, 0.0, + 0.0, 1.0, + 1.0, 1.0]); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + gl.bufferData( + gl.ARRAY_BUFFER, + this.vertexArray, + gl.STATIC_DRAW); + + + // bind and upload the uv buffer + this.uvArray = new Float32Array([0.0, 0.0, + 1.0, 0.0, + 0.0, 1.0, + 1.0, 1.0]); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); + gl.bufferData( + gl.ARRAY_BUFFER, + this.uvArray, + gl.STATIC_DRAW); + + // bind and upload the index + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + gl.bufferData( + gl.ELEMENT_ARRAY_BUFFER, + new Uint16Array([0, 1, 2, 1, 3, 2]), + gl.STATIC_DRAW); +} + +PIXI.WebGLFilterManager.prototype.getBounds = function(displayObject) +{ + // time to get the width and height of the object! + var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index, doTest; + var a, b, c, d, tx, ty, x1, x2, x3, x4, y1, y2, y3, y4; + + var tempObject = displayObject.first; + var testObject = displayObject.last._iNext; + + var maxX = -Infinity; + var maxY = -Infinity; + + var minX = Infinity; + var minY = Infinity; + + do + { + // TODO can be optimized! - what if there is no scale / rotation? + + if(tempObject.visible) + { + if(tempObject instanceof PIXI.Sprite) + { + width = tempObject.texture.frame.width; + height = tempObject.texture.frame.height; + + // TODO trim?? + aX = tempObject.anchor.x; + aY = tempObject.anchor.y; + w0 = width * (1-aX); + w1 = width * -aX; + + h0 = height * (1-aY); + h1 = height * -aY; + + doTest = true; + } + else if(tempObject instanceof PIXI.Graphics) + { + tempObject.updateFilterBounds(); + + var bounds = tempObject.bounds; + + width = bounds.width; + height = bounds.height; + + w0 = bounds.x + w1 = bounds.x + bounds.width; + + h0 = bounds.y + h1 = bounds.y + bounds.height; + + doTest = true; + } + } + + if(doTest) + { + worldTransform = tempObject.worldTransform; + + a = worldTransform[0]; + b = worldTransform[3]; + c = worldTransform[1]; + d = worldTransform[4]; + tx = worldTransform[2]; + ty = worldTransform[5]; + + x1 = a * w1 + c * h1 + tx; + y1 = d * h1 + b * w1 + ty; + + x2 = a * w0 + c * h1 + tx; + y2 = d * h1 + b * w0 + ty; + + x3 = a * w0 + c * h0 + tx; + y3 = d * h0 + b * w0 + ty; + + x4 = a * w1 + c * h0 + tx; + y4 = d * h0 + b * w1 + ty; + + 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; + } + + doTest = false; + tempObject = tempObject._iNext; + + } + while(tempObject != testObject) + + // maximum bounds is the size of the screen.. + //minX = minX > 0 ? minX : 0; + //minY = minY > 0 ? minY : 0; + + displayObject.filterArea.x = minX; + displayObject.filterArea.y = minY; + +// console.log(maxX+ " : " + minX) + displayObject.filterArea.width = maxX - minX; + displayObject.filterArea.height = maxY - minY; +} + +PIXI.FilterTexture = function(width, height) +{ + var gl = PIXI.gl; + + // next time to create a frame buffer and texture + this.frameBuffer = gl.createFramebuffer(); + this.texture = gl.createTexture(); + + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer ); + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer ); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0); + + this.resize(width, height); +} + +PIXI.FilterTexture.prototype.resize = function(width, height) +{ + this.width = width; + this.height = height; + + var gl = PIXI.gl; + + gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * the CanvasRenderer draws the stage and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. + * Dont forget to add the view to your DOM or you will not see anything :) + * + * @class CanvasRenderer + * @constructor + * @param width=0 {Number} the width of the canvas view + * @param height=0 {Number} the height of the canvas view + * @param view {Canvas} the canvas to use as a view, optional + * @param transparent=false {Boolean} the transparency of the render view, default false + */ +PIXI.CanvasRenderer = function(width, height, view, transparent) +{ + this.transparent = transparent; + + /** + * The width of the canvas view + * + * @property width + * @type Number + * @default 800 + */ + this.width = width || 800; + + /** + * The height of the canvas view + * + * @property height + * @type Number + * @default 600 + */ + this.height = height || 600; + + /** + * The canvas element that the everything is drawn to + * + * @property view + * @type Canvas + */ + this.view = view || document.createElement( 'canvas' ); + + /** + * The canvas context that the everything is drawn to + * @property context + * @type Canvas 2d Context + */ + this.context = this.view.getContext("2d"); + + this.refresh = true; + // hack to enable some hardware acceleration! + //this.view.style["transform"] = "translatez(0)"; + + this.view.width = this.width; + this.view.height = this.height; + this.count = 0; +} + +// constructor +PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; + +/** + * Renders the stage to its canvas view + * + * @method render + * @param stage {Stage} the Stage element to be rendered + */ +PIXI.CanvasRenderer.prototype.render = function(stage) +{ + + //stage.__childrenAdded = []; + //stage.__childrenRemoved = []; + + // update textures if need be + PIXI.texturesToUpdate = []; + PIXI.texturesToDestroy = []; + + PIXI.visibleCount++; + stage.updateTransform(); + + // update the background color + if(this.view.style.backgroundColor!=stage.backgroundColorString && !this.transparent)this.view.style.backgroundColor = stage.backgroundColorString; + + this.context.setTransform(1,0,0,1,0,0); + this.context.clearRect(0, 0, this.width, this.height) + this.renderDisplayObject(stage); + //as + + // run interaction! + if(stage.interactive) + { + //need to add some events! + if(!stage._interactiveEventsAdded) + { + stage._interactiveEventsAdded = true; + stage.interactionManager.setTarget(this); + } + } + + // remove frame updates.. + if(PIXI.Texture.frameUpdates.length > 0) + { + PIXI.Texture.frameUpdates = []; + } + + +} + +/** + * resizes the canvas view to the specified width and height + * + * @method resize + * @param width {Number} the new width of the canvas view + * @param height {Number} the new height of the canvas view + */ +PIXI.CanvasRenderer.prototype.resize = function(width, height) +{ + this.width = width; + this.height = height; + + this.view.width = width; + this.view.height = height; +} + +/** + * Renders a display object + * + * @method renderDisplayObject + * @param displayObject {DisplayObject} The displayObject to render + * @private + */ +PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) +{ + // no loger recurrsive! + var transform; + var context = this.context; + + context.globalCompositeOperation = 'source-over'; + + // one the display object hits this. we can break the loop + var testObject = displayObject.last._iNext; + displayObject = displayObject.first; + + do + { + transform = displayObject.worldTransform; + + if(!displayObject.visible) + { + displayObject = displayObject.last._iNext; + continue; + } + + if(!displayObject.renderable) + { + displayObject = displayObject._iNext; + continue; + } + + if(displayObject instanceof PIXI.Sprite) + { + + var frame = displayObject.texture.frame; + + if(frame && frame.width && frame.height) + { + context.globalAlpha = displayObject.worldAlpha; + + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); + + context.drawImage(displayObject.texture.baseTexture.source, + frame.x, + frame.y, + frame.width, + frame.height, + (displayObject.anchor.x) * -frame.width, + (displayObject.anchor.y) * -frame.height, + frame.width, + frame.height); + } + } + else if(displayObject instanceof PIXI.Strip) + { + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) + this.renderStrip(displayObject); + } + else if(displayObject instanceof PIXI.TilingSprite) + { + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) + this.renderTilingSprite(displayObject); + } + else if(displayObject instanceof PIXI.CustomRenderable) + { + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); + displayObject.renderCanvas(this); + } + else if(displayObject instanceof PIXI.Graphics) + { + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) + PIXI.CanvasGraphics.renderGraphics(displayObject, context); + } + else if(displayObject instanceof PIXI.FilterBlock) + { + if(displayObject.data instanceof PIXI.Graphics) + { + var mask = displayObject.data; + + if(displayObject.open) + { + context.save(); + + var cacheAlpha = mask.alpha; + var maskTransform = mask.worldTransform; + + context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) + + mask.worldAlpha = 0.5; + + context.worldAlpha = 0; + + PIXI.CanvasGraphics.renderGraphicsMask(mask, context); + context.clip(); + + mask.worldAlpha = cacheAlpha; + } + else + { + context.restore(); + } + } + else + { + // only masks supported right now! + } + } + // count++ + displayObject = displayObject._iNext; + + + } + while(displayObject != testObject) + + +} + +/** + * Renders a flat strip + * + * @method renderStripFlat + * @param strip {Strip} The Strip to render + * @private + */ +PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip) +{ + var context = this.context; + var verticies = strip.verticies; + var uvs = strip.uvs; + + var length = verticies.length/2; + this.count++; + + context.beginPath(); + for (var i=1; i < length-2; i++) + { + + // draw some triangles! + var index = i*2; + + var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; + var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + + }; + + context.fillStyle = "#FF0000"; + context.fill(); + context.closePath(); +} + +/** + * Renders a tiling sprite + * + * @method renderTilingSprite + * @param sprite {TilingSprite} The tilingsprite to render + * @private + */ +PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) +{ + var context = this.context; + + context.globalAlpha = sprite.worldAlpha; + + if(!sprite.__tilePattern) sprite.__tilePattern = context.createPattern(sprite.texture.baseTexture.source, "repeat"); + + context.beginPath(); + + var tilePosition = sprite.tilePosition; + var tileScale = sprite.tileScale; + + // offset + context.scale(tileScale.x,tileScale.y); + context.translate(tilePosition.x, tilePosition.y); + + context.fillStyle = sprite.__tilePattern; + context.fillRect(-tilePosition.x,-tilePosition.y,sprite.width / tileScale.x, sprite.height / tileScale.y); + + context.scale(1/tileScale.x, 1/tileScale.y); + context.translate(-tilePosition.x, -tilePosition.y); + + context.closePath(); +} + +/** + * Renders a strip + * + * @method renderStrip + * @param strip {Strip} The Strip to render + * @private + */ +PIXI.CanvasRenderer.prototype.renderStrip = function(strip) +{ + var context = this.context; + + // draw triangles!! + var verticies = strip.verticies; + var uvs = strip.uvs; + + var length = verticies.length/2; + this.count++; + for (var i=1; i < length-2; i++) + { + + // draw some triangles! + var index = i*2; + + var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; + var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; + + var u0 = uvs[index] * strip.texture.width, u1 = uvs[index+2] * strip.texture.width, u2 = uvs[index+4]* strip.texture.width; + var v0 = uvs[index+1]* strip.texture.height, v1 = uvs[index+3] * strip.texture.height, v2 = uvs[index+5]* strip.texture.height; + + + 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 delta_a = x0*v1 + v0*x2 + x1*v2 - v1*x2 - v0*x1 - x0*v2; + var delta_b = u0*x1 + x0*u2 + u1*x2 - x1*u2 - x0*u1 - u0*x2; + var delta_c = u0*v1*x2 + v0*x1*u2 + x0*u1*v2 - x0*v1*u2 - v0*u1*x2 - u0*x1*v2; + var delta_d = y0*v1 + v0*y2 + y1*v2 - v1*y2 - v0*y1 - y0*v2; + var delta_e = u0*y1 + y0*u2 + u1*y2 - y1*u2 - y0*u1 - u0*y2; + var delta_f = u0*v1*y2 + v0*y1*u2 + y0*u1*v2 - y0*v1*u2 - v0*u1*y2 - u0*y1*v2; + + + + + context.transform(delta_a/delta, delta_d/delta, + delta_b/delta, delta_e/delta, + delta_c/delta, delta_f/delta); + + context.drawImage(strip.texture.baseTexture.source, 0, 0); + context.restore(); + }; + +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * A set of functions used by the canvas renderer to draw the primitive graphics data + * + * @class CanvasGraphics + */ +PIXI.CanvasGraphics = function() +{ + +} + + +/* + * Renders the graphics object + * + * @static + * @private + * @method renderGraphics + * @param graphics {Graphics} + * @param context {Context2D} + */ +PIXI.CanvasGraphics.renderGraphics = function(graphics, context) +{ + var worldAlpha = graphics.worldAlpha; + + for (var i=0; i < graphics.graphicsData.length; i++) + { + var data = graphics.graphicsData[i]; + var points = data.points; + + context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); + + context.lineWidth = data.lineWidth; + + if(data.type == PIXI.Graphics.POLY) + { + context.beginPath(); + + context.moveTo(points[0], points[1]); + + for (var j=1; j < points.length/2; j++) + { + context.lineTo(points[j * 2], points[j * 2 + 1]); + } + + // if the first and last point are the same close the path - much neater :) + if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) + { + context.closePath(); + } + + if(data.fill) + { + context.globalAlpha = data.fillAlpha * worldAlpha; + context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); + context.fill(); + } + if(data.lineWidth) + { + context.globalAlpha = data.lineAlpha * worldAlpha; + context.stroke(); + } + } + else if(data.type == PIXI.Graphics.RECT) + { + + if(data.fillColor || data.fillColor === 0) + { + context.globalAlpha = data.fillAlpha * worldAlpha; + context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); + context.fillRect(points[0], points[1], points[2], points[3]); + + } + if(data.lineWidth) + { + context.globalAlpha = data.lineAlpha * worldAlpha; + context.strokeRect(points[0], points[1], points[2], points[3]); + } + + } + else if(data.type == PIXI.Graphics.CIRC) + { + // TODO - need to be Undefined! + context.beginPath(); + context.arc(points[0], points[1], points[2],0,2*Math.PI); + context.closePath(); + + if(data.fill) + { + context.globalAlpha = data.fillAlpha * worldAlpha; + context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); + context.fill(); + } + if(data.lineWidth) + { + context.globalAlpha = data.lineAlpha * worldAlpha; + context.stroke(); + } + } + else if(data.type == PIXI.Graphics.ELIP) + { + + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas + + var elipseData = data.points; + + var w = elipseData[2] * 2; + var h = elipseData[3] * 2; + + var x = elipseData[0] - w/2; + var y = elipseData[1] - h/2; + + context.beginPath(); + + var kappa = .5522848, + ox = (w / 2) * kappa, // control point offset horizontal + oy = (h / 2) * kappa, // control point offset vertical + xe = x + w, // x-end + ye = y + h, // y-end + xm = x + w / 2, // x-middle + ym = y + h / 2; // y-middle + + context.moveTo(x, ym); + context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); + context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); + context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); + context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); + + context.closePath(); + + if(data.fill) + { + context.globalAlpha = data.fillAlpha * worldAlpha; + context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); + context.fill(); + } + if(data.lineWidth) + { + context.globalAlpha = data.lineAlpha * worldAlpha; + context.stroke(); + } + } + + }; +} + +/* + * Renders a graphics mask + * + * @static + * @private + * @method renderGraphicsMask + * @param graphics {Graphics} + * @param context {Context2D} + */ +PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) +{ + var worldAlpha = graphics.worldAlpha; + + var len = graphics.graphicsData.length; + if(len === 0)return; + + if(len > 1) + { + len = 1; + console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") + } + + for (var i=0; i < 1; i++) + { + var data = graphics.graphicsData[i]; + var points = data.points; + + if(data.type == PIXI.Graphics.POLY) + { + context.beginPath(); + context.moveTo(points[0], points[1]); + + for (var j=1; j < points.length/2; j++) + { + context.lineTo(points[j * 2], points[j * 2 + 1]); + } + + // if the first and last point are the same close the path - much neater :) + if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) + { + context.closePath(); + } + + } + else if(data.type == PIXI.Graphics.RECT) + { + context.beginPath(); + context.rect(points[0], points[1], points[2], points[3]); + context.closePath(); + } + else if(data.type == PIXI.Graphics.CIRC) + { + // TODO - need to be Undefined! + context.beginPath(); + context.arc(points[0], points[1], points[2],0,2*Math.PI); + context.closePath(); + } + else if(data.type == PIXI.Graphics.ELIP) + { + + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas + var elipseData = data.points; + + var w = elipseData[2] * 2; + var h = elipseData[3] * 2; + + var x = elipseData[0] - w/2; + var y = elipseData[1] - h/2; + + context.beginPath(); + + var kappa = .5522848, + ox = (w / 2) * kappa, // control point offset horizontal + oy = (h / 2) * kappa, // control point offset vertical + xe = x + w, // x-end + ye = y + h, // y-end + xm = x + w / 2, // x-middle + ym = y + h / 2; // y-middle + + context.moveTo(x, ym); + context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); + context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); + context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); + context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); + context.closePath(); + } + + + }; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. + * It is important to know that with the webGL renderer only simple polys can be filled at this stage + * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png + * + * @class Graphics + * @extends DisplayObjectContainer + * @constructor + */ +PIXI.Graphics = function() +{ + PIXI.DisplayObjectContainer.call( this ); + + this.renderable = true; + + /** + * The alpha of the fill of this graphics object + * + * @property fillAlpha + * @type Number + */ + this.fillAlpha = 1; + + /** + * The width of any lines drawn + * + * @property lineWidth + * @type Number + */ + this.lineWidth = 0; + + /** + * The color of any lines drawn + * + * @property lineColor + * @type String + */ + this.lineColor = "black"; + + /** + * Graphics data + * + * @property graphicsData + * @type Array + * @private + */ + this.graphicsData = []; + + /** + * Current path + * + * @property currentPath + * @type Object + * @private + */ + this.currentPath = {points:[]}; +} + +// constructor +PIXI.Graphics.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); +PIXI.Graphics.prototype.constructor = PIXI.Graphics; + +/** + * Specifies a line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method. + * + * @method lineStyle + * @param lineWidth {Number} width of the line to draw, will update the object's stored style + * @param color {Number} color of the line to draw, will update the object's stored style + * @param alpha {Number} alpha of the line to draw, will update the object's stored style + */ +PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) +{ + if(this.currentPath.points.length == 0)this.graphicsData.pop(); + + this.lineWidth = lineWidth || 0; + this.lineColor = color || 0; + this.lineAlpha = (alpha == undefined) ? 1 : alpha; + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; + + this.graphicsData.push(this.currentPath); +} + +/** + * Moves the current drawing position to (x, y). + * + * @method moveTo + * @param x {Number} the X coord to move to + * @param y {Number} the Y coord to move to + */ +PIXI.Graphics.prototype.moveTo = function(x, y) +{ + if(this.currentPath.points.length == 0)this.graphicsData.pop(); + + this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; + + this.currentPath.points.push(x, y); + + this.graphicsData.push(this.currentPath); +} + +/** + * Draws a line using the current line style from the current drawing position to (x, y); + * the current drawing position is then set to (x, y). + * + * @method lineTo + * @param x {Number} the X coord to draw to + * @param y {Number} the Y coord to draw to + */ +PIXI.Graphics.prototype.lineTo = function(x, y) +{ + this.currentPath.points.push(x, y); + this.dirty = true; +} + +/** + * Specifies a simple one-color fill that subsequent calls to other Graphics methods + * (such as lineTo() or drawCircle()) use when drawing. + * + * @method beginFill + * @param color {uint} the color of the fill + * @param alpha {Number} the alpha + */ +PIXI.Graphics.prototype.beginFill = function(color, alpha) +{ + this.filling = true; + this.fillColor = color || 0; + this.fillAlpha = (alpha == undefined) ? 1 : alpha; +} + +/** + * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. + * + * @method endFill + */ +PIXI.Graphics.prototype.endFill = function() +{ + this.filling = false; + this.fillColor = null; + this.fillAlpha = 1; +} + +/** + * @method drawRect + * + * @param x {Number} The X coord of the top-left of the rectangle + * @param y {Number} The Y coord of the top-left of the rectangle + * @param width {Number} The width of the rectangle + * @param height {Number} The height of the rectangle + */ +PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) +{ + if(this.currentPath.points.length == 0)this.graphicsData.pop(); + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + points:[x, y, width, height], type:PIXI.Graphics.RECT}; + + this.graphicsData.push(this.currentPath); + this.dirty = true; +} + +/** + * Draws a circle. + * + * @method drawCircle + * @param x {Number} The X coord of the center of the circle + * @param y {Number} The Y coord of the center of the circle + * @param radius {Number} The radius of the circle + */ +PIXI.Graphics.prototype.drawCircle = function( x, y, radius) +{ + if(this.currentPath.points.length == 0)this.graphicsData.pop(); + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; + + this.graphicsData.push(this.currentPath); + this.dirty = true; +} + +/** + * Draws an elipse. + * + * @method drawElipse + * @param x {Number} + * @param y {Number} + * @param width {Number} + * @param height {Number} + */ +PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) +{ + if(this.currentPath.points.length == 0)this.graphicsData.pop(); + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + points:[x, y, width, height], type:PIXI.Graphics.ELIP}; + + this.graphicsData.push(this.currentPath); + this.dirty = true; +} + +/** + * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. + * + * @method clear + */ +PIXI.Graphics.prototype.clear = function() +{ + this.lineWidth = 0; + this.filling = false; + + this.dirty = true; + this.clearDirty = true; + this.graphicsData = []; + + this.bounds = null//new PIXI.Rectangle(); +} + + +PIXI.Graphics.prototype.updateFilterBounds = function() +{ + if(!this.bounds) + { + var minX = Infinity; + var maxX = -Infinity; + + var minY = Infinity; + var maxY = -Infinity; + + var points, x, y; + + for (var i = 0; i < this.graphicsData.length; i++) { + + + var data = this.graphicsData[i]; + var type = data.type; + var lineWidth = data.lineWidth; + + points = data.points; + + if(type === PIXI.Graphics.RECT) + { + x = points.x - lineWidth/2; + y = points.y - lineWidth/2; + var width = points.width + lineWidth; + var height = points.height + lineWidth; + + minX = x < minX ? x : minX; + maxX = x + width > maxX ? x + width : maxX; + + minY = y < minY ? x : minY; + maxY = y + height > maxY ? y + height : maxY; + } + else if(type === PIXI.Graphics.CIRC || type === PIXI.Graphics.ELIP) + { + x = points.x; + y = points.y; + var radius = points.radius + lineWidth/2; + + minX = x - radius < minX ? x - radius : minX; + maxX = x + radius > maxX ? x + radius : maxX; + + minY = y - radius < minY ? y - radius : minY; + maxY = y + radius > maxY ? y + radius : maxY; + } + else + { + // POLY + for (var j = 0; j < points.length; j+=2) + { + + x = points[j]; + y = points[j+1]; + + minX = x-lineWidth < minX ? x-lineWidth : minX; + maxX = x+lineWidth > maxX ? x+lineWidth : maxX; + + minY = y-lineWidth < minY ? y-lineWidth : minY; + maxY = y+lineWidth > maxY ? y+lineWidth : maxY; + }; + } + + }; + + this.bounds = new PIXI.Rectangle(minX, minY, maxX - minX, maxY - minY); + + } + +// console.log(this.bounds); +} + +// SOME TYPES: +PIXI.Graphics.POLY = 0; +PIXI.Graphics.RECT = 1; +PIXI.Graphics.CIRC = 2; +PIXI.Graphics.ELIP = 3; + +/** + * @author Mat Groves http://matgroves.com/ + */ + +PIXI.Strip = function(texture, width, height) +{ + PIXI.DisplayObjectContainer.call( this ); + this.texture = texture; + this.blendMode = PIXI.blendModes.NORMAL; + + try + { + this.uvs = new Float32Array([0, 1, + 1, 1, + 1, 0, 0,1]); + + this.verticies = new Float32Array([0, 0, + 0,0, + 0,0, 0, + 0, 0]); + + this.colors = new Float32Array([1, 1, 1, 1]); + + this.indices = new Uint16Array([0, 1, 2, 3]); + } + catch(error) + { + this.uvs = [0, 1, + 1, 1, + 1, 0, 0,1]; + + this.verticies = [0, 0, + 0,0, + 0,0, 0, + 0, 0]; + + this.colors = [1, 1, 1, 1]; + + this.indices = [0, 1, 2, 3]; + } + + + /* + this.uvs = new Float32Array() + this.verticies = new Float32Array() + this.colors = new Float32Array() + this.indices = new Uint16Array() +*/ + this.width = width; + this.height = height; + + // load the texture! + if(texture.baseTexture.hasLoaded) + { + this.width = this.texture.frame.width; + this.height = this.texture.frame.height; + this.updateFrame = true; + } + else + { + this.onTextureUpdateBind = this.onTextureUpdate.bind(this); + this.texture.addEventListener( 'update', this.onTextureUpdateBind ); + } + + this.renderable = true; +} + +// constructor +PIXI.Strip.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); +PIXI.Strip.prototype.constructor = PIXI.Strip; + +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; +} + +PIXI.Strip.prototype.onTextureUpdate = function(event) +{ + this.updateFrame = true; +} +// some helper functions.. + + +/** + * @author Mat Groves http://matgroves.com/ + */ + + +PIXI.Rope = function(texture, points) +{ + PIXI.Strip.call( this, texture ); + this.points = points; + + try + { + this.verticies = new Float32Array( points.length * 4); + this.uvs = new Float32Array( points.length * 4); + this.colors = new Float32Array( points.length * 2); + this.indices = new Uint16Array( points.length * 2); + } + catch(error) + { + this.verticies = verticies + + this.uvs = uvs + this.colors = colors + this.indices = indices + } + + this.refresh(); +} + + +// constructor +PIXI.Rope.prototype = Object.create( PIXI.Strip.prototype ); +PIXI.Rope.prototype.constructor = PIXI.Rope; + +PIXI.Rope.prototype.refresh = function() +{ + var points = this.points; + if(points.length < 1)return; + + var uvs = this.uvs + var indices = this.indices; + var colors = this.colors; + + var lastPoint = points[0]; + var nextPoint; + var perp = {x:0, y:0}; + var point = points[0]; + + this.count-=0.2; + + + uvs[0] = 0 + uvs[1] = 1 + uvs[2] = 0 + uvs[3] = 1 + + colors[0] = 1; + colors[1] = 1; + + indices[0] = 0; + indices[1] = 1; + + var total = points.length; + + for (var i = 1; i < total; i++) + { + + var point = points[i]; + var index = i * 4; + // time to do some smart drawing! + var 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; + } +} + +PIXI.Rope.prototype.updateTransform = function() +{ + + var points = this.points; + if(points.length < 1)return; + + var verticies = this.verticies + + var lastPoint = points[0]; + var nextPoint; + var perp = {x:0, y:0}; + var point = points[0]; + + this.count-=0.2; + + verticies[0] = point.x + perp.x + verticies[1] = point.y + perp.y //+ 200 + verticies[2] = point.x - perp.x + verticies[3] = point.y - perp.y//+200 + // time to do some smart drawing! + + var total = points.length; + + for (var i = 1; i < total; i++) + { + + var point = points[i]; + var 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; + + var ratio = (1 - (i / (total-1))) * 10; + if(ratio > 1)ratio = 1; + + var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); + var 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; + + verticies[index] = point.x + perp.x + verticies[index+1] = point.y + perp.y + verticies[index+2] = point.x - perp.x + verticies[index+3] = point.y - perp.y + + lastPoint = point; + } + + PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); +} + +PIXI.Rope.prototype.setTexture = function(texture) +{ + // stop current texture + this.texture = texture; + this.updateFrame = true; +} + + + + + +/** + * @author Mat Groves http://matgroves.com/ + */ + +/** + * A tiling sprite is a fast way of rendering a tiling image + * + * @class TilingSprite + * @extends DisplayObjectContainer + * @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.DisplayObjectContainer.call( this ); + + /** + * The texture that the sprite is using + * + * @property texture + * @type Texture + */ + this.texture = texture; + + /** + * The width of the tiling sprite + * + * @property width + * @type Number + */ + this.width = width; + + /** + * The height of the tiling sprite + * + * @property height + * @type Number + */ + this.height = height; + + /** + * The scaling of the image that is being tiled + * + * @property tileScale + * @type Point + */ + this.tileScale = 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); + + this.renderable = true; + + this.blendMode = PIXI.blendModes.NORMAL +} + +// constructor +PIXI.TilingSprite.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); +PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite; + +/** + * Sets the texture of the tiling sprite + * + * @method setTexture + * @param texture {Texture} The PIXI texture that is displayed by the sprite + */ +PIXI.TilingSprite.prototype.setTexture = function(texture) +{ + //TODO SET THE TEXTURES + //TODO VISIBILITY + + // stop current texture + this.texture = texture; + this.updateFrame = true; +} + +/** + * When the texture is updated, this event will fire to update the frame + * + * @method onTextureUpdate + * @param event + * @private + */ +PIXI.TilingSprite.prototype.onTextureUpdate = function(event) +{ + this.updateFrame = true; +} + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi + * + * Awesome JS run time provided by EsotericSoftware + * https://github.com/EsotericSoftware/spine-runtimes + * + */ + +/** + * 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)) { + continue; + } + var spriteName = attachment.rendererObject.name; + var sprite = this.createSprite(slot, attachment.rendererObject); + slot.currentSprite = sprite; + slot.currentSpriteName = spriteName; + slotContainer.addChild(sprite); + } +}; + +PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); +PIXI.Spine.prototype.constructor = PIXI.Spine; + +/* + * Updates the object transform for rendering + * + * @method updateTransform + * @private + */ +PIXI.Spine.prototype.updateTransform = function () { + this.lastTime = this.lastTime || Date.now(); + var timeDelta = (Date.now() - this.lastTime) * 0.001; + this.lastTime = Date.now(); + this.state.update(timeDelta); + 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 instanceof spine.RegionAttachment)) { + slotContainer.visible = false; + continue; + } + + 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.rendererObject); + slotContainer.addChild(sprite); + } + slot.currentSprite = slot.sprites[spriteName]; + slot.currentSpriteName = spriteName; + } + } + slotContainer.visible = true; + + 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 * Math.PI / 180); + } + + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); +}; + + +PIXI.Spine.prototype.createSprite = function (slot, descriptor) { + var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; + var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); + sprite.scale = descriptor.scale; + sprite.rotation = descriptor.rotation; + sprite.anchor.x = sprite.anchor.y = 0.5; + + slot.sprites = slot.sprites || {}; + slot.sprites[descriptor.name] = sprite; + return sprite; +}; + +/* + * Awesome JS run time provided by EsotericSoftware + * + * https://github.com/EsotericSoftware/spine-runtimes + * + */ + +var spine = {}; + +spine.BoneData = function (name, parent) { + this.name = name; + this.parent = parent; +}; +spine.BoneData.prototype = { + length: 0, + x: 0, y: 0, + rotation: 0, + scaleX: 1, scaleY: 1 +}; + +spine.SlotData = function (name, boneData) { + this.name = name; + this.boneData = boneData; +}; +spine.SlotData.prototype = { + r: 1, g: 1, b: 1, a: 1, + attachmentName: null +}; + +spine.Bone = function (boneData, parent) { + this.data = boneData; + this.parent = parent; + this.setToSetupPose(); +}; +spine.Bone.yDown = false; +spine.Bone.prototype = { + x: 0, y: 0, + rotation: 0, + scaleX: 1, scaleY: 1, + m00: 0, m01: 0, worldX: 0, // a b x + m10: 0, m11: 0, worldY: 0, // c d y + worldRotation: 0, + worldScaleX: 1, worldScaleY: 1, + updateWorldTransform: function (flipX, flipY) { + var parent = this.parent; + if (parent != null) { + this.worldX = this.x * parent.m00 + this.y * parent.m01 + parent.worldX; + this.worldY = this.x * parent.m10 + this.y * parent.m11 + parent.worldY; + this.worldScaleX = parent.worldScaleX * this.scaleX; + this.worldScaleY = parent.worldScaleY * this.scaleY; + this.worldRotation = parent.worldRotation + this.rotation; + } else { + this.worldX = this.x; + this.worldY = this.y; + this.worldScaleX = this.scaleX; + this.worldScaleY = this.scaleY; + this.worldRotation = this.rotation; + } + var radians = this.worldRotation * Math.PI / 180; + var cos = Math.cos(radians); + var sin = Math.sin(radians); + this.m00 = cos * this.worldScaleX; + this.m10 = sin * this.worldScaleX; + this.m01 = -sin * this.worldScaleY; + this.m11 = cos * this.worldScaleY; + if (flipX) { + this.m00 = -this.m00; + this.m01 = -this.m01; + } + if (flipY) { + this.m10 = -this.m10; + this.m11 = -this.m11; + } + if (spine.Bone.yDown) { + this.m10 = -this.m10; + this.m11 = -this.m11; + } + }, + setToSetupPose: function () { + var data = this.data; + this.x = data.x; + this.y = data.y; + this.rotation = data.rotation; + this.scaleX = data.scaleX; + this.scaleY = data.scaleY; + } +}; + +spine.Slot = function (slotData, skeleton, bone) { + this.data = slotData; + this.skeleton = skeleton; + this.bone = bone; + this.setToSetupPose(); +}; +spine.Slot.prototype = { + r: 1, g: 1, b: 1, a: 1, + _attachmentTime: 0, + attachment: null, + setAttachment: function (attachment) { + this.attachment = attachment; + this._attachmentTime = this.skeleton.time; + }, + setAttachmentTime: function (time) { + this._attachmentTime = this.skeleton.time - time; + }, + getAttachmentTime: function () { + return this.skeleton.time - this._attachmentTime; + }, + setToSetupPose: function () { + var data = this.data; + this.r = data.r; + this.g = data.g; + this.b = data.b; + this.a = data.a; + + var slotDatas = this.skeleton.data.slots; + for (var i = 0, n = slotDatas.length; i < n; i++) { + if (slotDatas[i] == data) { + this.setAttachment(!data.attachmentName ? null : this.skeleton.getAttachmentBySlotIndex(i, data.attachmentName)); + break; + } + } + } +}; + +spine.Skin = function (name) { + this.name = name; + this.attachments = {}; +}; +spine.Skin.prototype = { + addAttachment: function (slotIndex, name, attachment) { + this.attachments[slotIndex + ":" + name] = attachment; + }, + getAttachment: function (slotIndex, name) { + return this.attachments[slotIndex + ":" + name]; + }, + _attachAll: function (skeleton, oldSkin) { + for (var key in oldSkin.attachments) { + var colon = key.indexOf(":"); + var slotIndex = parseInt(key.substring(0, colon)); + var name = key.substring(colon + 1); + var slot = skeleton.slots[slotIndex]; + if (slot.attachment && slot.attachment.name == name) { + var attachment = this.getAttachment(slotIndex, name); + if (attachment) slot.setAttachment(attachment); + } + } + } +}; + +spine.Animation = function (name, timelines, duration) { + this.name = name; + this.timelines = timelines; + this.duration = duration; +}; +spine.Animation.prototype = { + apply: function (skeleton, time, loop) { + if (loop && this.duration != 0) time %= this.duration; + var timelines = this.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, time, 1); + }, + mix: function (skeleton, time, loop, alpha) { + if (loop && this.duration != 0) time %= this.duration; + var timelines = this.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, time, alpha); + } +}; + +spine.binarySearch = function (values, target, step) { + var low = 0; + var high = Math.floor(values.length / step) - 2; + if (high == 0) return step; + var current = high >>> 1; + while (true) { + if (values[(current + 1) * step] <= target) + low = current + 1; + else + high = current; + if (low == high) return (low + 1) * step; + current = (low + high) >>> 1; + } +}; +spine.linearSearch = function (values, target, step) { + for (var i = 0, last = values.length - step; i <= last; i += step) + if (values[i] > target) return i; + return -1; +}; + +spine.Curves = function (frameCount) { + this.curves = []; // dfx, dfy, ddfx, ddfy, dddfx, dddfy, ... + this.curves.length = (frameCount - 1) * 6; +}; +spine.Curves.prototype = { + setLinear: function (frameIndex) { + this.curves[frameIndex * 6] = 0/*LINEAR*/; + }, + setStepped: function (frameIndex) { + this.curves[frameIndex * 6] = -1/*STEPPED*/; + }, + /** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next. + * cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of + * the difference between the keyframe's values. */ + setCurve: function (frameIndex, cx1, cy1, cx2, cy2) { + var subdiv_step = 1 / 10/*BEZIER_SEGMENTS*/; + var subdiv_step2 = subdiv_step * subdiv_step; + var subdiv_step3 = subdiv_step2 * subdiv_step; + var pre1 = 3 * subdiv_step; + var pre2 = 3 * subdiv_step2; + var pre4 = 6 * subdiv_step2; + var pre5 = 6 * subdiv_step3; + var tmp1x = -cx1 * 2 + cx2; + var tmp1y = -cy1 * 2 + cy2; + var tmp2x = (cx1 - cx2) * 3 + 1; + var tmp2y = (cy1 - cy2) * 3 + 1; + var i = frameIndex * 6; + var curves = this.curves; + curves[i] = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; + curves[i + 1] = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; + curves[i + 2] = tmp1x * pre4 + tmp2x * pre5; + curves[i + 3] = tmp1y * pre4 + tmp2y * pre5; + curves[i + 4] = tmp2x * pre5; + curves[i + 5] = tmp2y * pre5; + }, + getCurvePercent: function (frameIndex, percent) { + percent = percent < 0 ? 0 : (percent > 1 ? 1 : percent); + var curveIndex = frameIndex * 6; + var curves = this.curves; + var dfx = curves[curveIndex]; + if (!dfx/*LINEAR*/) return percent; + if (dfx == -1/*STEPPED*/) return 0; + var dfy = curves[curveIndex + 1]; + var ddfx = curves[curveIndex + 2]; + var ddfy = curves[curveIndex + 3]; + var dddfx = curves[curveIndex + 4]; + var dddfy = curves[curveIndex + 5]; + var x = dfx, y = dfy; + var i = 10/*BEZIER_SEGMENTS*/ - 2; + while (true) { + if (x >= percent) { + var lastX = x - dfx; + var lastY = y - dfy; + return lastY + (y - lastY) * (percent - lastX) / (x - lastX); + } + if (i == 0) break; + i--; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + x += dfx; + y += dfy; + } + return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1. + } +}; + +spine.RotateTimeline = function (frameCount) { + this.curves = new spine.Curves(frameCount); + this.frames = []; // time, angle, ... + this.frames.length = frameCount * 2; +}; +spine.RotateTimeline.prototype = { + boneIndex: 0, + getFrameCount: function () { + return this.frames.length / 2; + }, + setFrame: function (frameIndex, time, angle) { + frameIndex *= 2; + this.frames[frameIndex] = time; + this.frames[frameIndex + 1] = angle; + }, + apply: function (skeleton, time, alpha) { + var frames = this.frames; + if (time < frames[0]) return; // Time is before first frame. + + var bone = skeleton.bones[this.boneIndex]; + + if (time >= frames[frames.length - 2]) { // Time is after last frame. + var amount = bone.data.rotation + frames[frames.length - 1] - bone.rotation; + while (amount > 180) + amount -= 360; + while (amount < -180) + amount += 360; + bone.rotation += amount * alpha; + return; + } + + // Interpolate between the last frame and the current frame. + var frameIndex = spine.binarySearch(frames, time, 2); + var lastFrameValue = frames[frameIndex - 1]; + var frameTime = frames[frameIndex]; + var percent = 1 - (time - frameTime) / (frames[frameIndex - 2/*LAST_FRAME_TIME*/] - frameTime); + percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent); + + var amount = frames[frameIndex + 1/*FRAME_VALUE*/] - lastFrameValue; + while (amount > 180) + amount -= 360; + while (amount < -180) + amount += 360; + amount = bone.data.rotation + (lastFrameValue + amount * percent) - bone.rotation; + while (amount > 180) + amount -= 360; + while (amount < -180) + amount += 360; + bone.rotation += amount * alpha; + } +}; + +spine.TranslateTimeline = function (frameCount) { + this.curves = new spine.Curves(frameCount); + this.frames = []; // time, x, y, ... + this.frames.length = frameCount * 3; +}; +spine.TranslateTimeline.prototype = { + boneIndex: 0, + getFrameCount: function () { + return this.frames.length / 3; + }, + setFrame: function (frameIndex, time, x, y) { + frameIndex *= 3; + this.frames[frameIndex] = time; + this.frames[frameIndex + 1] = x; + this.frames[frameIndex + 2] = y; + }, + apply: function (skeleton, time, alpha) { + var frames = this.frames; + if (time < frames[0]) return; // Time is before first frame. + + var bone = skeleton.bones[this.boneIndex]; + + if (time >= frames[frames.length - 3]) { // Time is after last frame. + bone.x += (bone.data.x + frames[frames.length - 2] - bone.x) * alpha; + bone.y += (bone.data.y + frames[frames.length - 1] - bone.y) * alpha; + return; + } + + // Interpolate between the last frame and the current frame. + var frameIndex = spine.binarySearch(frames, time, 3); + var lastFrameX = frames[frameIndex - 2]; + var lastFrameY = frames[frameIndex - 1]; + var frameTime = frames[frameIndex]; + var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); + percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); + + bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; + bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; + } +}; + +spine.ScaleTimeline = function (frameCount) { + this.curves = new spine.Curves(frameCount); + this.frames = []; // time, x, y, ... + this.frames.length = frameCount * 3; +}; +spine.ScaleTimeline.prototype = { + boneIndex: 0, + getFrameCount: function () { + return this.frames.length / 3; + }, + setFrame: function (frameIndex, time, x, y) { + frameIndex *= 3; + this.frames[frameIndex] = time; + this.frames[frameIndex + 1] = x; + this.frames[frameIndex + 2] = y; + }, + apply: function (skeleton, time, alpha) { + var frames = this.frames; + if (time < frames[0]) return; // Time is before first frame. + + var bone = skeleton.bones[this.boneIndex]; + + if (time >= frames[frames.length - 3]) { // Time is after last frame. + bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; + return; + } + + // Interpolate between the last frame and the current frame. + var frameIndex = spine.binarySearch(frames, time, 3); + var lastFrameX = frames[frameIndex - 2]; + var lastFrameY = frames[frameIndex - 1]; + var frameTime = frames[frameIndex]; + var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); + percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); + + bone.scaleX += (bone.data.scaleX - 1 + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - 1 + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.scaleY) * alpha; + } +}; + +spine.ColorTimeline = function (frameCount) { + this.curves = new spine.Curves(frameCount); + this.frames = []; // time, r, g, b, a, ... + this.frames.length = frameCount * 5; +}; +spine.ColorTimeline.prototype = { + slotIndex: 0, + getFrameCount: function () { + return this.frames.length / 2; + }, + setFrame: function (frameIndex, time, x, y) { + frameIndex *= 5; + this.frames[frameIndex] = time; + this.frames[frameIndex + 1] = r; + this.frames[frameIndex + 2] = g; + this.frames[frameIndex + 3] = b; + this.frames[frameIndex + 4] = a; + }, + apply: function (skeleton, time, alpha) { + var frames = this.frames; + if (time < frames[0]) return; // Time is before first frame. + + var slot = skeleton.slots[this.slotIndex]; + + if (time >= frames[frames.length - 5]) { // Time is after last frame. + var i = frames.length - 1; + slot.r = frames[i - 3]; + slot.g = frames[i - 2]; + slot.b = frames[i - 1]; + slot.a = frames[i]; + return; + } + + // Interpolate between the last frame and the current frame. + var frameIndex = spine.binarySearch(frames, time, 5); + var lastFrameR = frames[frameIndex - 4]; + var lastFrameG = frames[frameIndex - 3]; + var lastFrameB = frames[frameIndex - 2]; + var lastFrameA = frames[frameIndex - 1]; + var frameTime = frames[frameIndex]; + var percent = 1 - (time - frameTime) / (frames[frameIndex - 5/*LAST_FRAME_TIME*/] - frameTime); + percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent); + + var r = lastFrameR + (frames[frameIndex + 1/*FRAME_R*/] - lastFrameR) * percent; + var g = lastFrameG + (frames[frameIndex + 2/*FRAME_G*/] - lastFrameG) * percent; + var b = lastFrameB + (frames[frameIndex + 3/*FRAME_B*/] - lastFrameB) * percent; + var a = lastFrameA + (frames[frameIndex + 4/*FRAME_A*/] - lastFrameA) * percent; + if (alpha < 1) { + slot.r += (r - slot.r) * alpha; + slot.g += (g - slot.g) * alpha; + slot.b += (b - slot.b) * alpha; + slot.a += (a - slot.a) * alpha; + } else { + slot.r = r; + slot.g = g; + slot.b = b; + slot.a = a; + } + } +}; + +spine.AttachmentTimeline = function (frameCount) { + this.curves = new spine.Curves(frameCount); + this.frames = []; // time, ... + this.frames.length = frameCount; + this.attachmentNames = []; // time, ... + this.attachmentNames.length = frameCount; +}; +spine.AttachmentTimeline.prototype = { + slotIndex: 0, + getFrameCount: function () { + return this.frames.length; + }, + setFrame: function (frameIndex, time, attachmentName) { + this.frames[frameIndex] = time; + this.attachmentNames[frameIndex] = attachmentName; + }, + apply: function (skeleton, time, alpha) { + var frames = this.frames; + if (time < frames[0]) return; // Time is before first frame. + + var frameIndex; + if (time >= frames[frames.length - 1]) // Time is after last frame. + frameIndex = frames.length - 1; + else + frameIndex = spine.binarySearch(frames, time, 1) - 1; + + var attachmentName = this.attachmentNames[frameIndex]; + skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); + } +}; + +spine.SkeletonData = function () { + this.bones = []; + this.slots = []; + this.skins = []; + this.animations = []; +}; +spine.SkeletonData.prototype = { + defaultSkin: null, + /** @return May be null. */ + findBone: function (boneName) { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].name == boneName) return bones[i]; + return null; + }, + /** @return -1 if the bone was not found. */ + findBoneIndex: function (boneName) { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].name == boneName) return i; + return -1; + }, + /** @return May be null. */ + findSlot: function (slotName) { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + if (slots[i].name == slotName) return slot[i]; + } + return null; + }, + /** @return -1 if the bone was not found. */ + findSlotIndex: function (slotName) { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].name == slotName) return i; + return -1; + }, + /** @return May be null. */ + findSkin: function (skinName) { + var skins = this.skins; + for (var i = 0, n = skins.length; i < n; i++) + if (skins[i].name == skinName) return skins[i]; + return null; + }, + /** @return May be null. */ + findAnimation: function (animationName) { + var animations = this.animations; + for (var i = 0, n = animations.length; i < n; i++) + if (animations[i].name == animationName) return animations[i]; + return null; + } +}; + +spine.Skeleton = function (skeletonData) { + this.data = skeletonData; + + this.bones = []; + for (var i = 0, n = skeletonData.bones.length; i < n; i++) { + var boneData = skeletonData.bones[i]; + var parent = !boneData.parent ? null : this.bones[skeletonData.bones.indexOf(boneData.parent)]; + this.bones.push(new spine.Bone(boneData, parent)); + } + + this.slots = []; + this.drawOrder = []; + for (var i = 0, n = skeletonData.slots.length; i < n; i++) { + var slotData = skeletonData.slots[i]; + var bone = this.bones[skeletonData.bones.indexOf(slotData.boneData)]; + var slot = new spine.Slot(slotData, this, bone); + this.slots.push(slot); + this.drawOrder.push(slot); + } +}; +spine.Skeleton.prototype = { + x: 0, y: 0, + skin: null, + r: 1, g: 1, b: 1, a: 1, + time: 0, + flipX: false, flipY: false, + /** Updates the world transform for each bone. */ + updateWorldTransform: function () { + var flipX = this.flipX; + var flipY = this.flipY; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + bones[i].updateWorldTransform(flipX, flipY); + }, + /** Sets the bones and slots to their setup pose values. */ + setToSetupPose: function () { + this.setBonesToSetupPose(); + this.setSlotsToSetupPose(); + }, + setBonesToSetupPose: function () { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + bones[i].setToSetupPose(); + }, + setSlotsToSetupPose: function () { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + slots[i].setToSetupPose(i); + }, + /** @return May return null. */ + getRootBone: function () { + return this.bones.length == 0 ? null : this.bones[0]; + }, + /** @return May be null. */ + findBone: function (boneName) { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].data.name == boneName) return bones[i]; + return null; + }, + /** @return -1 if the bone was not found. */ + findBoneIndex: function (boneName) { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].data.name == boneName) return i; + return -1; + }, + /** @return May be null. */ + findSlot: function (slotName) { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].data.name == slotName) return slots[i]; + return null; + }, + /** @return -1 if the bone was not found. */ + findSlotIndex: function (slotName) { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].data.name == slotName) return i; + return -1; + }, + setSkinByName: function (skinName) { + var skin = this.data.findSkin(skinName); + if (!skin) throw "Skin not found: " + skinName; + this.setSkin(skin); + }, + /** Sets the skin used to look up attachments not found in the {@link SkeletonData#getDefaultSkin() default skin}. Attachments + * from the new skin are attached if the corresponding attachment from the old skin was attached. + * @param newSkin May be null. */ + setSkin: function (newSkin) { + if (this.skin && newSkin) newSkin._attachAll(this, this.skin); + this.skin = newSkin; + }, + /** @return May be null. */ + getAttachmentBySlotName: function (slotName, attachmentName) { + return this.getAttachmentBySlotIndex(this.data.findSlotIndex(slotName), attachmentName); + }, + /** @return May be null. */ + getAttachmentBySlotIndex: function (slotIndex, attachmentName) { + if (this.skin) { + var attachment = this.skin.getAttachment(slotIndex, attachmentName); + if (attachment) return attachment; + } + if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); + return null; + }, + /** @param attachmentName May be null. */ + setAttachment: function (slotName, attachmentName) { + var slots = this.slots; + for (var i = 0, n = slots.size; i < n; i++) { + var slot = slots[i]; + if (slot.data.name == slotName) { + var attachment = null; + if (attachmentName) { + attachment = this.getAttachment(i, attachmentName); + if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; + } + slot.setAttachment(attachment); + return; + } + } + throw "Slot not found: " + slotName; + }, + update: function (delta) { + time += delta; + } +}; + +spine.AttachmentType = { + region: 0 +}; + +spine.RegionAttachment = function () { + this.offset = []; + this.offset.length = 8; + this.uvs = []; + this.uvs.length = 8; +}; +spine.RegionAttachment.prototype = { + x: 0, y: 0, + rotation: 0, + scaleX: 1, scaleY: 1, + width: 0, height: 0, + rendererObject: null, + regionOffsetX: 0, regionOffsetY: 0, + regionWidth: 0, regionHeight: 0, + regionOriginalWidth: 0, regionOriginalHeight: 0, + setUVs: function (u, v, u2, v2, rotate) { + var uvs = this.uvs; + if (rotate) { + uvs[2/*X2*/] = u; + uvs[3/*Y2*/] = v2; + uvs[4/*X3*/] = u; + uvs[5/*Y3*/] = v; + uvs[6/*X4*/] = u2; + uvs[7/*Y4*/] = v; + uvs[0/*X1*/] = u2; + uvs[1/*Y1*/] = v2; + } else { + uvs[0/*X1*/] = u; + uvs[1/*Y1*/] = v2; + uvs[2/*X2*/] = u; + uvs[3/*Y2*/] = v; + uvs[4/*X3*/] = u2; + uvs[5/*Y3*/] = v; + uvs[6/*X4*/] = u2; + uvs[7/*Y4*/] = v2; + } + }, + updateOffset: function () { + var regionScaleX = this.width / this.regionOriginalWidth * this.scaleX; + var regionScaleY = this.height / this.regionOriginalHeight * this.scaleY; + var localX = -this.width / 2 * this.scaleX + this.regionOffsetX * regionScaleX; + var localY = -this.height / 2 * this.scaleY + this.regionOffsetY * regionScaleY; + var localX2 = localX + this.regionWidth * regionScaleX; + var localY2 = localY + this.regionHeight * regionScaleY; + var radians = this.rotation * Math.PI / 180; + var cos = Math.cos(radians); + var sin = Math.sin(radians); + var localXCos = localX * cos + this.x; + var localXSin = localX * sin; + var localYCos = localY * cos + this.y; + var localYSin = localY * sin; + var localX2Cos = localX2 * cos + this.x; + var localX2Sin = localX2 * sin; + var localY2Cos = localY2 * cos + this.y; + var localY2Sin = localY2 * sin; + var offset = this.offset; + offset[0/*X1*/] = localXCos - localYSin; + offset[1/*Y1*/] = localYCos + localXSin; + offset[2/*X2*/] = localXCos - localY2Sin; + offset[3/*Y2*/] = localY2Cos + localXSin; + offset[4/*X3*/] = localX2Cos - localY2Sin; + offset[5/*Y3*/] = localY2Cos + localX2Sin; + offset[6/*X4*/] = localX2Cos - localYSin; + offset[7/*Y4*/] = localYCos + localX2Sin; + }, + computeVertices: function (x, y, bone, vertices) { + x += bone.worldX; + y += bone.worldY; + var m00 = bone.m00; + var m01 = bone.m01; + var m10 = bone.m10; + var m11 = bone.m11; + var offset = this.offset; + vertices[0/*X1*/] = offset[0/*X1*/] * m00 + offset[1/*Y1*/] * m01 + x; + vertices[1/*Y1*/] = offset[0/*X1*/] * m10 + offset[1/*Y1*/] * m11 + y; + vertices[2/*X2*/] = offset[2/*X2*/] * m00 + offset[3/*Y2*/] * m01 + x; + vertices[3/*Y2*/] = offset[2/*X2*/] * m10 + offset[3/*Y2*/] * m11 + y; + vertices[4/*X3*/] = offset[4/*X3*/] * m00 + offset[5/*X3*/] * m01 + x; + vertices[5/*X3*/] = offset[4/*X3*/] * m10 + offset[5/*X3*/] * m11 + y; + vertices[6/*X4*/] = offset[6/*X4*/] * m00 + offset[7/*Y4*/] * m01 + x; + vertices[7/*Y4*/] = offset[6/*X4*/] * m10 + offset[7/*Y4*/] * m11 + y; + } +} + +spine.AnimationStateData = function (skeletonData) { + this.skeletonData = skeletonData; + this.animationToMixTime = {}; +}; +spine.AnimationStateData.prototype = { + defaultMix: 0, + setMixByName: function (fromName, toName, duration) { + var from = this.skeletonData.findAnimation(fromName); + if (!from) throw "Animation not found: " + fromName; + var to = this.skeletonData.findAnimation(toName); + if (!to) throw "Animation not found: " + toName; + this.setMix(from, to, duration); + }, + setMix: function (from, to, duration) { + this.animationToMixTime[from.name + ":" + to.name] = duration; + }, + getMix: function (from, to) { + var time = this.animationToMixTime[from.name + ":" + to.name]; + return time ? time : this.defaultMix; + } +}; + +spine.AnimationState = function (stateData) { + this.data = stateData; + this.queue = []; +}; +spine.AnimationState.prototype = { + current: null, + previous: null, + currentTime: 0, + previousTime: 0, + currentLoop: false, + previousLoop: false, + mixTime: 0, + mixDuration: 0, + update: function (delta) { + this.currentTime += delta; + this.previousTime += delta; + this.mixTime += delta; + + if (this.queue.length > 0) { + var entry = this.queue[0]; + if (this.currentTime >= entry.delay) { + this._setAnimation(entry.animation, entry.loop); + this.queue.shift(); + } + } + }, + apply: function (skeleton) { + if (!this.current) return; + if (this.previous) { + this.previous.apply(skeleton, this.previousTime, this.previousLoop); + var alpha = this.mixTime / this.mixDuration; + if (alpha >= 1) { + alpha = 1; + this.previous = null; + } + this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); + } else + this.current.apply(skeleton, this.currentTime, this.currentLoop); + }, + clearAnimation: function () { + this.previous = null; + this.current = null; + this.queue.length = 0; + }, + _setAnimation: function (animation, loop) { + this.previous = null; + if (animation && this.current) { + this.mixDuration = this.data.getMix(this.current, animation); + if (this.mixDuration > 0) { + this.mixTime = 0; + this.previous = this.current; + this.previousTime = this.currentTime; + this.previousLoop = this.currentLoop; + } + } + this.current = animation; + this.currentLoop = loop; + this.currentTime = 0; + }, + /** @see #setAnimation(Animation, Boolean) */ + setAnimationByName: function (animationName, loop) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) throw "Animation not found: " + animationName; + this.setAnimation(animation, loop); + }, + /** Set the current animation. Any queued animations are cleared and the current animation time is set to 0. + * @param animation May be null. */ + setAnimation: function (animation, loop) { + this.queue.length = 0; + this._setAnimation(animation, loop); + }, + /** @see #addAnimation(Animation, Boolean, Number) */ + addAnimationByName: function (animationName, loop, delay) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) throw "Animation not found: " + animationName; + this.addAnimation(animation, loop, delay); + }, + /** Adds an animation to be played delay seconds after the current or last queued animation. + * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */ + addAnimation: function (animation, loop, delay) { + var entry = {}; + entry.animation = animation; + entry.loop = loop; + + if (!delay || delay <= 0) { + var previousAnimation = this.queue.length == 0 ? this.current : this.queue[this.queue.length - 1].animation; + if (previousAnimation != null) + delay = previousAnimation.duration - this.data.getMix(previousAnimation, animation) + (delay || 0); + else + delay = 0; + } + entry.delay = delay; + + this.queue.push(entry); + }, + /** Returns true if no animation is set or if the current time is greater than the animation duration, regardless of looping. */ + isComplete: function () { + return !this.current || this.currentTime >= this.current.duration; + } +}; + +spine.SkeletonJson = function (attachmentLoader) { + this.attachmentLoader = attachmentLoader; +}; +spine.SkeletonJson.prototype = { + scale: 1, + readSkeletonData: function (root) { + var skeletonData = new spine.SkeletonData(); + + // Bones. + var bones = root["bones"]; + for (var i = 0, n = bones.length; i < n; i++) { + var boneMap = bones[i]; + var parent = null; + if (boneMap["parent"]) { + parent = skeletonData.findBone(boneMap["parent"]); + if (!parent) throw "Parent bone not found: " + boneMap["parent"]; + } + var boneData = new spine.BoneData(boneMap["name"], parent); + boneData.length = (boneMap["length"] || 0) * this.scale; + boneData.x = (boneMap["x"] || 0) * this.scale; + boneData.y = (boneMap["y"] || 0) * this.scale; + boneData.rotation = (boneMap["rotation"] || 0); + boneData.scaleX = boneMap["scaleX"] || 1; + boneData.scaleY = boneMap["scaleY"] || 1; + skeletonData.bones.push(boneData); + } + + // Slots. + var slots = root["slots"]; + for (var i = 0, n = slots.length; i < n; i++) { + var slotMap = slots[i]; + var boneData = skeletonData.findBone(slotMap["bone"]); + if (!boneData) throw "Slot bone not found: " + slotMap["bone"]; + var slotData = new spine.SlotData(slotMap["name"], boneData); + + var color = slotMap["color"]; + if (color) { + slotData.r = spine.SkeletonJson.toColor(color, 0); + slotData.g = spine.SkeletonJson.toColor(color, 1); + slotData.b = spine.SkeletonJson.toColor(color, 2); + slotData.a = spine.SkeletonJson.toColor(color, 3); + } + + slotData.attachmentName = slotMap["attachment"]; + + skeletonData.slots.push(slotData); + } + + // Skins. + var skins = root["skins"]; + for (var skinName in skins) { + if (!skins.hasOwnProperty(skinName)) continue; + var skinMap = skins[skinName]; + var skin = new spine.Skin(skinName); + for (var slotName in skinMap) { + if (!skinMap.hasOwnProperty(slotName)) continue; + var slotIndex = skeletonData.findSlotIndex(slotName); + var slotEntry = skinMap[slotName]; + for (var attachmentName in slotEntry) { + if (!slotEntry.hasOwnProperty(attachmentName)) continue; + var attachment = this.readAttachment(skin, attachmentName, slotEntry[attachmentName]); + if (attachment != null) skin.addAttachment(slotIndex, attachmentName, attachment); + } + } + skeletonData.skins.push(skin); + if (skin.name == "default") skeletonData.defaultSkin = skin; + } + + // Animations. + var animations = root["animations"]; + for (var animationName in animations) { + if (!animations.hasOwnProperty(animationName)) continue; + this.readAnimation(animationName, animations[animationName], skeletonData); + } + + return skeletonData; + }, + readAttachment: function (skin, name, map) { + name = map["name"] || name; + + var type = spine.AttachmentType[map["type"] || "region"]; + + if (type == spine.AttachmentType.region) { + var attachment = new spine.RegionAttachment(); + attachment.x = (map["x"] || 0) * this.scale; + attachment.y = (map["y"] || 0) * this.scale; + attachment.scaleX = map["scaleX"] || 1; + attachment.scaleY = map["scaleY"] || 1; + attachment.rotation = map["rotation"] || 0; + attachment.width = (map["width"] || 32) * this.scale; + attachment.height = (map["height"] || 32) * this.scale; + attachment.updateOffset(); + + attachment.rendererObject = {}; + attachment.rendererObject.name = name; + attachment.rendererObject.scale = {}; + attachment.rendererObject.scale.x = attachment.scaleX; + attachment.rendererObject.scale.y = attachment.scaleY; + attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; + return attachment; + } + + throw "Unknown attachment type: " + type; + }, + + readAnimation: function (name, map, skeletonData) { + var timelines = []; + var duration = 0; + + var bones = map["bones"]; + for (var boneName in bones) { + if (!bones.hasOwnProperty(boneName)) continue; + var boneIndex = skeletonData.findBoneIndex(boneName); + if (boneIndex == -1) throw "Bone not found: " + boneName; + var boneMap = bones[boneName]; + + for (var timelineName in boneMap) { + if (!boneMap.hasOwnProperty(timelineName)) continue; + var values = boneMap[timelineName]; + if (timelineName == "rotate") { + var timeline = new spine.RotateTimeline(values.length); + timeline.boneIndex = boneIndex; + + var frameIndex = 0; + for (var i = 0, n = values.length; i < n; i++) { + var valueMap = values[i]; + timeline.setFrame(frameIndex, valueMap["time"], valueMap["angle"]); + spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 2 - 2]); + + } else if (timelineName == "translate" || timelineName == "scale") { + var timeline; + var timelineScale = 1; + if (timelineName == "scale") + timeline = new spine.ScaleTimeline(values.length); + else { + timeline = new spine.TranslateTimeline(values.length); + timelineScale = this.scale; + } + timeline.boneIndex = boneIndex; + + var frameIndex = 0; + for (var i = 0, n = values.length; i < n; i++) { + var valueMap = values[i]; + var x = (valueMap["x"] || 0) * timelineScale; + var y = (valueMap["y"] || 0) * timelineScale; + timeline.setFrame(frameIndex, valueMap["time"], x, y); + spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); + + } else + throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; + } + } + var slots = map["slots"]; + for (var slotName in slots) { + if (!slots.hasOwnProperty(slotName)) continue; + var slotMap = slots[slotName]; + var slotIndex = skeletonData.findSlotIndex(slotName); + + for (var timelineName in slotMap) { + if (!slotMap.hasOwnProperty(timelineName)) continue; + var values = slotMap[timelineName]; + if (timelineName == "color") { + var timeline = new spine.ColorTimeline(values.length); + timeline.slotIndex = slotIndex; + + var frameIndex = 0; + for (var i = 0, n = values.length; i < n; i++) { + var valueMap = values[i]; + var color = valueMap["color"]; + var r = spine.SkeletonJson.toColor(color, 0); + var g = spine.SkeletonJson.toColor(color, 1); + var b = spine.SkeletonJson.toColor(color, 2); + var a = spine.SkeletonJson.toColor(color, 3); + timeline.setFrame(frameIndex, valueMap["time"], r, g, b, a); + spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 5 - 5]); + + } else if (timelineName == "attachment") { + var timeline = new spine.AttachmentTimeline(values.length); + timeline.slotIndex = slotIndex; + + var frameIndex = 0; + for (var i = 0, n = values.length; i < n; i++) { + var valueMap = values[i]; + timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + + } else + throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; + } + } + skeletonData.animations.push(new spine.Animation(name, timelines, duration)); + } +}; +spine.SkeletonJson.readCurve = function (timeline, frameIndex, valueMap) { + var curve = valueMap["curve"]; + if (!curve) return; + if (curve == "stepped") + timeline.curves.setStepped(frameIndex); + else if (curve instanceof Array) + timeline.curves.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); +}; +spine.SkeletonJson.toColor = function (hexString, colorIndex) { + if (hexString.length != 8) throw "Color hexidecimal length must be 8, recieved: " + hexString; + return parseInt(hexString.substring(colorIndex * 2, 2), 16) / 255; +}; + +spine.Atlas = function (atlasText, textureLoader) { + this.textureLoader = textureLoader; + this.pages = []; + this.regions = []; + + var reader = new spine.AtlasReader(atlasText); + var tuple = []; + tuple.length = 4; + var page = null; + while (true) { + var line = reader.readLine(); + if (line == null) break; + line = reader.trim(line); + if (line.length == 0) + page = null; + else if (!page) { + page = new spine.AtlasPage(); + page.name = line; + + page.format = spine.Atlas.Format[reader.readValue()]; + + reader.readTuple(tuple); + page.minFilter = spine.Atlas.TextureFilter[tuple[0]]; + page.magFilter = spine.Atlas.TextureFilter[tuple[1]]; + + var direction = reader.readValue(); + page.uWrap = spine.Atlas.TextureWrap.clampToEdge; + page.vWrap = spine.Atlas.TextureWrap.clampToEdge; + if (direction == "x") + page.uWrap = spine.Atlas.TextureWrap.repeat; + else if (direction == "y") + page.vWrap = spine.Atlas.TextureWrap.repeat; + else if (direction == "xy") + page.uWrap = page.vWrap = spine.Atlas.TextureWrap.repeat; + + textureLoader.load(page, line); + + this.pages.push(page); + + } else { + var region = new spine.AtlasRegion(); + region.name = line; + region.page = page; + + region.rotate = reader.readValue() == "true"; + + reader.readTuple(tuple); + var x = parseInt(tuple[0]); + var y = parseInt(tuple[1]); + + reader.readTuple(tuple); + var width = parseInt(tuple[0]); + var height = parseInt(tuple[1]); + + region.u = x / page.width; + region.v = y / page.height; + if (region.rotate) { + region.u2 = (x + height) / page.width; + region.v2 = (y + width) / page.height; + } else { + region.u2 = (x + width) / page.width; + region.v2 = (y + height) / page.height; + } + region.x = x; + region.y = y; + region.width = Math.abs(width); + region.height = Math.abs(height); + + if (reader.readTuple(tuple) == 4) { // split is optional + region.splits = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; + + if (reader.readTuple(tuple) == 4) { // pad is optional, but only present with splits + region.pads = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; + + reader.readTuple(tuple); + } + } + + region.originalWidth = parseInt(tuple[0]); + region.originalHeight = parseInt(tuple[1]); + + reader.readTuple(tuple); + region.offsetX = parseInt(tuple[0]); + region.offsetY = parseInt(tuple[1]); + + region.index = parseInt(reader.readValue()); + + this.regions.push(region); + } + } +}; +spine.Atlas.prototype = { + findRegion: function (name) { + var regions = this.regions; + for (var i = 0, n = regions.length; i < n; i++) + if (regions[i].name == name) return regions[i]; + return null; + }, + dispose: function () { + var pages = this.pages; + for (var i = 0, n = pages.length; i < n; i++) + this.textureLoader.unload(pages[i].rendererObject); + }, + updateUVs: function (page) { + var regions = this.regions; + for (var i = 0, n = regions.length; i < n; i++) { + var region = regions[i]; + if (region.page != page) continue; + region.u = region.x / page.width; + region.v = region.y / page.height; + if (region.rotate) { + region.u2 = (region.x + region.height) / page.width; + region.v2 = (region.y + region.width) / page.height; + } else { + region.u2 = (region.x + region.width) / page.width; + region.v2 = (region.y + region.height) / page.height; + } + } + } +}; + +spine.Atlas.Format = { + alpha: 0, + intensity: 1, + luminanceAlpha: 2, + rgb565: 3, + rgba4444: 4, + rgb888: 5, + rgba8888: 6 +}; + +spine.Atlas.TextureFilter = { + nearest: 0, + linear: 1, + mipMap: 2, + mipMapNearestNearest: 3, + mipMapLinearNearest: 4, + mipMapNearestLinear: 5, + mipMapLinearLinear: 6 +}; + +spine.Atlas.TextureWrap = { + mirroredRepeat: 0, + clampToEdge: 1, + repeat: 2 +}; + +spine.AtlasPage = function () {}; +spine.AtlasPage.prototype = { + name: null, + format: null, + minFilter: null, + magFilter: null, + uWrap: null, + vWrap: null, + rendererObject: null, + width: 0, + height: 0 +}; + +spine.AtlasRegion = function () {}; +spine.AtlasRegion.prototype = { + page: null, + name: null, + x: 0, y: 0, + width: 0, height: 0, + u: 0, v: 0, u2: 0, v2: 0, + offsetX: 0, offsetY: 0, + originalWidth: 0, originalHeight: 0, + index: 0, + rotate: false, + splits: null, + pads: null, +}; + +spine.AtlasReader = function (text) { + this.lines = text.split(/\r\n|\r|\n/); +}; +spine.AtlasReader.prototype = { + index: 0, + trim: function (value) { + return value.replace(/^\s+|\s+$/g, ""); + }, + readLine: function () { + if (this.index >= this.lines.length) return null; + return this.lines[this.index++]; + }, + readValue: function () { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) throw "Invalid line: " + line; + return this.trim(line.substring(colon + 1)); + }, + /** Returns the number of tuple values read (2 or 4). */ + readTuple: function (tuple) { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) throw "Invalid line: " + line; + var i = 0, lastMatch= colon + 1; + for (; i < 3; i++) { + var comma = line.indexOf(",", lastMatch); + if (comma == -1) { + if (i == 0) throw "Invalid line: " + line; + break; + } + tuple[i] = this.trim(line.substr(lastMatch, comma - lastMatch)); + lastMatch = comma + 1; + } + tuple[i] = this.trim(line.substring(lastMatch)); + return i + 1; + } +} + +spine.AtlasAttachmentLoader = function (atlas) { + this.atlas = atlas; +} +spine.AtlasAttachmentLoader.prototype = { + newAttachment: function (skin, type, name) { + switch (type) { + case spine.AttachmentType.region: + var region = this.atlas.findRegion(name); + if (!region) throw "Region not found in atlas: " + name + " (" + type + ")"; + var attachment = new spine.RegionAttachment(name); + attachment.rendererObject = region; + attachment.setUVs(region.u, region.v, region.u2, region.v2, region.rotate); + attachment.regionOffsetX = region.offsetX; + attachment.regionOffsetY = region.offsetY; + attachment.regionWidth = region.width; + attachment.regionHeight = region.height; + attachment.regionOriginalWidth = region.originalWidth; + attachment.regionOriginalHeight = region.originalHeight; + return attachment; + } + throw "Unknown attachment type: " + type; + } +} + +PIXI.AnimCache = {}; +spine.Bone.yDown = true; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * This object is one that will allow you to specify custom rendering functions based on render type + * + * @class CustomRenderable + * @extends DisplayObject + * @constructor + */ +PIXI.CustomRenderable = function() +{ + PIXI.DisplayObject.call( this ); + + this.renderable = true; +} + +// constructor +PIXI.CustomRenderable.prototype = Object.create( PIXI.DisplayObject.prototype ); +PIXI.CustomRenderable.prototype.constructor = PIXI.CustomRenderable; + +/** + * If this object is being rendered by a CanvasRenderer it will call this callback + * + * @method renderCanvas + * @param renderer {CanvasRenderer} The renderer instance + */ +PIXI.CustomRenderable.prototype.renderCanvas = function(renderer) +{ + // override! +} + +/** + * If this object is being rendered by a WebGLRenderer it will call this callback to initialize + * + * @method initWebGL + * @param renderer {WebGLRenderer} The renderer instance + */ +PIXI.CustomRenderable.prototype.initWebGL = function(renderer) +{ + // override! +} + +/** + * If this object is being rendered by a WebGLRenderer it will call this callback + * + * @method renderWebGL + * @param renderer {WebGLRenderer} The renderer instance + */ +PIXI.CustomRenderable.prototype.renderWebGL = function(renderGroup, projectionMatrix) +{ + // not sure if both needed? but ya have for now! + // override! +} + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.BaseTextureCache = {}; +PIXI.texturesToUpdate = []; +PIXI.texturesToDestroy = []; + +/** + * A texture stores the information that represents an image. All textures have a base texture + * + * @class BaseTexture + * @uses EventTarget + * @constructor + * @param source {String} the source object (image or canvas) + */ +PIXI.BaseTexture = function(source) +{ + PIXI.EventTarget.call( this ); + + /** + * [read-only] The width of the base texture set when the image has loaded + * + * @property width + * @type Number + * @readOnly + */ + this.width = 100; + + /** + * [read-only] The height of the base texture set when the image has loaded + * + * @property height + * @type Number + * @readOnly + */ + this.height = 100; + + /** + * [read-only] Describes if the base texture has loaded or not + * + * @property hasLoaded + * @type Boolean + * @readOnly + */ + this.hasLoaded = false; + + /** + * The source that is loaded to create the texture + * + * @property source + * @type Image + */ + this.source = source; + + if(!source)return; + + if(this.source instanceof Image || this.source instanceof HTMLImageElement) + { + if(this.source.complete) + { + this.hasLoaded = true; + this.width = this.source.width; + this.height = this.source.height; + + PIXI.texturesToUpdate.push(this); + } + else + { + + var scope = this; + this.source.onload = function(){ + + scope.hasLoaded = true; + scope.width = scope.source.width; + scope.height = scope.source.height; + + // add it to somewhere... + PIXI.texturesToUpdate.push(scope); + scope.dispatchEvent( { type: 'loaded', content: scope } ); + } + // this.image.src = imageUrl; + } + } + else + { + this.hasLoaded = true; + this.width = this.source.width; + this.height = this.source.height; + + PIXI.texturesToUpdate.push(this); + } + + this._powerOf2 = false; +} + +PIXI.BaseTexture.prototype.constructor = PIXI.BaseTexture; + +/** + * Destroys this base texture + * + * @method destroy + */ +PIXI.BaseTexture.prototype.destroy = function() +{ + if(this.source instanceof Image) + { + this.source.src = null; + } + this.source = null; + PIXI.texturesToDestroy.push(this); +} + +/** + * Helper function that returns a base texture based on an image url + * If the image is not in the base texture cache it will be created and loaded + * + * @static + * @method fromImage + * @param imageUrl {String} The image url of the texture + * @return BaseTexture + */ +PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) +{ + var baseTexture = PIXI.BaseTextureCache[imageUrl]; + if(!baseTexture) + { + // new Image() breaks tex loading in some versions of Chrome. + // See https://code.google.com/p/chromium/issues/detail?id=238071 + var image = new Image();//document.createElement('img'); + if (crossorigin) + { + image.crossOrigin = ''; + } + image.src = imageUrl; + baseTexture = new PIXI.BaseTexture(image); + PIXI.BaseTextureCache[imageUrl] = baseTexture; + } + + return baseTexture; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.TextureCache = {}; +PIXI.FrameCache = {}; + +/** + * A texture stores the information that represents an image or part of an image. It cannot be added + * to the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used + * + * @class Texture + * @uses EventTarget + * @constructor + * @param baseTexture {BaseTexture} The base texture source to create the texture from + * @param frame {Rectangle} The rectangle frame of the texture to show + */ +PIXI.Texture = function(baseTexture, frame) +{ + PIXI.EventTarget.call( this ); + + if(!frame) + { + this.noFrame = true; + frame = new PIXI.Rectangle(0,0,1,1); + } + + if(baseTexture instanceof PIXI.Texture) + baseTexture = baseTexture.baseTexture; + + /** + * The base texture of this texture + * + * @property baseTexture + * @type BaseTexture + */ + this.baseTexture = baseTexture; + + /** + * The frame specifies the region of the base texture that this texture uses + * + * @property frame + * @type Rectangle + */ + this.frame = frame; + + /** + * The trim point + * + * @property trim + * @type Point + */ + this.trim = new PIXI.Point(); + + this.scope = this; + + if(baseTexture.hasLoaded) + { + if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); + //console.log(frame) + + this.setFrame(frame); + } + else + { + var scope = this; + baseTexture.addEventListener( 'loaded', function(){ scope.onBaseTextureLoaded()} ); + } +} + +PIXI.Texture.prototype.constructor = PIXI.Texture; + +/** + * Called when the base texture is loaded + * + * @method onBaseTextureLoaded + * @param event + * @private + */ +PIXI.Texture.prototype.onBaseTextureLoaded = function(event) +{ + var baseTexture = this.baseTexture; + baseTexture.removeEventListener( 'loaded', this.onLoaded ); + + if(this.noFrame)this.frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); + this.noFrame = false; + this.width = this.frame.width; + this.height = this.frame.height; + + this.scope.dispatchEvent( { type: 'update', content: this } ); +} + +/** + * Destroys this texture + * + * @method destroy + * @param destroyBase {Boolean} Whether to destroy the base texture as well + */ +PIXI.Texture.prototype.destroy = function(destroyBase) +{ + if(destroyBase)this.baseTexture.destroy(); +} + +/** + * Specifies the rectangle region of the baseTexture + * + * @method setFrame + * @param frame {Rectangle} The frame of the texture to set it to + */ +PIXI.Texture.prototype.setFrame = function(frame) +{ + this.frame = frame; + this.width = frame.width; + this.height = frame.height; + + if(frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height) + { + throw new Error("Texture Error: frame does not fit inside the base Texture dimensions " + this); + } + + this.updateFrame = true; + + PIXI.Texture.frameUpdates.push(this); + //this.dispatchEvent( { type: 'update', content: this } ); +} + +/** + * Helper function that returns a texture based on an image url + * If the image is not in the texture cache it will be created and loaded + * + * @static + * @method fromImage + * @param imageUrl {String} The image url of the texture + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin + * @return Texture + */ +PIXI.Texture.fromImage = function(imageUrl, crossorigin) +{ + var texture = PIXI.TextureCache[imageUrl]; + + if(!texture) + { + texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); + PIXI.TextureCache[imageUrl] = texture; + } + + return texture; +} + +/** + * Helper function that returns a texture based on a frame id + * If the frame id is not in the texture cache an error will be thrown + * + * @static + * @method fromFrame + * @param frameId {String} The frame id of the texture + * @return Texture + */ +PIXI.Texture.fromFrame = function(frameId) +{ + var texture = PIXI.TextureCache[frameId]; + if(!texture)throw new Error("The frameId '"+ frameId +"' does not exist in the texture cache " + this); + return texture; +} + +/** + * Helper function that returns a texture based on a canvas element + * If the canvas is not in the texture cache it will be created and loaded + * + * @static + * @method fromCanvas + * @param canvas {Canvas} The canvas element source of the texture + * @return Texture + */ +PIXI.Texture.fromCanvas = function(canvas) +{ + var baseTexture = new PIXI.BaseTexture(canvas); + return new PIXI.Texture(baseTexture); +} + + +/** + * Adds a texture to the textureCache. + * + * @static + * @method addTextureToCache + * @param texture {Texture} + * @param id {String} the id that the texture will be stored against. + */ +PIXI.Texture.addTextureToCache = function(texture, id) +{ + PIXI.TextureCache[id] = texture; +} + +/** + * Remove a texture from the textureCache. + * + * @static + * @method removeTextureFromCache + * @param id {String} the id of the texture to be removed + * @return {Texture} the texture that was removed + */ +PIXI.Texture.removeTextureFromCache = function(id) +{ + var texture = PIXI.TextureCache[id] + PIXI.TextureCache[id] = null; + return texture; +} + +// this is more for webGL.. it contains updated frames.. +PIXI.Texture.frameUpdates = []; + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + A RenderTexture is a special texture that allows any pixi displayObject to be rendered to it. + + __Hint__: All DisplayObjects (exmpl. Sprites) that renders on RenderTexture should be preloaded. + Otherwise black rectangles will be drawn instead. + + RenderTexture takes snapshot of DisplayObject passed to render method. If DisplayObject is passed to render method, position and rotation of it will be ignored. For example: + + var renderTexture = new PIXI.RenderTexture(800, 600); + var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); + sprite.position.x = 800/2; + sprite.position.y = 600/2; + sprite.anchor.x = 0.5; + sprite.anchor.y = 0.5; + renderTexture.render(sprite); + + Sprite in this case will be rendered to 0,0 position. To render this sprite at center DisplayObjectContainer should be used: + + var doc = new PIXI.DisplayObjectContainer(); + doc.addChild(sprite); + renderTexture.render(doc); // Renders to center of renderTexture + + @class RenderTexture + @extends Texture + @constructor + @param width {Number} The width of the render texture + @param height {Number} The height of the render texture + */ +PIXI.RenderTexture = function(width, height) +{ + PIXI.EventTarget.call( this ); + + this.width = width || 100; + this.height = height || 100; + + this.indetityMatrix = PIXI.mat3.create(); + + this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); + + if(PIXI.gl) + { + this.initWebGL(); + } + else + { + this.initCanvas(); + } +} + +PIXI.RenderTexture.prototype = Object.create( PIXI.Texture.prototype ); +PIXI.RenderTexture.prototype.constructor = PIXI.RenderTexture; + +/** + * Initializes the webgl data for this texture + * + * @method initWebGL + * @private + */ +PIXI.RenderTexture.prototype.initWebGL = function() +{ + var gl = PIXI.gl; + this.glFramebuffer = gl.createFramebuffer(); + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); + + this.glFramebuffer.width = this.width; + this.glFramebuffer.height = this.height; + + this.baseTexture = new PIXI.BaseTexture(); + + this.baseTexture.width = this.width; + this.baseTexture.height = this.height; + + this.baseTexture._glTexture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); + + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + + this.baseTexture.isRender = true; + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.baseTexture._glTexture, 0); + + // create a projection matrix.. + this.projection = new PIXI.Point(this.width/2 , -this.height/2); + + // set the correct render function.. + this.render = this.renderWebGL; +} + + +PIXI.RenderTexture.prototype.resize = function(width, height) +{ + + this.width = width; + this.height = height; + + if(PIXI.gl) + { + this.projection.x = this.width/2 + this.projection.y = -this.height/2; + + var gl = PIXI.gl; + gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + } + else + { + + this.frame.width = this.width + this.frame.height = this.height; + this.renderer.resize(this.width, this.height); + } +} + +/** + * Initializes the canvas data for this texture + * + * @method initCanvas + * @private + */ +PIXI.RenderTexture.prototype.initCanvas = function() +{ + this.renderer = new PIXI.CanvasRenderer(this.width, this.height, null, 0); + + this.baseTexture = new PIXI.BaseTexture(this.renderer.view); + this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); + + this.render = this.renderCanvas; +} + +/** + * This function will draw the display object to the texture. + * + * @method renderWebGL + * @param displayObject {DisplayObject} The display object to render this texture on + * @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn + * @private + */ +PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, clear) +{ + var gl = PIXI.gl; + + // enable the alpha color mask.. + gl.colorMask(true, true, true, true); + + gl.viewport(0, 0, this.width, this.height); + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); + + if(clear) + { + gl.clearColor(0,0,0, 0); + gl.clear(gl.COLOR_BUFFER_BIT); + } + + // THIS WILL MESS WITH HIT TESTING! + var children = displayObject.children; + + //TODO -? create a new one??? dont think so! + var originalWorldTransform = displayObject.worldTransform; + displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; + // modify to flip... + displayObject.worldTransform[4] = -1; + displayObject.worldTransform[5] = this.projection.y * -2; + + if(position) + { + displayObject.worldTransform[2] = position.x; + displayObject.worldTransform[5] -= position.y; + } + + PIXI.visibleCount++; + displayObject.vcount = PIXI.visibleCount; + + for(var i=0,j=children.length; i} assetURLs an array of image/sprite sheet urls that you would like loaded + * supported. Supported image formats include "jpeg", "jpg", "png", "gif". Supported + * sprite sheet data formats only include "JSON" at this time. Supported bitmap font + * data formats include "xml" and "fnt". + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin + */ +PIXI.AssetLoader = function(assetURLs, crossorigin) +{ + PIXI.EventTarget.call(this); + + /** + * The array of asset URLs that are going to be loaded + * + * @property assetURLs + * @type Array + */ + this.assetURLs = assetURLs; + + /** + * Whether the requests should be treated as cross origin + * + * @property crossorigin + * @type Boolean + */ + this.crossorigin = crossorigin; + + /** + * Maps file extension to loader types + * + * @property loadersByType + * @type Object + */ + this.loadersByType = { + "jpg": PIXI.ImageLoader, + "jpeg": PIXI.ImageLoader, + "png": PIXI.ImageLoader, + "gif": PIXI.ImageLoader, + "json": PIXI.JsonLoader, + "anim": PIXI.SpineLoader, + "xml": PIXI.BitmapFontLoader, + "fnt": PIXI.BitmapFontLoader + }; + + +}; + +/** + * Fired when an item has loaded + * @event onProgress + */ + +/** + * Fired when all the assets have loaded + * @event onComplete + */ + +// constructor +PIXI.AssetLoader.prototype.constructor = PIXI.AssetLoader; + +/** + * Starts loading the assets sequentially + * + * @method load + */ +PIXI.AssetLoader.prototype.load = function() +{ + var scope = this; + + this.loadCount = this.assetURLs.length; + + for (var i=0; i < this.assetURLs.length; i++) + { + var fileName = this.assetURLs[i]; + var fileType = fileName.split("?").shift().split(".").pop().toLowerCase(); + + var loaderClass = this.loadersByType[fileType]; + if(!loaderClass) + throw new Error(fileType + " is an unsupported file type"); + + var loader = new loaderClass(fileName, this.crossorigin); + + loader.addEventListener("loaded", function() + { + scope.onAssetLoaded(); + }); + loader.load(); + } +}; + +/** + * Invoked after each file is loaded + * + * @method onAssetLoaded + * @private + */ +PIXI.AssetLoader.prototype.onAssetLoaded = function() +{ + this.loadCount--; + this.dispatchEvent({type: "onProgress", content: this}); + if(this.onProgress) this.onProgress(); + + if(this.loadCount == 0) + { + this.dispatchEvent({type: "onComplete", content: this}); + if(this.onComplete) this.onComplete(); + } +}; + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * The json file loader is used to load in JSON data and parsing it + * When loaded this class will dispatch a "loaded" event + * If load failed this class will dispatch a "error" event + * + * @class JsonLoader + * @uses EventTarget + * @constructor + * @param url {String} The url of the JSON file + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin + */ +PIXI.JsonLoader = function (url, crossorigin) { + PIXI.EventTarget.call(this); + + /** + * The url of the bitmap font data + * + * @property url + * @type String + */ + this.url = url; + + /** + * Whether the requests should be treated as cross origin + * + * @property crossorigin + * @type Boolean + */ + this.crossorigin = crossorigin; + + /** + * [read-only] The base url of the bitmap font data + * + * @property baseUrl + * @type String + * @readOnly + */ + this.baseUrl = url.replace(/[^\/]*$/, ""); + + /** + * [read-only] Whether the data has loaded yet + * + * @property loaded + * @type Boolean + * @readOnly + */ + this.loaded = false; + +}; + +// constructor +PIXI.JsonLoader.prototype.constructor = PIXI.JsonLoader; + +/** + * Loads the JSON data + * + * @method load + */ +PIXI.JsonLoader.prototype.load = function () { + this.ajaxRequest = new AjaxRequest(); + var scope = this; + this.ajaxRequest.onreadystatechange = function () { + scope.onJSONLoaded(); + }; + + this.ajaxRequest.open("GET", this.url, true); + if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/json"); + this.ajaxRequest.send(null); +}; + +/** + * Invoke when JSON file is loaded + * + * @method onJSONLoaded + * @private + */ +PIXI.JsonLoader.prototype.onJSONLoaded = function () { + if (this.ajaxRequest.readyState == 4) { + if (this.ajaxRequest.status == 200 || window.location.href.indexOf("http") == -1) { + this.json = JSON.parse(this.ajaxRequest.responseText); + + if(this.json.frames) + { + // sprite sheet + var scope = this; + var textureUrl = this.baseUrl + this.json.meta.image; + var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); + var frameData = this.json.frames; + + this.texture = image.texture.baseTexture; + image.addEventListener("loaded", function (event) { + scope.onLoaded(); + }); + + for (var i in frameData) { + var rect = frameData[i].frame; + if (rect) { + PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { + x: rect.x, + y: rect.y, + width: rect.w, + height: rect.h + }); + if (frameData[i].trimmed) { + //var realSize = frameData[i].spriteSourceSize; + PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; + PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) + // calculate the offset! + } + } + } + + image.load(); + + } + else if(this.json.bones) + { + // spine animation + var spineJsonParser = new spine.SkeletonJson(); + var skeletonData = spineJsonParser.readSkeletonData(this.json); + PIXI.AnimCache[this.url] = skeletonData; + this.onLoaded(); + } + else + { + this.onLoaded(); + } + } + else + { + this.onError(); + } + } +}; + +/** + * Invoke when json file loaded + * + * @method onLoaded + * @private + */ +PIXI.JsonLoader.prototype.onLoaded = function () { + this.loaded = true; + this.dispatchEvent({ + type: "loaded", + content: this + }); +}; + +/** + * Invoke when error occured + * + * @method onError + * @private + */ +PIXI.JsonLoader.prototype.onError = function () { + this.dispatchEvent({ + type: "error", + content: this + }); +}; +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * The sprite sheet loader is used to load in JSON sprite sheet data + * To generate the data you can use http://www.codeandweb.com/texturepacker and publish the "JSON" format + * There is a free version so thats nice, although the paid version is great value for money. + * It is highly recommended to use Sprite sheets (also know as texture atlas") as it means sprite"s can be batched and drawn together for highly increased rendering speed. + * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() + * This loader will also load the image file that the Spritesheet points to as well as the data. + * When loaded this class will dispatch a "loaded" event + * + * @class SpriteSheetLoader + * @uses EventTarget + * @constructor + * @param url {String} The url of the sprite sheet JSON file + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin + */ + +PIXI.SpriteSheetLoader = function (url, crossorigin) { + /* + * i use texture packer to load the assets.. + * http://www.codeandweb.com/texturepacker + * make sure to set the format as "JSON" + */ + PIXI.EventTarget.call(this); + + /** + * The url of the bitmap font data + * + * @property url + * @type String + */ + this.url = url; + + /** + * Whether the requests should be treated as cross origin + * + * @property crossorigin + * @type Boolean + */ + this.crossorigin = crossorigin; + + /** + * [read-only] The base url of the bitmap font data + * + * @property baseUrl + * @type String + * @readOnly + */ + this.baseUrl = url.replace(/[^\/]*$/, ""); + + /** + * The texture being loaded + * + * @property texture + * @type Texture + */ + this.texture = null; + + /** + * The frames of the sprite sheet + * + * @property frames + * @type Object + */ + this.frames = {}; +}; + +// constructor +PIXI.SpriteSheetLoader.prototype.constructor = PIXI.SpriteSheetLoader; + +/** + * This will begin loading the JSON file + * + * @method load + */ +PIXI.SpriteSheetLoader.prototype.load = function () { + var scope = this; + var jsonLoader = new PIXI.JsonLoader(this.url, this.crossorigin); + jsonLoader.addEventListener("loaded", function (event) { + scope.json = event.content.json; + scope.onJSONLoaded(); + }); + jsonLoader.load(); +}; + +/** + * Invoke when JSON file is loaded + * + * @method onJSONLoaded + * @private + */ +PIXI.SpriteSheetLoader.prototype.onJSONLoaded = function () { + var scope = this; + var textureUrl = this.baseUrl + this.json.meta.image; + var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); + var frameData = this.json.frames; + + this.texture = image.texture.baseTexture; + image.addEventListener("loaded", function (event) { + scope.onLoaded(); + }); + + for (var i in frameData) { + var rect = frameData[i].frame; + if (rect) { + PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { + x: rect.x, + y: rect.y, + width: rect.w, + height: rect.h + }); + if (frameData[i].trimmed) { + //var realSize = frameData[i].spriteSourceSize; + PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; + PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) + // calculate the offset! + } + } + } + + image.load(); +}; +/** + * Invoke when all files are loaded (json and texture) + * + * @method onLoaded + * @private + */ +PIXI.SpriteSheetLoader.prototype.onLoaded = function () { + this.dispatchEvent({ + type: "loaded", + content: this + }); +}; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * The image loader class is responsible for loading images file formats ("jpeg", "jpg", "png" and "gif") + * Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() + * When loaded this class will dispatch a 'loaded' event + * + * @class ImageLoader + * @uses EventTarget + * @constructor + * @param url {String} The url of the image + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin + */ +PIXI.ImageLoader = function(url, crossorigin) +{ + PIXI.EventTarget.call(this); + + /** + * The texture being loaded + * + * @property texture + * @type Texture + */ + this.texture = PIXI.Texture.fromImage(url, crossorigin); + + /** + * if the image is loaded with loadFramedSpriteSheet + * frames will contain the sprite sheet frames + * + */ + this.frames = []; +}; + +// constructor +PIXI.ImageLoader.prototype.constructor = PIXI.ImageLoader; + +/** + * Loads image or takes it from cache + * + * @method load + */ +PIXI.ImageLoader.prototype.load = function() +{ + if(!this.texture.baseTexture.hasLoaded) + { + var scope = this; + this.texture.baseTexture.addEventListener("loaded", function() + { + scope.onLoaded(); + }); + } + else + { + this.onLoaded(); + } +}; + +/** + * Invoked when image file is loaded or it is already cached and ready to use + * + * @method onLoaded + * @private + */ +PIXI.ImageLoader.prototype.onLoaded = function() +{ + this.dispatchEvent({type: "loaded", content: this}); +}; + +/** + * Loads image and split it to uniform sized frames + * + * + * @method loadFramedSpriteSheet + * @param frameWidth {Number} with of each frame + * @param frameHeight {Number} height of each frame + * @param textureName {String} if given, the frames will be cached in - format + */ +PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) +{ + this.frames = []; + var cols = Math.floor(this.texture.width / frameWidth); + var rows = Math.floor(this.texture.height / frameHeight); + + var i=0; + for (var y=0; y>16)/255,(255&a>>8)/255,(255&a)/255]}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}var e=this,f=f||{};f.Point=function(a,b){this.x=a||0,this.y=b||0},f.Point.prototype.clone=function(){return new f.Point(this.x,this.y)},f.Point.prototype.constructor=f.Point,f.Rectangle=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Rectangle.prototype.clone=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Rectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},f.Rectangle.prototype.constructor=f.Rectangle,f.Polygon=function(a){if(a instanceof Array||(a=Array.prototype.slice.call(arguments)),"number"==typeof a[0]){for(var b=[],c=0,d=a.length;d>c;c+=2)b.push(new f.Point(a[c],a[c+1]));a=b}this.points=a},f.Polygon.prototype.clone=function(){for(var a=[],b=0;bb!=i>b&&(h-f)*(b-g)/(i-g)+f>a;j&&(c=!c)}return c},f.Polygon.prototype.constructor=f.Polygon,f.Circle=function(a,b,c){this.x=a||0,this.y=b||0,this.radius=c||0},f.Circle.prototype.clone=function(){return new f.Circle(this.x,this.y,this.radius)},f.Circle.prototype.contains=function(a,b){if(this.radius<=0)return!1;var c=this.x-a,d=this.y-b,e=this.radius*this.radius;return c*=c,d*=d,e>=c+d},f.Circle.prototype.constructor=f.Circle,f.Ellipse=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Ellipse.prototype.clone=function(){return new f.Ellipse(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=(a-this.x)/this.width-.5,d=(b-this.y)/this.height-.5;return c*=c,d*=d,.25>c+d},f.Ellipse.getBounds=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.constructor=f.Ellipse,c(),f.mat3={},f.mat3.create=function(){var a=new f.Matrix(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat3.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat4={},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat3.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=b[0],n=b[1],o=b[2],p=b[3],q=b[4],r=b[5],s=b[6],t=b[7],u=b[8];return c[0]=m*d+n*g+o*j,c[1]=m*e+n*h+o*k,c[2]=m*f+n*i+o*l,c[3]=p*d+q*g+r*j,c[4]=p*e+q*h+r*k,c[5]=p*f+q*i+r*l,c[6]=s*d+t*g+u*j,c[7]=s*e+t*h+u*k,c[8]=s*f+t*i+u*l,c},f.mat3.clone=function(a){var b=new f.Matrix(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},f.mat3.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[5];return a[1]=a[3],a[2]=a[6],a[3]=c,a[5]=a[7],a[6]=d,a[7]=e,a}return b[0]=a[0],b[1]=a[3],b[2]=a[6],b[3]=a[1],b[4]=a[4],b[5]=a[7],b[6]=a[2],b[7]=a[5],b[8]=a[8],b},f.mat3.toMat4=function(a,b){return b||(b=f.mat4.create()),b[15]=1,b[14]=0,b[13]=0,b[12]=0,b[11]=0,b[10]=a[8],b[9]=a[7],b[8]=a[6],b[7]=0,b[6]=a[5],b[5]=a[4],b[4]=a[3],b[3]=0,b[2]=a[2],b[1]=a[1],b[0]=a[0],b},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat4.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[3],f=a[6],g=a[7],h=a[11];return a[1]=a[4],a[2]=a[8],a[3]=a[12],a[4]=c,a[6]=a[9],a[7]=a[13],a[8]=d,a[9]=f,a[11]=a[14],a[12]=e,a[13]=g,a[14]=h,a}return b[0]=a[0],b[1]=a[4],b[2]=a[8],b[3]=a[12],b[4]=a[1],b[5]=a[5],b[6]=a[9],b[7]=a[13],b[8]=a[2],b[9]=a[6],b[10]=a[10],b[11]=a[14],b[12]=a[3],b[13]=a[7],b[14]=a[11],b[15]=a[15],b},f.mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=b[0],u=b[1],v=b[2],w=b[3];return c[0]=t*d+u*h+v*l+w*p,c[1]=t*e+u*i+v*m+w*q,c[2]=t*f+u*j+v*n+w*r,c[3]=t*g+u*k+v*o+w*s,t=b[4],u=b[5],v=b[6],w=b[7],c[4]=t*d+u*h+v*l+w*p,c[5]=t*e+u*i+v*m+w*q,c[6]=t*f+u*j+v*n+w*r,c[7]=t*g+u*k+v*o+w*s,t=b[8],u=b[9],v=b[10],w=b[11],c[8]=t*d+u*h+v*l+w*p,c[9]=t*e+u*i+v*m+w*q,c[10]=t*f+u*j+v*n+w*r,c[11]=t*g+u*k+v*o+w*s,t=b[12],u=b[13],v=b[14],w=b[15],c[12]=t*d+u*h+v*l+w*p,c[13]=t*e+u*i+v*m+w*q,c[14]=t*f+u*j+v*n+w*r,c[15]=t*g+u*k+v*o+w*s,c},f.DisplayObject=function(){this.last=this,this.first=this,this.position=new f.Point,this.scale=new f.Point(1,1),this.pivot=new f.Point(0,0),this.rotation=0,this.alpha=1,this.visible=!0,this.hitArea=null,this.buttonMode=!1,this.renderable=!1,this.parent=null,this.stage=null,this.worldAlpha=1,this._interactive=!1,this.worldTransform=f.mat3.create(),this.localTransform=f.mat3.create(),this.color=[],this.dynamic=!0,this._sr=0,this._cr=1,this.filterArea=new f.Rectangle(0,0,1,1)},f.DisplayObject.prototype.constructor=f.DisplayObject,f.DisplayObject.prototype.setInteractive=function(a){this.interactive=a},Object.defineProperty(f.DisplayObject.prototype,"interactive",{get:function(){return this._interactive},set:function(a){this._interactive=a,this.stage&&(this.stage.dirty=!0)}}),Object.defineProperty(f.DisplayObject.prototype,"mask",{get:function(){return this._mask},set:function(a){a?this._mask?(a.start=this._mask.start,a.end=this._mask.end):(this.addFilter(a),a.renderable=!1):(this.removeFilter(this._mask),this._mask.renderable=!0),this._mask=a}}),Object.defineProperty(f.DisplayObject.prototype,"filters",{get:function(){return this._filters},set:function(a){if(a){this._filters&&this.removeFilter(this._filters),this.addFilter(a);for(var b=[],c=0;c=0&&b<=this.children.length))throw new Error(a+" The index "+b+" supplied is out of bounds "+this.children.length);if(void 0!=a.parent&&a.parent.removeChild(a),a.parent=this,this.stage){var c=a;do c.interactive&&(this.stage.dirty=!0),c.stage=this.stage,c=c._iNext;while(c)}var d,e,f=a.first,g=a.last;if(b==this.children.length){e=this.last;for(var h=this,i=this.last;h;)h.last==i&&(h.last=a.last),h=h.parent}else e=0==b?this:this.children[b-1].last;d=e._iNext,d&&(d._iPrev=g,g._iNext=d),f._iPrev=e,e._iNext=f,this.children.splice(b,0,a),this.__renderGroup&&(a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a),this.__renderGroup.addDisplayObjectAndChildren(a))},f.DisplayObjectContainer.prototype.swapChildren=function(){},f.DisplayObjectContainer.prototype.getChildAt=function(a){if(a>=0&&aa;a++)this.children[a].updateTransform()}},f.blendModes={},f.blendModes.NORMAL=0,f.blendModes.SCREEN=1,f.Sprite=function(a){f.DisplayObjectContainer.call(this),this.anchor=new f.Point,this.texture=a,this.blendMode=f.blendModes.NORMAL,this._width=0,this._height=0,a.baseTexture.hasLoaded?this.updateFrame=!0:(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Sprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Sprite.prototype.constructor=f.Sprite,Object.defineProperty(f.Sprite.prototype,"width",{get:function(){return this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(f.Sprite.prototype,"height",{get:function(){return this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),f.Sprite.prototype.setTexture=function(a){this.texture.baseTexture!=a.baseTexture?(this.textureChange=!0,this.texture=a,this.__renderGroup&&this.__renderGroup.updateTexture(this)):this.texture=a,this.updateFrame=!0},f.Sprite.prototype.onTextureUpdate=function(){this._width&&(this.scale.x=this._width/this.texture.frame.width),this._height&&(this.scale.y=this._height/this.texture.frame.height),this.updateFrame=!0},f.Sprite.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache"+this);return new f.Sprite(b)},f.Sprite.fromImage=function(a){var b=f.Texture.fromImage(a);return new f.Sprite(b)},f.MovieClip=function(a){f.Sprite.call(this,a[0]),this.textures=a,this.animationSpeed=1,this.loop=!0,this.onComplete=null,this.currentFrame=0,this.playing=!1},f.MovieClip.prototype=Object.create(f.Sprite.prototype),f.MovieClip.prototype.constructor=f.MovieClip,Object.defineProperty(f.MovieClip.prototype,"totalFrames",{get:function(){return this.textures.length}}),f.MovieClip.prototype.stop=function(){this.playing=!1},f.MovieClip.prototype.play=function(){this.playing=!0},f.MovieClip.prototype.gotoAndStop=function(a){this.playing=!1,this.currentFrame=a;var b=0|this.currentFrame+.5;this.setTexture(this.textures[b%this.textures.length])},f.MovieClip.prototype.gotoAndPlay=function(a){this.currentFrame=a,this.playing=!0},f.MovieClip.prototype.updateTransform=function(){if(f.Sprite.prototype.updateTransform.call(this),this.playing){this.currentFrame+=this.animationSpeed;var a=0|this.currentFrame+.5;this.loop||a=this.textures.length&&(this.gotoAndStop(this.textures.length-1),this.onComplete&&this.onComplete())}},f.FilterBlock=function(){this.visible=!0,this.renderable=!0},f.Text=function(a,b){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),f.Sprite.call(this,f.Texture.fromCanvas(this.canvas)),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.Text.prototype=Object.create(f.Sprite.prototype),f.Text.prototype.constructor=f.Text,f.Text.prototype.setStyle=function(a){a=a||{},a.font=a.font||"bold 20pt Arial",a.fill=a.fill||"black",a.align=a.align||"left",a.stroke=a.stroke||"black",a.strokeThickness=a.strokeThickness||0,a.wordWrap=a.wordWrap||!1,a.wordWrapWidth=a.wordWrapWidth||100,this.style=a,this.dirty=!0},f.Text.prototype.setText=function(a){this.text=a.toString()||" ",this.dirty=!0},f.Text.prototype.updateText=function(){this.context.font=this.style.font;var a=this.text;this.style.wordWrap&&(a=this.wordWrap(this.text));for(var b=a.split(/(?:\r\n|\r|\n)/),c=[],d=0,e=0;ee?(g>0&&(b+="\n"),b+=f[g]+" ",e=this.style.wordWrapWidth-h):(e-=i,b+=f[g]+" ")}b+="\n"}return b},f.Text.prototype.destroy=function(a){a&&this.texture.destroy()},f.Text.heightCache={},f.BitmapText=function(a,b){f.DisplayObjectContainer.call(this),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.BitmapText.prototype=Object.create(f.DisplayObjectContainer.prototype),f.BitmapText.prototype.constructor=f.BitmapText,f.BitmapText.prototype.setText=function(a){this.text=a||" ",this.dirty=!0},f.BitmapText.prototype.setStyle=function(a){a=a||{},a.align=a.align||"left",this.style=a;var b=a.font.split(" ");this.fontName=b[b.length-1],this.fontSize=b.length>=2?parseInt(b[b.length-2],10):f.BitmapText.fonts[this.fontName].size,this.dirty=!0},f.BitmapText.prototype.updateText=function(){for(var a=f.BitmapText.fonts[this.fontName],b=new f.Point,c=null,d=[],e=0,g=[],h=0,i=this.fontSize/a.size,j=0;j=j;j++){var n=0;"right"==this.style.align?n=e-g[j]:"center"==this.style.align&&(n=(e-g[j])/2),m.push(n)}for(j=0;j0;)this.removeChild(this.getChildAt(0));this.updateText(),this.dirty=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.BitmapText.fonts={},f.InteractionManager=function(a){this.stage=a,this.mouse=new f.InteractionData,this.touchs={},this.tempPoint=new f.Point,this.mouseoverEnabled=!0,this.pool=[],this.interactiveItems=[],this.interactionDOMElement=null,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseOut=this.onMouseOut.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.last=0},f.InteractionManager.prototype.constructor=f.InteractionManager,f.InteractionManager.prototype.collectInteractiveSprite=function(a,b){for(var c=a.children,d=c.length,e=d-1;e>=0;e--){var f=c[e];f.interactive?(b.interactiveChildren=!0,this.interactiveItems.push(f),f.children.length>0&&this.collectInteractiveSprite(f,f)):(f.__iParent=null,f.children.length>0&&this.collectInteractiveSprite(f,b))}},f.InteractionManager.prototype.setTarget=function(a){this.target=a,null===this.interactionDOMElement&&this.setTargetDomElement(a.view),document.body.addEventListener("mouseup",this.onMouseUp,!0)},f.InteractionManager.prototype.setTargetDomElement=function(a){null!==this.interactionDOMElement&&(this.interactionDOMElement.style["-ms-content-zooming"]="",this.interactionDOMElement.style["-ms-touch-action"]="",this.interactionDOMElement.removeEventListener("mousemove",this.onMouseMove,!0),this.interactionDOMElement.removeEventListener("mousedown",this.onMouseDown,!0),this.interactionDOMElement.removeEventListener("mouseout",this.onMouseOut,!0),this.interactionDOMElement.removeEventListener("touchstart",this.onTouchStart,!0),this.interactionDOMElement.removeEventListener("touchend",this.onTouchEnd,!0),this.interactionDOMElement.removeEventListener("touchmove",this.onTouchMove,!0)),window.navigator.msPointerEnabled&&(a.style["-ms-content-zooming"]="none",a.style["-ms-touch-action"]="none"),this.interactionDOMElement=a,a.addEventListener("mousemove",this.onMouseMove,!0),a.addEventListener("mousedown",this.onMouseDown,!0),a.addEventListener("mouseout",this.onMouseOut,!0),a.addEventListener("touchstart",this.onTouchStart,!0),a.addEventListener("touchend",this.onTouchEnd,!0),a.addEventListener("touchmove",this.onTouchMove,!0)},f.InteractionManager.prototype.update=function(){if(this.target){var a=Date.now(),b=a-this.last;if(b=30*b/1e3,!(1>b)){if(this.last=a,this.dirty){this.dirty=!1;for(var c=this.interactiveItems.length,d=0;c>d;d++)this.interactiveItems[d].interactiveChildren=!1;this.interactiveItems=[],this.stage.interactive&&this.interactiveItems.push(this.stage),this.collectInteractiveSprite(this.stage,this.stage)}var e=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var d=0;e>d;d++){var f=this.interactiveItems[d];(f.mouseover||f.mouseout||f.buttonMode)&&(f.__hit=this.hitTest(f,this.mouse),this.mouse.target=f,f.__hit?(f.buttonMode&&(this.interactionDOMElement.style.cursor="pointer"),f.__isOver||(f.mouseover&&f.mouseover(this.mouse),f.__isOver=!0)):f.__isOver&&(f.mouseout&&f.mouseout(this.mouse),f.__isOver=!1))}}}},f.InteractionManager.prototype.onMouseMove=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactionDOMElement.getBoundingClientRect();this.mouse.global.x=(a.clientX-b.left)*(this.target.width/b.width),this.mouse.global.y=(a.clientY-b.top)*(this.target.height/b.height);var c=this.interactiveItems.length;this.mouse.global;for(var d=0;c>d;d++){var e=this.interactiveItems[d];e.mousemove&&e.mousemove(this.mouse)}},f.InteractionManager.prototype.onMouseDown=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactiveItems.length;this.mouse.global,this.stage;for(var c=0;b>c;c++){var d=this.interactiveItems[c];if((d.mousedown||d.click)&&(d.__mouseIsDown=!0,d.__hit=this.hitTest(d,this.mouse),d.__hit&&(d.mousedown&&d.mousedown(this.mouse),d.__isDown=!0,!d.interactiveChildren)))break}},f.InteractionManager.prototype.onMouseOut=function(){var a=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var b=0;a>b;b++){var c=this.interactiveItems[b];c.__isOver&&(this.mouse.target=c,c.mouseout&&c.mouseout(this.mouse),c.__isOver=!1)}},f.InteractionManager.prototype.onMouseUp=function(a){this.mouse.originalEvent=a||window.event,this.mouse.global;for(var b=this.interactiveItems.length,c=!1,d=0;b>d;d++){var e=this.interactiveItems[d];(e.mouseup||e.mouseupoutside||e.click)&&(e.__hit=this.hitTest(e,this.mouse),e.__hit&&!c?(e.mouseup&&e.mouseup(this.mouse),e.__isDown&&e.click&&e.click(this.mouse),e.interactiveChildren||(c=!0)):e.__isDown&&e.mouseupoutside&&e.mouseupoutside(this.mouse),e.__isDown=!1)}},f.InteractionManager.prototype.hitTest=function(a,b){var c=b.global;if(a.vcount!==f.visibleCount)return!1;var d=a instanceof f.Sprite,e=a.worldTransform,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=1/(g*k+h*-j),n=k*m*c.x+-h*m*c.y+(l*h-i*k)*m,o=g*m*c.y+-j*m*c.x+(-l*g+i*j)*m;if(b.target=a,a.hitArea&&a.hitArea.contains)return a.hitArea.contains(n,o)?(b.target=a,!0):!1;if(d){var p,q=a.texture.frame.width,r=a.texture.frame.height,s=-q*a.anchor.x;if(n>s&&s+q>n&&(p=-r*a.anchor.y,o>p&&p+r>o))return b.target=a,!0}for(var t=a.children.length,u=0;t>u;u++){var v=a.children[u],w=this.hitTest(v,b);if(w)return b.target=a,!0}return!1},f.InteractionManager.prototype.onTouchMove=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;dd;d++){var h=this.interactiveItems[d];h.touchmove&&h.touchmove(f)}},f.InteractionManager.prototype.onTouchStart=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i];if((j.touchstart||j.tap)&&(j.__hit=this.hitTest(j,g),j.__hit&&(j.touchstart&&j.touchstart(g),j.__isDown=!0,j.__touchData=g,!j.interactiveChildren)))break}}},f.InteractionManager.prototype.onTouchEnd=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i],k=j.__touchData;j.__hit=this.hitTest(j,f),k==f&&(f.originalEvent=a||window.event,(j.touchend||j.tap)&&(j.__hit&&!g?(j.touchend&&j.touchend(f),j.__isDown&&j.tap&&j.tap(f),j.interactiveChildren||(g=!0)):j.__isDown&&j.touchendoutside&&j.touchendoutside(f),j.__isDown=!1),j.__touchData=null)}this.pool.push(f),this.touchs[e.identifier]=null}},f.InteractionData=function(){this.global=new f.Point,this.local=new f.Point,this.target,this.originalEvent},f.InteractionData.prototype.getLocalPosition=function(a){var b=a.worldTransform,c=this.global,d=b[0],e=b[1],g=b[2],h=b[3],i=b[4],j=b[5],k=1/(d*i+e*-h);return new f.Point(i*k*c.x+-e*k*c.y+(j*e-g*i)*k,d*k*c.y+-h*k*c.x+(-j*d+g*h)*k)},f.InteractionData.prototype.constructor=f.InteractionData,f.Stage=function(a){f.DisplayObjectContainer.call(this),this.worldTransform=f.mat3.create(),this.interactive=!0,this.interactionManager=new f.InteractionManager(this),this.dirty=!0,this.__childrenAdded=[],this.__childrenRemoved=[],this.stage=this,this.stage.hitArea=new f.Rectangle(0,0,1e5,1e5),this.setBackgroundColor(a),this.worldVisible=!0},f.Stage.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Stage.prototype.constructor=f.Stage,f.Stage.prototype.setInteractionDelegate=function(a){this.interactionManager.setTargetDomElement(a)},f.Stage.prototype.updateTransform=function(){this.worldAlpha=1,this.vcount=f.visibleCount;for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform();this.dirty&&(this.dirty=!1,this.interactionManager.dirty=!0),this.interactive&&this.interactionManager.update()},f.Stage.prototype.setBackgroundColor=function(a){this.backgroundColor=a||0,this.backgroundColorSplit=d(this.backgroundColor);var b=this.backgroundColor.toString(16);b="000000".substr(0,6-b.length)+b,this.backgroundColorString="#"+b},f.Stage.prototype.getMousePosition=function(){return this.interactionManager.mouse.global};for(var h=0,i=["ms","moz","webkit","o"],j=0;j>>>>>>>>"),console.log("_");var b=0,c=a.first;for(console.log(c);c._iNext;)if(b++,c=c._iNext,console.log(c),b>100){console.log("BREAK");break}},f.EventTarget=function(){var a={};this.addEventListener=this.on=function(b,c){void 0===a[b]&&(a[b]=[]),-1===a[b].indexOf(c)&&a[b].push(c)},this.dispatchEvent=this.emit=function(b){if(a[b.type]&&a[b.type].length)for(var c=0,d=a[b.type].length;d>c;c++)a[b.type][c](b)},this.removeEventListener=this.off=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)}},f.autoDetectRenderer=function(a,b,c,d,e){a||(a=800),b||(b=600);var g=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}();if(g){var h=-1!=navigator.userAgent.toLowerCase().indexOf("msie");g=!h}return g?new f.WebGLRenderer(a,b,c,d,e):new f.CanvasRenderer(a,b,c,d)},f.PolyK={},f.PolyK.Triangulate=function(a){var b=!0,c=a.length>>1;if(3>c)return[];for(var d=[],e=[],g=0;c>g;g++)e.push(g);for(var g=0,h=c;h>3;){var i=e[(g+0)%h],j=e[(g+1)%h],k=e[(g+2)%h],l=a[2*i],m=a[2*i+1],n=a[2*j],o=a[2*j+1],p=a[2*k],q=a[2*k+1],r=!1;if(f.PolyK._convex(l,m,n,o,p,q,b)){r=!0;for(var s=0;h>s;s++){var t=e[s];if(t!=i&&t!=j&&t!=k&&f.PolyK._PointInTriangle(a[2*t],a[2*t+1],l,m,n,o,p,q)){r=!1;break}}}if(r)d.push(i,j,k),e.splice((g+1)%h,1),h--,g=0;else if(g++>3*h){if(!b)return console.log("PIXI Warning: shape too complex to fill"),[];var d=[];e=[];for(var g=0;c>g;g++)e.push(g);g=0,h=c,b=!1}}return d.push(e[0],e[1],e[2]),d},f.PolyK._PointInTriangle=function(a,b,c,d,e,f,g,h){var i=g-c,j=h-d,k=e-c,l=f-d,m=a-c,n=b-d,o=i*i+j*j,p=i*k+j*l,q=i*m+j*n,r=k*k+l*l,s=k*m+l*n,t=1/(o*r-p*p),u=(r*q-p*s)*t,v=(o*s-p*q)*t;return u>=0&&v>=0&&1>u+v},f.PolyK._convex=function(a,b,c,d,e,f,g){return(b-d)*(e-c)+(c-a)*(f-d)>=0==g},f.initDefaultShaders=function(){f.primitiveShader=new f.PrimitiveShader,f.primitiveShader.init(),f.stripShader=new f.StripShader,f.stripShader.init(),f.defaultShader=new f.PixiShader,f.defaultShader.init();var a=f.gl,b=f.defaultShader.program;a.useProgram(b),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.primitiveShader.program),a.disableVertexAttribArray(f.defaultShader.aVertexPosition),a.disableVertexAttribArray(f.defaultShader.colorAttribute),a.disableVertexAttribArray(f.defaultShader.aTextureCoord),a.enableVertexAttribArray(f.primitiveShader.aVertexPosition),a.enableVertexAttribArray(f.primitiveShader.colorAttribute)},f.deactivatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program),a.disableVertexAttribArray(f.primitiveShader.aVertexPosition),a.disableVertexAttribArray(f.primitiveShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activateStripShader=function(){var a=f.gl;a.useProgram(f.stripShader.program)},f.deactivateStripShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program)},f.CompileVertexShader=function(a,b){return f._CompileShader(a,b,a.VERTEX_SHADER)},f.CompileFragmentShader=function(a,b){return f._CompileShader(a,b,a.FRAGMENT_SHADER)},f._CompileShader=function(a,b,c){var d=b.join("\n"),e=a.createShader(c);return a.shaderSource(e,d),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)?e:(console.log(a.getShaderInfoLog(e)),null)},f.compileProgram=function(a,b){var c=f.gl,d=f.CompileFragmentShader(c,b),e=f.CompileVertexShader(c,a),g=c.createProgram();return c.attachShader(g,e),c.attachShader(g,d),c.linkProgram(g),c.getProgramParameter(g,c.LINK_STATUS)||console.log("Could not initialise shaders"),g},f.PixiShader=function(){this.program,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;","}"]},f.PixiShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc||f.PixiShader.defaultVertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"); -for(var c in this.uniforms)this.uniforms[c].uniformLocation=b.getUniformLocation(a,c);this.program=a},f.PixiShader.prototype.syncUniforms=function(){var a=f.gl;for(var b in this.uniforms){var c=this.uniforms[b].type;if("f"==c&&a.uniform1f(this.uniforms[b].uniformLocation,this.uniforms[b].value),"f2"==c)a.uniform2f(this.uniforms[b].uniformLocation,this.uniforms[b].value.x,this.uniforms[b].value.y);else if("f4"==c)a.uniform4fv(this.uniforms[b].uniformLocation,this.uniforms[b].value);else if("mat4"==c)a.uniformMatrix4fv(this.uniforms[b].uniformLocation,!1,this.uniforms[b].value);else if("sampler2D"==c){var d=this.uniforms[b].value;a.activeTexture(a.TEXTURE1),a.bindTexture(a.TEXTURE_2D,d.baseTexture._glTexture),a.uniform1i(this.uniforms[b].uniformLocation,1)}}},f.PixiShader.defaultVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","varying float vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"],f.StripShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying float vColor;","uniform float alpha;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));","gl_FragColor = gl_FragColor * alpha;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","varying vec2 vTextureCoord;","varying vec2 offsetVector;","varying float vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"]},f.StripShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.PrimitiveShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","gl_FragColor = vColor;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec4 aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform float alpha;","varying vec4 vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","vColor = aColor * alpha;","}"]},f.PrimitiveShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.WebGLGraphics=function(){},f.WebGLGraphics.renderGraphics=function(a,b){var c=f.gl;a._webGL||(a._webGL={points:[],indices:[],lastIndex:0,buffer:c.createBuffer(),indexBuffer:c.createBuffer()}),a.dirty&&(a.dirty=!1,a.clearDirty&&(a.clearDirty=!1,a._webGL.lastIndex=0,a._webGL.points=[],a._webGL.indices=[]),f.WebGLGraphics.updateGraphics(a)),f.activatePrimitiveShader();var d=f.mat3.clone(a.worldTransform);f.mat3.transpose(d),c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA),c.uniformMatrix3fv(f.primitiveShader.translationMatrix,!1,d),c.uniform2f(f.primitiveShader.projectionVector,b.x,-b.y),c.uniform2f(f.primitiveShader.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(f.primitiveShader.alpha,a.worldAlpha),c.bindBuffer(c.ARRAY_BUFFER,a._webGL.buffer),c.vertexAttribPointer(f.primitiveShader.aVertexPosition,2,c.FLOAT,!1,24,0),c.vertexAttribPointer(f.primitiveShader.colorAttribute,4,c.FLOAT,!1,24,8),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),c.drawElements(c.TRIANGLE_STRIP,a._webGL.indices.length,c.UNSIGNED_SHORT,0),f.deactivatePrimitiveShader()},f.WebGLGraphics.updateGraphics=function(a){for(var b=a._webGL.lastIndex;b3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){if(a.lineWidth%2)for(var e=0;ee;e++)k=c[2*(e-1)],l=c[2*(e-1)+1],m=c[2*e],n=c[2*e+1],o=c[2*(e+1)],p=c[2*(e+1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,s=-(n-p),t=m-o,E=Math.sqrt(s*s+t*t),s/=E,t/=E,s*=K,t*=K,w=-r+l-(-r+n),x=-q+m-(-q+k),y=(-q+k)*(-r+n)-(-q+m)*(-r+l),z=-t+p-(-t+n),A=-s+m-(-s+o),B=(-s+o)*(-t+n)-(-s+m)*(-t+p),C=w*A-z*x,Math.abs(C)<.1?(C+=10.1,F.push(m-q,n-r,N,O,P,M),F.push(m+q,n+r,N,O,P,M)):(px=(x*B-A*y)/C,py=(z*y-w*B)/C,D=(px-m)*(px-m)+(py-n)+(py-n),D>19600?(u=q-s,v=r-t,E=Math.sqrt(u*u+v*v),u/=E,v/=E,u*=K,v*=K,F.push(m-u,n-v),F.push(N,O,P,M),F.push(m+u,n+v),F.push(N,O,P,M),F.push(m-u,n-v),F.push(N,O,P,M),I++):(F.push(px,py),F.push(N,O,P,M),F.push(m-(px-m),n-(py-n)),F.push(N,O,P,M)));k=c[2*(H-2)],l=c[2*(H-2)+1],m=c[2*(H-1)],n=c[2*(H-1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,F.push(m-q,n-r),F.push(N,O,P,M),F.push(m+q,n+r),F.push(N,O,P,M),G.push(J);for(var e=0;I>e;e++)G.push(J++);G.push(J-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl,this.transparent)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},flip=!1;var l=[],m=0;f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;if(a.open)a.data instanceof Array?this.filterManager.pushFilter(a):(m++,l.push(a),c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.INCR),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP));else if(a.data instanceof Array)this.filterManager.popFilter();else{var d=l.pop(a);d&&(c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.DECR),f.WebGLGraphics.renderGraphics(d.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)),c.disable(c.STENCIL_TEST)}},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(a){this.transparent=a,this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;hs?s:E,E=E>t?t:E,E=E>u?u:E,E=E>v?v:E,F=F>w?w:F,F=F>x?x:F,F=F>y?y:F,F=F>z?z:F,C=s>C?s:C,C=t>C?t:C,C=u>C?u:C,C=v>C?v:C,D=w>D?w:D,D=x>D?x:D,D=y>D?y:D,D=z>D?z:D),l=!1,A=A._iNext}while(A!=B);a.filterArea.x=E,a.filterArea.y=F,a.filterArea.width=C-E,a.filterArea.height=D-F},f.FilterTexture=function(a,b){var c=f.gl;this.frameBuffer=c.createFramebuffer(),this.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,this.texture),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.bindFramebuffer(c.FRAMEBUFFER,this.framebuffer),c.bindFramebuffer(c.FRAMEBUFFER,this.frameBuffer),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,this.texture,0),this.resize(a,b)},f.FilterTexture.prototype.resize=function(a,b){this.width=a,this.height=b;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a,b,0,c.RGBA,c.UNSIGNED_BYTE,null)},f.CanvasRenderer=function(a,b,c,d){this.transparent=d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.context=this.view.getContext("2d"),this.refresh=!0,this.view.width=this.width,this.view.height=this.height,this.count=0},f.CanvasRenderer.prototype.constructor=f.CanvasRenderer,f.CanvasRenderer.prototype.render=function(a){f.texturesToUpdate=[],f.texturesToDestroy=[],f.visibleCount++,a.updateTransform(),this.view.style.backgroundColor==a.backgroundColorString||this.transparent||(this.view.style.backgroundColor=a.backgroundColorString),this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.width,this.height),this.renderDisplayObject(a),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0&&(f.Texture.frameUpdates=[])},f.CanvasRenderer.prototype.resize=function(a,b){this.width=a,this.height=b,this.view.width=a,this.view.height=b},f.CanvasRenderer.prototype.renderDisplayObject=function(a){var b,c=this.context;c.globalCompositeOperation="source-over";var d=a.last._iNext;a=a.first;do if(b=a.worldTransform,a.visible)if(a.renderable){if(a instanceof f.Sprite){var e=a.texture.frame;e&&e.width&&e.height&&(c.globalAlpha=a.worldAlpha,c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),c.drawImage(a.texture.baseTexture.source,e.x,e.y,e.width,e.height,a.anchor.x*-e.width,a.anchor.y*-e.height,e.width,e.height))}else if(a instanceof f.Strip)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderStrip(a);else if(a instanceof f.TilingSprite)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderTilingSprite(a);else if(a instanceof f.CustomRenderable)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),a.renderCanvas(this);else if(a instanceof f.Graphics)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),f.CanvasGraphics.renderGraphics(a,c);else if(a instanceof f.FilterBlock&&a.data instanceof f.Graphics){var g=a.data;if(a.open){c.save();var h=g.alpha,i=g.worldTransform;c.setTransform(i[0],i[3],i[1],i[4],i[2],i[5]),g.worldAlpha=.5,c.worldAlpha=0,f.CanvasGraphics.renderGraphicsMask(g,c),c.clip(),g.worldAlpha=h}else c.restore()}a=a._iNext}else a=a._iNext;else a=a.last._iNext;while(a!=d)},f.CanvasRenderer.prototype.renderStripFlat=function(a){var b=this.context,c=a.verticies;a.uvs;var d=c.length/2;this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},f.CanvasRenderer.prototype.renderTilingSprite=function(a){var b=this.context;b.globalAlpha=a.worldAlpha,a.__tilePattern||(a.__tilePattern=b.createPattern(a.texture.baseTexture.source,"repeat")),b.beginPath();var c=a.tilePosition,d=a.tileScale;b.scale(d.x,d.y),b.translate(c.x,c.y),b.fillStyle=a.__tilePattern,b.fillRect(-c.x,-c.y,a.width/d.x,a.height/d.y),b.scale(1/d.x,1/d.y),b.translate(-c.x,-c.y),b.closePath()},f.CanvasRenderer.prototype.renderStrip=function(a){var b=this.context,c=a.verticies,d=a.uvs,e=c.length/2;this.count++;for(var f=1;e-2>f;f++){var g=2*f,h=c[g],i=c[g+2],j=c[g+4],k=c[g+1],l=c[g+3],m=c[g+5],n=d[g]*a.texture.width,o=d[g+2]*a.texture.width,p=d[g+4]*a.texture.width,q=d[g+1]*a.texture.height,r=d[g+3]*a.texture.height,s=d[g+5]*a.texture.height;b.save(),b.beginPath(),b.moveTo(h,k),b.lineTo(i,l),b.lineTo(j,m),b.closePath(),b.clip();var t=n*r+q*p+o*s-r*p-q*o-n*s,u=h*r+q*j+i*s-r*j-q*i-h*s,v=n*i+h*p+o*j-i*p-h*o-n*j,w=n*r*j+q*i*p+h*o*s-h*r*p-q*o*j-n*i*s,x=k*r+q*m+l*s-r*m-q*l-k*s,y=n*l+k*p+o*m-l*p-k*o-n*m,z=n*r*m+q*l*p+k*o*s-k*r*p-q*o*m-n*l*s;b.transform(u/t,x/t,v/t,y/t,w/t,z/t),b.drawImage(a.texture.baseTexture.source,0,0),b.restore()}},f.CanvasGraphics=function(){},f.CanvasGraphics.renderGraphics=function(a,b){for(var c=a.worldAlpha,d=0;d1&&(c=1,console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var d=0;1>d;d++){var e=a.graphicsData[d],g=e.points;if(e.type==f.Graphics.POLY){b.beginPath(),b.moveTo(g[0],g[1]);for(var h=1;hb?b:d,e=b+m>e?b+m:e,g=g>c?b:g,h=c+n>h?c+n:h}else if(k===f.Graphics.CIRC||k===f.Graphics.ELIP){b=a.x,c=a.y;var o=a.radius+l/2;d=d>b-o?b-o:d,e=b+o>e?b+o:e,g=g>c-o?c-o:g,h=c+o>h?c+o:h}else for(var p=0;pb-l?b-l:d,e=b+l>e?b+l:e,g=g>c-l?c-l:g,h=c+l>h?c+l:h}this.bounds=new f.Rectangle(d,g,e-d,h-g)}},f.Graphics.POLY=0,f.Graphics.RECT=1,f.Graphics.CIRC=2,f.Graphics.ELIP=3,f.Strip=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.blendMode=f.blendModes.NORMAL;try{this.uvs=new Float32Array([0,1,1,1,1,0,0,1]),this.verticies=new Float32Array([0,0,0,0,0,0,0,0,0]),this.colors=new Float32Array([1,1,1,1]),this.indices=new Uint16Array([0,1,2,3])}catch(d){this.uvs=[0,1,1,1,1,0,0,1],this.verticies=[0,0,0,0,0,0,0,0,0],this.colors=[1,1,1,1],this.indices=[0,1,2,3]}this.width=b,this.height=c,a.baseTexture.hasLoaded?(this.width=this.texture.frame.width,this.height=this.texture.frame.height,this.updateFrame=!0):(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Strip.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Strip.prototype.constructor=f.Strip,f.Strip.prototype.setTexture=function(a){this.texture=a,this.width=a.frame.width,this.height=a.frame.height,this.updateFrame=!0},f.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Rope=function(a,b){f.Strip.call(this,a),this.points=b;try{this.verticies=new Float32Array(4*b.length),this.uvs=new Float32Array(4*b.length),this.colors=new Float32Array(2*b.length),this.indices=new Uint16Array(2*b.length)}catch(c){this.verticies=verticies,this.uvs=uvs,this.colors=colors,this.indices=indices}this.refresh()},f.Rope.prototype=Object.create(f.Strip.prototype),f.Rope.prototype.constructor=f.Rope,f.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=this.indices,d=this.colors,e=a[0],f=a[0];this.count-=.2,b[0]=0,b[1]=1,b[2]=0,b[3]=1,d[0]=1,d[1]=1,c[0]=0,c[1]=1;for(var g=a.length,h=1;g>h;h++){var f=a[h],i=4*h,j=h/(g-1);h%2?(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1):(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1),i=2*h,d[i]=1,d[i+1]=1,i=2*h,c[i]=i,c[i+1]=i+1,e=f}}},f.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var b,c=this.verticies,d=a[0],e={x:0,y:0},g=a[0];this.count-=.2,c[0]=g.x+e.x,c[1]=g.y+e.y,c[2]=g.x-e.x,c[3]=g.y-e.y;for(var h=a.length,i=1;h>i;i++){var g=a[i],j=4*i;b=i1&&(k=1);var l=Math.sqrt(e.x*e.x+e.y*e.y),m=this.texture.height/2;e.x/=l,e.y/=l,e.x*=m,e.y*=m,c[j]=g.x+e.x,c[j+1]=g.y+e.y,c[j+2]=g.x-e.x,c[j+3]=g.y-e.y,d=g}f.DisplayObjectContainer.prototype.updateTransform.call(this)}},f.Rope.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.width=b,this.height=c,this.tileScale=new f.Point(1,1),this.tilePosition=new f.Point(0,0),this.renderable=!0,this.blendMode=f.blendModes.NORMAL},f.TilingSprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.TilingSprite.prototype.constructor=f.TilingSprite,f.TilingSprite.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Spine=function(a){if(f.DisplayObjectContainer.call(this),this.spineData=f.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new n.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new n.AnimationStateData(this.spineData),this.state=new n.AnimationState(this.stateData),this.slotContainers=[];for(var b=0,c=this.skeleton.drawOrder.length;c>b;b++){var d=this.skeleton.drawOrder[b],e=d.attachment,g=new f.DisplayObjectContainer;if(this.slotContainers.push(g),this.addChild(g),e instanceof n.RegionAttachment){var h=e.rendererObject.name,i=this.createSprite(d,e.rendererObject);d.currentSprite=i,d.currentSpriteName=h,g.addChild(i)}}},f.Spine.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Spine.prototype.constructor=f.Spine,f.Spine.prototype.updateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var b=this.skeleton.drawOrder,c=0,d=b.length;d>c;c++){var e=b[c],g=e.attachment,h=this.slotContainers[c];if(g instanceof n.RegionAttachment){if(g.rendererObject&&(!e.currentSpriteName||e.currentSpriteName!=g.name)){var i=g.rendererObject.name;if(void 0!==e.currentSprite&&(e.currentSprite.visible=!1),e.sprites=e.sprites||{},void 0!==e.sprites[i])e.sprites[i].visible=!0;else{var j=this.createSprite(e,g.rendererObject);h.addChild(j)}e.currentSprite=e.sprites[i],e.currentSpriteName=i}h.visible=!0;var k=e.bone;h.position.x=k.worldX+g.x*k.m00+g.y*k.m01,h.position.y=k.worldY+g.x*k.m10+g.y*k.m11,h.scale.x=k.worldScaleX,h.scale.y=k.worldScaleY,h.rotation=-(e.bone.worldRotation*Math.PI/180)}else h.visible=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.Spine.prototype.createSprite=function(a,b){var c=f.TextureCache[b.name]?b.name:b.name+".png",d=new f.Sprite(f.Texture.fromFrame(c));return d.scale=b.scale,d.rotation=b.rotation,d.anchor.x=d.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[b.name]=d,d};var n={};n.BoneData=function(a,b){this.name=a,this.parent=b},n.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1},n.SlotData=function(a,b){this.name=a,this.boneData=b},n.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null},n.Bone=function(a,b){this.data=a,this.parent=b,this.setToSetupPose()},n.Bone.yDown=!1,n.Bone.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,updateWorldTransform:function(a,b){var c=this.parent;null!=c?(this.worldX=this.x*c.m00+this.y*c.m01+c.worldX,this.worldY=this.x*c.m10+this.y*c.m11+c.worldY,this.worldScaleX=c.worldScaleX*this.scaleX,this.worldScaleY=c.worldScaleY*this.scaleY,this.worldRotation=c.worldRotation+this.rotation):(this.worldX=this.x,this.worldY=this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotation);var d=this.worldRotation*Math.PI/180,e=Math.cos(d),f=Math.sin(d);this.m00=e*this.worldScaleX,this.m10=f*this.worldScaleX,this.m01=-f*this.worldScaleY,this.m11=e*this.worldScaleY,a&&(this.m00=-this.m00,this.m01=-this.m01),b&&(this.m10=-this.m10,this.m11=-this.m11),n.Bone.yDown&&(this.m10=-this.m10,this.m11=-this.m11)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY}},n.Slot=function(a,b,c){this.data=a,this.skeleton=b,this.bone=c,this.setToSetupPose()},n.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,setAttachment:function(a){this.attachment=a,this._attachmentTime=this.skeleton.time},setAttachmentTime:function(a){this._attachmentTime=this.skeleton.time-a},getAttachmentTime:function(){return this.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},n.Skin=function(a){this.name=a,this.attachments={}},n.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},n.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},n.Animation.prototype={apply:function(a,b,c){c&&0!=this.duration&&(b%=this.duration);for(var d=this.timelines,e=0,f=d.length;f>e;e++)d[e].apply(a,b,1)},mix:function(a,b,c,d){c&&0!=this.duration&&(b%=this.duration);for(var e=this.timelines,f=0,g=e.length;g>f;f++)e[f].apply(a,b,d)}},n.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(0==e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},n.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},n.Curves=function(a){this.curves=[],this.curves.length=6*(a-1)},n.Curves.prototype={setLinear:function(a){this.curves[6*a]=0},setStepped:function(a){this.curves[6*a]=-1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=6*a,r=this.curves;r[q]=b*i+m*j+o*h,r[q+1]=c*i+n*j+p*h,r[q+2]=m*k+o*l,r[q+3]=n*k+p*l,r[q+4]=o*l,r[q+5]=p*l},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=6*a,d=this.curves,e=d[c];if(!e)return b;if(-1==e)return 0;for(var f=d[c+1],g=d[c+2],h=d[c+3],i=d[c+4],j=d[c+5],k=e,l=f,m=8;;){if(k>=b){var n=k-e,o=l-f;return o+(l-o)*(b-n)/(k-n)}if(0==m)break;m--,e+=g,f+=h,g+=i,h+=j,k+=e,l+=f}return l+(1-l)*(b-k)/(1-k)}},n.RotateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=2*a},n.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-2]){for(var f=e.data.rotation+d[d.length-1]-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;return e.rotation+=f*c,void 0}var g=n.binarySearch(d,b,2),h=d[g-1],i=d[g],j=1-(b-i)/(d[g-2]-i);j=this.curves.getCurvePercent(g/2-1,j);for(var f=d[g+1]-h;f>180;)f-=360;for(;-180>f;)f+=360;for(f=e.data.rotation+(h+f*j)-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;e.rotation+=f*c}}},n.TranslateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.x+=(e.data.x+d[d.length-2]-e.x)*c,e.y+=(e.data.y+d[d.length-1]-e.y)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.x+=(e.data.x+g+(d[f+1]-g)*j-e.x)*c,e.y+=(e.data.y+h+(d[f+2]-h)*j-e.y)*c}}},n.ScaleTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.scaleX+=(e.data.scaleX-1+d[d.length-2]-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+d[d.length-1]-e.scaleY)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.scaleX+=(e.data.scaleX-1+g+(d[f+1]-g)*j-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+h+(d[f+2]-h)*j-e.scaleY)*c}}},n.ColorTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=5*a},n.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(c,d){c*=5,this.frames[c]=d,this.frames[c+1]=r,this.frames[c+2]=g,this.frames[c+3]=b,this.frames[c+4]=a},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-5]){var f=d.length-1;return e.r=d[f-3],e.g=d[f-2],e.b=d[f-1],e.a=d[f],void 0}var g=n.binarySearch(d,b,5),h=d[g-4],i=d[g-3],j=d[g-2],k=d[g-1],l=d[g],m=1-(b-l)/(d[g-5]-l);m=this.curves.getCurvePercent(g/5-1,m);var o=h+(d[g+1]-h)*m,p=i+(d[g+2]-i)*m,q=j+(d[g+3]-j)*m,r=k+(d[g+4]-k)*m;1>c?(e.r+=(o-e.r)*c,e.g+=(p-e.g)*c,e.b+=(q-e.b)*c,e.a+=(r-e.a)*c):(e.r=o,e.g=p,e.b=q,e.a=r)}}},n.AttachmentTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},n.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b){var c=this.frames;if(!(b=c[c.length-1]?c.length-1:n.binarySearch(c,b,1)-1;var e=this.attachmentNames[d];a.slots[this.slotIndex].setAttachment(e?a.getAttachmentBySlotIndex(this.slotIndex,e):null)}}},n.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.animations=[]},n.SkeletonData.prototype={defaultSkin:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},n.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,c=a.bones.length;c>b;b++){var d=a.bones[b],e=d.parent?this.bones[a.bones.indexOf(d.parent)]:null;this.bones.push(new n.Bone(d,e))}this.slots=[],this.drawOrder=[];for(var b=0,c=a.slots.length;c>b;b++){var f=a.slots[b],g=this.bones[a.bones.indexOf(f.boneData)],h=new n.Slot(f,this,g);this.slots.push(h),this.drawOrder.push(h)}},n.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateWorldTransform:function(){for(var a=this.flipX,b=this.flipY,c=this.bones,d=0,e=c.length;e>d;d++)c[d].updateWorldTransform(a,b)},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose()},setSlotsToSetupPose:function(){for(var a=this.slots,b=0,c=a.length;c>b;b++)a[b].setToSetupPose(b)},getRootBone:function(){return 0==this.bones.length?null:this.bones[0]},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a);if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){this.skin&&a&&a._attachAll(this,this.skin),this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.size;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachment(d,b),null==g))throw"Attachment not found: "+b+", for slot: "+a;return f.setAttachment(g),void 0}}throw"Slot not found: "+a},update:function(a){time+=a}},n.AttachmentType={region:0},n.RegionAttachment=function(){this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},n.RegionAttachment.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,c=-this.width/2*this.scaleX+this.regionOffsetX*a,d=-this.height/2*this.scaleY+this.regionOffsetY*b,e=c+this.regionWidth*a,f=d+this.regionHeight*b,g=this.rotation*Math.PI/180,h=Math.cos(g),i=Math.sin(g),j=c*h+this.x,k=c*i,l=d*h+this.y,m=d*i,n=e*h+this.x,o=e*i,p=f*h+this.y,q=f*i,r=this.offset;r[0]=j-m,r[1]=l+k,r[2]=j-q,r[3]=p+k,r[4]=n-q,r[5]=p+o,r[6]=n-m,r[7]=l+o},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},n.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},n.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=this.animationToMixTime[a.name+":"+b.name];return c?c:this.defaultMix}},n.AnimationState=function(a){this.data=a,this.queue=[]},n.AnimationState.prototype={current:null,previous:null,currentTime:0,previousTime:0,currentLoop:!1,previousLoop:!1,mixTime:0,mixDuration:0,update:function(a){if(this.currentTime+=a,this.previousTime+=a,this.mixTime+=a,this.queue.length>0){var b=this.queue[0];this.currentTime>=b.delay&&(this._setAnimation(b.animation,b.loop),this.queue.shift())}},apply:function(a){if(this.current)if(this.previous){this.previous.apply(a,this.previousTime,this.previousLoop);var b=this.mixTime/this.mixDuration;b>=1&&(b=1,this.previous=null),this.current.mix(a,this.currentTime,this.currentLoop,b)}else this.current.apply(a,this.currentTime,this.currentLoop)},clearAnimation:function(){this.previous=null,this.current=null,this.queue.length=0},_setAnimation:function(a,b){this.previous=null,a&&this.current&&(this.mixDuration=this.data.getMix(this.current,a),this.mixDuration>0&&(this.mixTime=0,this.previous=this.current,this.previousTime=this.currentTime,this.previousLoop=this.currentLoop)),this.current=a,this.currentLoop=b,this.currentTime=0},setAnimationByName:function(a,b){var c=this.data.skeletonData.findAnimation(a);if(!c)throw"Animation not found: "+a;this.setAnimation(c,b)},setAnimation:function(a,b){this.queue.length=0,this._setAnimation(a,b)},addAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;this.addAnimation(d,b,c)},addAnimation:function(a,b,c){var d={};if(d.animation=a,d.loop=b,!c||0>=c){var e=0==this.queue.length?this.current:this.queue[this.queue.length-1].animation;c=null!=e?e.duration-this.data.getMix(e,a)+(c||0):0}d.delay=c,this.queue.push(d)},isComplete:function(){return!this.current||this.currentTime>=this.current.duration}},n.SkeletonJson=function(a){this.attachmentLoader=a},n.SkeletonJson.prototype={scale:1,readSkeletonData:function(a){for(var b=new n.SkeletonData,c=a.bones,d=0,e=c.length;e>d;d++){var f=c[d],g=null;if(f.parent&&(g=b.findBone(f.parent),!g))throw"Parent bone not found: "+f.parent;var h=new n.BoneData(f.name,g);h.length=(f.length||0)*this.scale,h.x=(f.x||0)*this.scale,h.y=(f.y||0)*this.scale,h.rotation=f.rotation||0,h.scaleX=f.scaleX||1,h.scaleY=f.scaleY||1,b.bones.push(h)}for(var i=a.slots,d=0,e=i.length;e>d;d++){var j=i[d],h=b.findBone(j.bone); -if(!h)throw"Slot bone not found: "+j.bone;var k=new n.SlotData(j.name,h),l=j.color;l&&(k.r=n.SkeletonJson.toColor(l,0),k.g=n.SkeletonJson.toColor(l,1),k.b=n.SkeletonJson.toColor(l,2),k.a=n.SkeletonJson.toColor(l,3)),k.attachmentName=j.attachment,b.slots.push(k)}var m=a.skins;for(var o in m)if(m.hasOwnProperty(o)){var p=m[o],q=new n.Skin(o);for(var r in p)if(p.hasOwnProperty(r)){var s=b.findSlotIndex(r),t=p[r];for(var u in t)if(t.hasOwnProperty(u)){var v=this.readAttachment(q,u,t[u]);null!=v&&q.addAttachment(s,u,v)}}b.skins.push(q),"default"==q.name&&(b.defaultSkin=q)}var w=a.animations;for(var x in w)w.hasOwnProperty(x)&&this.readAnimation(x,w[x],b);return b},readAttachment:function(a,b,c){b=c.name||b;var d=n.AttachmentType[c.type||"region"];if(d==n.AttachmentType.region){var e=new n.RegionAttachment;return e.x=(c.x||0)*this.scale,e.y=(c.y||0)*this.scale,e.scaleX=c.scaleX||1,e.scaleY=c.scaleY||1,e.rotation=c.rotation||0,e.width=(c.width||32)*this.scale,e.height=(c.height||32)*this.scale,e.updateOffset(),e.rendererObject={},e.rendererObject.name=b,e.rendererObject.scale={},e.rendererObject.scale.x=e.scaleX,e.rendererObject.scale.y=e.scaleY,e.rendererObject.rotation=-e.rotation*Math.PI/180,e}throw"Unknown attachment type: "+d},readAnimation:function(a,b,c){var d=[],e=0,f=b.bones;for(var g in f)if(f.hasOwnProperty(g)){var h=c.findBoneIndex(g);if(-1==h)throw"Bone not found: "+g;var i=f[g];for(var j in i)if(i.hasOwnProperty(j)){var k=i[j];if("rotate"==j){var l=new n.RotateTimeline(k.length);l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m,q.time,q.angle),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[2*l.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var l,r=1;"scale"==j?l=new n.ScaleTimeline(k.length):(l=new n.TranslateTimeline(k.length),r=this.scale),l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;l.setFrame(m,q.time,s,t),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[3*l.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var l=new n.ColorTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=n.SkeletonJson.toColor(y,0),A=n.SkeletonJson.toColor(y,1),B=n.SkeletonJson.toColor(y,2),C=n.SkeletonJson.toColor(y,3);l.setFrame(m,q.time,z,A,B,C),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[5*l.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var l=new n.AttachmentTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m++,q.time,q.name)}d.push(l),e=Math.max(e,l.frames[l.getFrameCount()-1])}}}c.animations.push(new n.Animation(a,d,e))}},n.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},n.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},n.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new n.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new n.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new n.AtlasPage,e.name=f,e.format=n.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=n.Atlas.TextureFilter[d[0]],e.magFilter=n.Atlas.TextureFilter[d[1]];var l=c.readValue();e.uWrap=n.Atlas.TextureWrap.clampToEdge,e.vWrap=n.Atlas.TextureWrap.clampToEdge,"x"==l?e.uWrap=n.Atlas.TextureWrap.repeat:"y"==l?e.vWrap=n.Atlas.TextureWrap.repeat:"xy"==l&&(e.uWrap=e.vWrap=n.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},n.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},n.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},n.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},n.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},n.AtlasPage=function(){},n.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},n.AtlasRegion=function(){},n.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},n.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},n.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},n.AtlasAttachmentLoader=function(a){this.atlas=a},n.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case n.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new n.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},n.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;h>16&255)/255,(a>>8&255)/255,(255&a)/255]}function d(a){return[(a>>16&255)/255,(a>>8&255)/255,(255&a)/255]}var e=this,f=f||{};f.Point=function(a,b){this.x=a||0,this.y=b||0},f.Point.prototype.clone=function(){return new f.Point(this.x,this.y)},f.Point.prototype.constructor=f.Point,f.Rectangle=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Rectangle.prototype.clone=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Rectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},f.Rectangle.prototype.constructor=f.Rectangle,f.Polygon=function(a){if(a instanceof Array||(a=Array.prototype.slice.call(arguments)),"number"==typeof a[0]){for(var b=[],c=0,d=a.length;d>c;c+=2)b.push(new f.Point(a[c],a[c+1]));a=b}this.points=a},f.Polygon.prototype.clone=function(){for(var a=[],b=0;bb!=i>b&&(h-f)*(b-g)/(i-g)+f>a;j&&(c=!c)}return c},f.Polygon.prototype.constructor=f.Polygon,f.Circle=function(a,b,c){this.x=a||0,this.y=b||0,this.radius=c||0},f.Circle.prototype.clone=function(){return new f.Circle(this.x,this.y,this.radius)},f.Circle.prototype.contains=function(a,b){if(this.radius<=0)return!1;var c=this.x-a,d=this.y-b,e=this.radius*this.radius;return c*=c,d*=d,e>=c+d},f.Circle.prototype.constructor=f.Circle,f.Ellipse=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Ellipse.prototype.clone=function(){return new f.Ellipse(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=(a-this.x)/this.width-.5,d=(b-this.y)/this.height-.5;return c*=c,d*=d,.25>c+d},f.Ellipse.getBounds=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.constructor=f.Ellipse,c(),f.mat3={},f.mat3.create=function(){var a=new f.Matrix(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat3.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat4={},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat3.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=b[0],n=b[1],o=b[2],p=b[3],q=b[4],r=b[5],s=b[6],t=b[7],u=b[8];return c[0]=m*d+n*g+o*j,c[1]=m*e+n*h+o*k,c[2]=m*f+n*i+o*l,c[3]=p*d+q*g+r*j,c[4]=p*e+q*h+r*k,c[5]=p*f+q*i+r*l,c[6]=s*d+t*g+u*j,c[7]=s*e+t*h+u*k,c[8]=s*f+t*i+u*l,c},f.mat3.clone=function(a){var b=new f.Matrix(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},f.mat3.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[5];return a[1]=a[3],a[2]=a[6],a[3]=c,a[5]=a[7],a[6]=d,a[7]=e,a}return b[0]=a[0],b[1]=a[3],b[2]=a[6],b[3]=a[1],b[4]=a[4],b[5]=a[7],b[6]=a[2],b[7]=a[5],b[8]=a[8],b},f.mat3.toMat4=function(a,b){return b||(b=f.mat4.create()),b[15]=1,b[14]=0,b[13]=0,b[12]=0,b[11]=0,b[10]=a[8],b[9]=a[7],b[8]=a[6],b[7]=0,b[6]=a[5],b[5]=a[4],b[4]=a[3],b[3]=0,b[2]=a[2],b[1]=a[1],b[0]=a[0],b},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat4.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[3],f=a[6],g=a[7],h=a[11];return a[1]=a[4],a[2]=a[8],a[3]=a[12],a[4]=c,a[6]=a[9],a[7]=a[13],a[8]=d,a[9]=f,a[11]=a[14],a[12]=e,a[13]=g,a[14]=h,a}return b[0]=a[0],b[1]=a[4],b[2]=a[8],b[3]=a[12],b[4]=a[1],b[5]=a[5],b[6]=a[9],b[7]=a[13],b[8]=a[2],b[9]=a[6],b[10]=a[10],b[11]=a[14],b[12]=a[3],b[13]=a[7],b[14]=a[11],b[15]=a[15],b},f.mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=b[0],u=b[1],v=b[2],w=b[3];return c[0]=t*d+u*h+v*l+w*p,c[1]=t*e+u*i+v*m+w*q,c[2]=t*f+u*j+v*n+w*r,c[3]=t*g+u*k+v*o+w*s,t=b[4],u=b[5],v=b[6],w=b[7],c[4]=t*d+u*h+v*l+w*p,c[5]=t*e+u*i+v*m+w*q,c[6]=t*f+u*j+v*n+w*r,c[7]=t*g+u*k+v*o+w*s,t=b[8],u=b[9],v=b[10],w=b[11],c[8]=t*d+u*h+v*l+w*p,c[9]=t*e+u*i+v*m+w*q,c[10]=t*f+u*j+v*n+w*r,c[11]=t*g+u*k+v*o+w*s,t=b[12],u=b[13],v=b[14],w=b[15],c[12]=t*d+u*h+v*l+w*p,c[13]=t*e+u*i+v*m+w*q,c[14]=t*f+u*j+v*n+w*r,c[15]=t*g+u*k+v*o+w*s,c},f.DisplayObject=function(){this.last=this,this.first=this,this.position=new f.Point,this.scale=new f.Point(1,1),this.pivot=new f.Point(0,0),this.rotation=0,this.alpha=1,this.visible=!0,this.hitArea=null,this.buttonMode=!1,this.renderable=!1,this.parent=null,this.stage=null,this.worldAlpha=1,this._interactive=!1,this.worldTransform=f.mat3.create(),this.localTransform=f.mat3.create(),this.color=[],this.dynamic=!0,this._sr=0,this._cr=1,this.filterArea=new f.Rectangle(0,0,1,1)},f.DisplayObject.prototype.constructor=f.DisplayObject,f.DisplayObject.prototype.setInteractive=function(a){this.interactive=a},Object.defineProperty(f.DisplayObject.prototype,"interactive",{get:function(){return this._interactive},set:function(a){this._interactive=a,this.stage&&(this.stage.dirty=!0)}}),Object.defineProperty(f.DisplayObject.prototype,"mask",{get:function(){return this._mask},set:function(a){a?this._mask?(a.start=this._mask.start,a.end=this._mask.end):(this.addFilter(a),a.renderable=!1):(this.removeFilter(this._mask),this._mask.renderable=!0),this._mask=a}}),Object.defineProperty(f.DisplayObject.prototype,"filters",{get:function(){return this._filters},set:function(a){if(a){this._filters&&this.removeFilter(this._filters),this.addFilter(a);for(var b=[],c=0;c=0&&b<=this.children.length))throw new Error(a+" The index "+b+" supplied is out of bounds "+this.children.length);if(void 0!=a.parent&&a.parent.removeChild(a),a.parent=this,this.stage){var c=a;do c.interactive&&(this.stage.dirty=!0),c.stage=this.stage,c=c._iNext;while(c)}var d,e,f=a.first,g=a.last;if(b==this.children.length){e=this.last;for(var h=this,i=this.last;h;)h.last==i&&(h.last=a.last),h=h.parent}else e=0==b?this:this.children[b-1].last;d=e._iNext,d&&(d._iPrev=g,g._iNext=d),f._iPrev=e,e._iNext=f,this.children.splice(b,0,a),this.__renderGroup&&(a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a),this.__renderGroup.addDisplayObjectAndChildren(a))},f.DisplayObjectContainer.prototype.swapChildren=function(){},f.DisplayObjectContainer.prototype.getChildAt=function(a){if(a>=0&&aa;a++)this.children[a].updateTransform()}},f.blendModes={},f.blendModes.NORMAL=0,f.blendModes.SCREEN=1,f.Sprite=function(a){f.DisplayObjectContainer.call(this),this.anchor=new f.Point,this.texture=a,this.blendMode=f.blendModes.NORMAL,this._width=0,this._height=0,a.baseTexture.hasLoaded?this.updateFrame=!0:(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Sprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Sprite.prototype.constructor=f.Sprite,Object.defineProperty(f.Sprite.prototype,"width",{get:function(){return this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(f.Sprite.prototype,"height",{get:function(){return this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),f.Sprite.prototype.setTexture=function(a){this.texture.baseTexture!=a.baseTexture?(this.textureChange=!0,this.texture=a,this.__renderGroup&&this.__renderGroup.updateTexture(this)):this.texture=a,this.updateFrame=!0},f.Sprite.prototype.onTextureUpdate=function(){this._width&&(this.scale.x=this._width/this.texture.frame.width),this._height&&(this.scale.y=this._height/this.texture.frame.height),this.updateFrame=!0},f.Sprite.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache"+this);return new f.Sprite(b)},f.Sprite.fromImage=function(a){var b=f.Texture.fromImage(a);return new f.Sprite(b)},f.MovieClip=function(a){f.Sprite.call(this,a[0]),this.textures=a,this.animationSpeed=1,this.loop=!0,this.onComplete=null,this.currentFrame=0,this.playing=!1},f.MovieClip.prototype=Object.create(f.Sprite.prototype),f.MovieClip.prototype.constructor=f.MovieClip,Object.defineProperty(f.MovieClip.prototype,"totalFrames",{get:function(){return this.textures.length}}),f.MovieClip.prototype.stop=function(){this.playing=!1},f.MovieClip.prototype.play=function(){this.playing=!0},f.MovieClip.prototype.gotoAndStop=function(a){this.playing=!1,this.currentFrame=a;var b=this.currentFrame+.5|0;this.setTexture(this.textures[b%this.textures.length])},f.MovieClip.prototype.gotoAndPlay=function(a){this.currentFrame=a,this.playing=!0},f.MovieClip.prototype.updateTransform=function(){if(f.Sprite.prototype.updateTransform.call(this),this.playing){this.currentFrame+=this.animationSpeed;var a=this.currentFrame+.5|0;this.loop||a=this.textures.length&&(this.gotoAndStop(this.textures.length-1),this.onComplete&&this.onComplete())}},f.FilterBlock=function(){this.visible=!0,this.renderable=!0},f.Text=function(a,b){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),f.Sprite.call(this,f.Texture.fromCanvas(this.canvas)),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.Text.prototype=Object.create(f.Sprite.prototype),f.Text.prototype.constructor=f.Text,f.Text.prototype.setStyle=function(a){a=a||{},a.font=a.font||"bold 20pt Arial",a.fill=a.fill||"black",a.align=a.align||"left",a.stroke=a.stroke||"black",a.strokeThickness=a.strokeThickness||0,a.wordWrap=a.wordWrap||!1,a.wordWrapWidth=a.wordWrapWidth||100,this.style=a,this.dirty=!0},f.Text.prototype.setText=function(a){this.text=a.toString()||" ",this.dirty=!0},f.Text.prototype.updateText=function(){this.context.font=this.style.font;var a=this.text;this.style.wordWrap&&(a=this.wordWrap(this.text));for(var b=a.split(/(?:\r\n|\r|\n)/),c=[],d=0,e=0;ee?(g>0&&(b+="\n"),b+=f[g]+" ",e=this.style.wordWrapWidth-h):(e-=i,b+=f[g]+" ")}b+="\n"}return b},f.Text.prototype.destroy=function(a){a&&this.texture.destroy()},f.Text.heightCache={},f.BitmapText=function(a,b){f.DisplayObjectContainer.call(this),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.BitmapText.prototype=Object.create(f.DisplayObjectContainer.prototype),f.BitmapText.prototype.constructor=f.BitmapText,f.BitmapText.prototype.setText=function(a){this.text=a||" ",this.dirty=!0},f.BitmapText.prototype.setStyle=function(a){a=a||{},a.align=a.align||"left",this.style=a;var b=a.font.split(" ");this.fontName=b[b.length-1],this.fontSize=b.length>=2?parseInt(b[b.length-2],10):f.BitmapText.fonts[this.fontName].size,this.dirty=!0},f.BitmapText.prototype.updateText=function(){for(var a=f.BitmapText.fonts[this.fontName],b=new f.Point,c=null,d=[],e=0,g=[],h=0,i=this.fontSize/a.size,j=0;j=j;j++){var n=0;"right"==this.style.align?n=e-g[j]:"center"==this.style.align&&(n=(e-g[j])/2),m.push(n)}for(j=0;j0;)this.removeChild(this.getChildAt(0));this.updateText(),this.dirty=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.BitmapText.fonts={},f.InteractionManager=function(a){this.stage=a,this.mouse=new f.InteractionData,this.touchs={},this.tempPoint=new f.Point,this.mouseoverEnabled=!0,this.pool=[],this.interactiveItems=[],this.interactionDOMElement=null,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseOut=this.onMouseOut.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.last=0},f.InteractionManager.prototype.constructor=f.InteractionManager,f.InteractionManager.prototype.collectInteractiveSprite=function(a,b){for(var c=a.children,d=c.length,e=d-1;e>=0;e--){var f=c[e];f.interactive?(b.interactiveChildren=!0,this.interactiveItems.push(f),f.children.length>0&&this.collectInteractiveSprite(f,f)):(f.__iParent=null,f.children.length>0&&this.collectInteractiveSprite(f,b))}},f.InteractionManager.prototype.setTarget=function(a){this.target=a,null===this.interactionDOMElement&&this.setTargetDomElement(a.view),document.body.addEventListener("mouseup",this.onMouseUp,!0)},f.InteractionManager.prototype.setTargetDomElement=function(a){null!==this.interactionDOMElement&&(this.interactionDOMElement.style["-ms-content-zooming"]="",this.interactionDOMElement.style["-ms-touch-action"]="",this.interactionDOMElement.removeEventListener("mousemove",this.onMouseMove,!0),this.interactionDOMElement.removeEventListener("mousedown",this.onMouseDown,!0),this.interactionDOMElement.removeEventListener("mouseout",this.onMouseOut,!0),this.interactionDOMElement.removeEventListener("touchstart",this.onTouchStart,!0),this.interactionDOMElement.removeEventListener("touchend",this.onTouchEnd,!0),this.interactionDOMElement.removeEventListener("touchmove",this.onTouchMove,!0)),window.navigator.msPointerEnabled&&(a.style["-ms-content-zooming"]="none",a.style["-ms-touch-action"]="none"),this.interactionDOMElement=a,a.addEventListener("mousemove",this.onMouseMove,!0),a.addEventListener("mousedown",this.onMouseDown,!0),a.addEventListener("mouseout",this.onMouseOut,!0),a.addEventListener("touchstart",this.onTouchStart,!0),a.addEventListener("touchend",this.onTouchEnd,!0),a.addEventListener("touchmove",this.onTouchMove,!0)},f.InteractionManager.prototype.update=function(){if(this.target){var a=Date.now(),b=a-this.last;if(b=30*b/1e3,!(1>b)){if(this.last=a,this.dirty){this.dirty=!1;for(var c=this.interactiveItems.length,d=0;c>d;d++)this.interactiveItems[d].interactiveChildren=!1;this.interactiveItems=[],this.stage.interactive&&this.interactiveItems.push(this.stage),this.collectInteractiveSprite(this.stage,this.stage)}var e=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var d=0;e>d;d++){var f=this.interactiveItems[d];(f.mouseover||f.mouseout||f.buttonMode)&&(f.__hit=this.hitTest(f,this.mouse),this.mouse.target=f,f.__hit?(f.buttonMode&&(this.interactionDOMElement.style.cursor="pointer"),f.__isOver||(f.mouseover&&f.mouseover(this.mouse),f.__isOver=!0)):f.__isOver&&(f.mouseout&&f.mouseout(this.mouse),f.__isOver=!1))}}}},f.InteractionManager.prototype.onMouseMove=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactionDOMElement.getBoundingClientRect();this.mouse.global.x=(a.clientX-b.left)*(this.target.width/b.width),this.mouse.global.y=(a.clientY-b.top)*(this.target.height/b.height);for(var c=this.interactiveItems.length,d=(this.mouse.global,0);c>d;d++){var e=this.interactiveItems[d];e.mousemove&&e.mousemove(this.mouse)}},f.InteractionManager.prototype.onMouseDown=function(a){this.mouse.originalEvent=a||window.event;for(var b=this.interactiveItems.length,c=(this.mouse.global,this.stage,0);b>c;c++){var d=this.interactiveItems[c];if((d.mousedown||d.click)&&(d.__mouseIsDown=!0,d.__hit=this.hitTest(d,this.mouse),d.__hit&&(d.mousedown&&d.mousedown(this.mouse),d.__isDown=!0,!d.interactiveChildren)))break}},f.InteractionManager.prototype.onMouseOut=function(){var a=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var b=0;a>b;b++){var c=this.interactiveItems[b];c.__isOver&&(this.mouse.target=c,c.mouseout&&c.mouseout(this.mouse),c.__isOver=!1)}},f.InteractionManager.prototype.onMouseUp=function(a){this.mouse.originalEvent=a||window.event;for(var b=(this.mouse.global,this.interactiveItems.length),c=!1,d=0;b>d;d++){var e=this.interactiveItems[d];(e.mouseup||e.mouseupoutside||e.click)&&(e.__hit=this.hitTest(e,this.mouse),e.__hit&&!c?(e.mouseup&&e.mouseup(this.mouse),e.__isDown&&e.click&&e.click(this.mouse),e.interactiveChildren||(c=!0)):e.__isDown&&e.mouseupoutside&&e.mouseupoutside(this.mouse),e.__isDown=!1)}},f.InteractionManager.prototype.hitTest=function(a,b){var c=b.global;if(a.vcount!==f.visibleCount)return!1;var d=a instanceof f.Sprite,e=a.worldTransform,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=1/(g*k+h*-j),n=k*m*c.x+-h*m*c.y+(l*h-i*k)*m,o=g*m*c.y+-j*m*c.x+(-l*g+i*j)*m;if(b.target=a,a.hitArea&&a.hitArea.contains)return a.hitArea.contains(n,o)?(b.target=a,!0):!1;if(d){var p,q=a.texture.frame.width,r=a.texture.frame.height,s=-q*a.anchor.x;if(n>s&&s+q>n&&(p=-r*a.anchor.y,o>p&&p+r>o))return b.target=a,!0}for(var t=a.children.length,u=0;t>u;u++){var v=a.children[u],w=this.hitTest(v,b);if(w)return b.target=a,!0}return!1},f.InteractionManager.prototype.onTouchMove=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;dd;d++){var h=this.interactiveItems[d];h.touchmove&&h.touchmove(f)}},f.InteractionManager.prototype.onTouchStart=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i];if((j.touchstart||j.tap)&&(j.__hit=this.hitTest(j,g),j.__hit&&(j.touchstart&&j.touchstart(g),j.__isDown=!0,j.__touchData=g,!j.interactiveChildren)))break}}},f.InteractionManager.prototype.onTouchEnd=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i],k=j.__touchData;j.__hit=this.hitTest(j,f),k==f&&(f.originalEvent=a||window.event,(j.touchend||j.tap)&&(j.__hit&&!g?(j.touchend&&j.touchend(f),j.__isDown&&j.tap&&j.tap(f),j.interactiveChildren||(g=!0)):j.__isDown&&j.touchendoutside&&j.touchendoutside(f),j.__isDown=!1),j.__touchData=null)}this.pool.push(f),this.touchs[e.identifier]=null}},f.InteractionData=function(){this.global=new f.Point,this.local=new f.Point,this.target,this.originalEvent},f.InteractionData.prototype.getLocalPosition=function(a){var b=a.worldTransform,c=this.global,d=b[0],e=b[1],g=b[2],h=b[3],i=b[4],j=b[5],k=1/(d*i+e*-h);return new f.Point(i*k*c.x+-e*k*c.y+(j*e-g*i)*k,d*k*c.y+-h*k*c.x+(-j*d+g*h)*k)},f.InteractionData.prototype.constructor=f.InteractionData,f.Stage=function(a){f.DisplayObjectContainer.call(this),this.worldTransform=f.mat3.create(),this.interactive=!0,this.interactionManager=new f.InteractionManager(this),this.dirty=!0,this.__childrenAdded=[],this.__childrenRemoved=[],this.stage=this,this.stage.hitArea=new f.Rectangle(0,0,1e5,1e5),this.setBackgroundColor(a),this.worldVisible=!0},f.Stage.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Stage.prototype.constructor=f.Stage,f.Stage.prototype.setInteractionDelegate=function(a){this.interactionManager.setTargetDomElement(a)},f.Stage.prototype.updateTransform=function(){this.worldAlpha=1,this.vcount=f.visibleCount;for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform();this.dirty&&(this.dirty=!1,this.interactionManager.dirty=!0),this.interactive&&this.interactionManager.update()},f.Stage.prototype.setBackgroundColor=function(a){this.backgroundColor=a||0,this.backgroundColorSplit=d(this.backgroundColor);var b=this.backgroundColor.toString(16);b="000000".substr(0,6-b.length)+b,this.backgroundColorString="#"+b},f.Stage.prototype.getMousePosition=function(){return this.interactionManager.mouse.global};for(var h=0,i=["ms","moz","webkit","o"],j=0;j>>>>>>>>"),console.log("_");var b=0,c=a.first;for(console.log(c);c._iNext;)if(b++,c=c._iNext,console.log(c),b>100){console.log("BREAK");break}},f.EventTarget=function(){var a={};this.addEventListener=this.on=function(b,c){void 0===a[b]&&(a[b]=[]),-1===a[b].indexOf(c)&&a[b].push(c)},this.dispatchEvent=this.emit=function(b){if(a[b.type]&&a[b.type].length)for(var c=0,d=a[b.type].length;d>c;c++)a[b.type][c](b)},this.removeEventListener=this.off=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)}},f.autoDetectRenderer=function(a,b,c,d,e){a||(a=800),b||(b=600);var g=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}();if(g){var h=-1!=navigator.userAgent.toLowerCase().indexOf("msie");g=!h}return g?new f.WebGLRenderer(a,b,c,d,e):new f.CanvasRenderer(a,b,c,d)},f.PolyK={},f.PolyK.Triangulate=function(a){var b=!0,c=a.length>>1;if(3>c)return[];for(var d=[],e=[],g=0;c>g;g++)e.push(g);for(var g=0,h=c;h>3;){var i=e[(g+0)%h],j=e[(g+1)%h],k=e[(g+2)%h],l=a[2*i],m=a[2*i+1],n=a[2*j],o=a[2*j+1],p=a[2*k],q=a[2*k+1],r=!1;if(f.PolyK._convex(l,m,n,o,p,q,b)){r=!0;for(var s=0;h>s;s++){var t=e[s];if(t!=i&&t!=j&&t!=k&&f.PolyK._PointInTriangle(a[2*t],a[2*t+1],l,m,n,o,p,q)){r=!1;break}}}if(r)d.push(i,j,k),e.splice((g+1)%h,1),h--,g=0;else if(g++>3*h){if(!b)return console.log("PIXI Warning: shape too complex to fill"),[];var d=[];e=[];for(var g=0;c>g;g++)e.push(g);g=0,h=c,b=!1}}return d.push(e[0],e[1],e[2]),d},f.PolyK._PointInTriangle=function(a,b,c,d,e,f,g,h){var i=g-c,j=h-d,k=e-c,l=f-d,m=a-c,n=b-d,o=i*i+j*j,p=i*k+j*l,q=i*m+j*n,r=k*k+l*l,s=k*m+l*n,t=1/(o*r-p*p),u=(r*q-p*s)*t,v=(o*s-p*q)*t;return u>=0&&v>=0&&1>u+v},f.PolyK._convex=function(a,b,c,d,e,f,g){return(b-d)*(e-c)+(c-a)*(f-d)>=0==g},f.initDefaultShaders=function(){f.primitiveShader=new f.PrimitiveShader,f.primitiveShader.init(),f.stripShader=new f.StripShader,f.stripShader.init(),f.defaultShader=new f.PixiShader,f.defaultShader.init();var a=f.gl,b=f.defaultShader.program;a.useProgram(b),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.primitiveShader.program),a.disableVertexAttribArray(f.defaultShader.aVertexPosition),a.disableVertexAttribArray(f.defaultShader.colorAttribute),a.disableVertexAttribArray(f.defaultShader.aTextureCoord),a.enableVertexAttribArray(f.primitiveShader.aVertexPosition),a.enableVertexAttribArray(f.primitiveShader.colorAttribute)},f.deactivatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program),a.disableVertexAttribArray(f.primitiveShader.aVertexPosition),a.disableVertexAttribArray(f.primitiveShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activateStripShader=function(){var a=f.gl;a.useProgram(f.stripShader.program)},f.deactivateStripShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program)},f.CompileVertexShader=function(a,b){return f._CompileShader(a,b,a.VERTEX_SHADER)},f.CompileFragmentShader=function(a,b){return f._CompileShader(a,b,a.FRAGMENT_SHADER)},f._CompileShader=function(a,b,c){var d=b.join("\n"),e=a.createShader(c);return a.shaderSource(e,d),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)?e:(console.log(a.getShaderInfoLog(e)),null)},f.compileProgram=function(a,b){var c=f.gl,d=f.CompileFragmentShader(c,b),e=f.CompileVertexShader(c,a),g=c.createProgram();return c.attachShader(g,e),c.attachShader(g,d),c.linkProgram(g),c.getProgramParameter(g,c.LINK_STATUS)||console.log("Could not initialise shaders"),g},f.PixiShader=function(){this.program,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;","}"],this.textureCount=0},f.PixiShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc||f.PixiShader.defaultVertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"); +for(var c in this.uniforms)this.uniforms[c].uniformLocation=b.getUniformLocation(a,c);this.program=a},f.PixiShader.prototype.syncUniforms=function(){this.textureCount=1;var a=f.gl;for(var b in this.uniforms){var c=this.uniforms[b].type,d=!1;if(this.uniforms[b].transpose&&(d=this.uniforms[b].transpose),"1f"==c)a.uniform1f(this.uniforms[b].uniformLocation,this.uniforms[b].value);else if("1fv"==c)a.uniform1fv(this.uniforms[b].uniformLocation,this.uniforms[b].value);else if("1i"==c)a.uniform1i(this.uniforms[b].uniformLocation,this.uniforms[b].value);else if("1iv"==c)a.uniform1i(this.uniforms[b].uniformLocation,this.uniforms[b].value);else if("2f"==c)a.uniform2f(this.uniforms[b].uniformLocation,this.uniforms[b].value.x,this.uniforms[b].value.y);else if("2fv"==c)a.uniform2fv(this.uniforms[b].uniformLocation,this.uniforms[b].value);else if("2i"==c)a.uniform2i(this.uniforms[b].uniformLocation,this.uniforms[b].value.x,this.uniforms[b].value.y);else if("2iv"==c)a.uniform2iv(this.uniforms[b].uniformLocation,this.uniforms[b].value);else if("3f"==c)a.uniform3f(this.uniforms[b].uniformLocation,this.uniforms[b].value.x,this.uniforms[b].value.y,this.uniforms[b].value.z);else if("3fv"==c)a.uniform3fv(this.uniforms[b].uniformLocation,this.uniforms[b].value);else if("3i"==c)a.uniform3i(this.uniforms[b].uniformLocation,this.uniforms[b].value.x,this.uniforms[b].value.y,this.uniforms[b].value.z);else if("3iv"==c)a.uniform3iv(this.uniforms[b].uniformLocation,this.uniforms[b].value);else if("4f"==c)a.uniform4f(this.uniforms[b].uniformLocation,this.uniforms[b].value.x,this.uniforms[b].value.y,this.uniforms[b].value.z,this.uniforms[b].value.w);else if("4fv"==c)a.uniform4fv(this.uniforms[b].uniformLocation,this.uniforms[b].value);else if("4i"==c)a.uniform4i(this.uniforms[b].uniformLocation,this.uniforms[b].value.x,this.uniforms[b].value.y,this.uniforms[b].value.z,this.uniforms[b].value.w);else if("4iv"==c)a.uniform4iv(this.uniforms[b].uniformLocation,this.uniforms[b].value);else if("mat2"==c)a.uniformMatrix2fv(this.uniforms[b].uniformLocation,d,this.uniforms[b].value);else if("mat3"==c)a.uniformMatrix3fv(this.uniforms[b].uniformLocation,d,this.uniforms[b].value);else if("mat4"==c)a.uniformMatrix4fv(this.uniforms[b].uniformLocation,d,this.uniforms[b].value);else if("sampler2D"==c&&this.uniforms[b].value.baseTexture.hasLoaded){var e=this.uniforms[b].value.baseTexture._glTexture,g=this.uniforms[b].value.baseTexture.source,h=a.RGBA;this.uniforms[b].format&&"luminance"==this.uniforms[b].format&&(h=a.LUMINANCE),a.activeTexture(a["TEXTURE"+this.textureCount]),this.uniforms[b].wrap?"no-repeat"==this.uniforms[b].wrap||this.uniforms[b].wrap===!1?this.createGLTextureLinear(a,g,e):"repeat"==this.uniforms[b].wrap||this.uniforms[b].wrap===!0?this.createGLTexture(a,g,h,e):"nearest-repeat"==this.uniforms[b].wrap?this.createGLTextureNearestRepeat(a,g,e):"nearest"==this.uniforms[b].wrap?this.createGLTextureNearest(a,g,e):"audio"==this.uniforms[b].wrap?this.createAudioTexture(a,e):"keyboard"==this.uniforms[b].wrap&&this.createKeyboardTexture(a,e):this.createGLTextureLinear(a,g,e),a.uniform1i(this.uniforms[b].uniformLocation,this.textureCount),this.textureCount++}}},f.PixiShader.prototype.createGLTexture=function(a,b,c,d){a.bindTexture(a.TEXTURE_2D,d),a.pixelStorei(a.UNPACK_FLIP_Y_WEBGL,!1),a.texImage2D(a.TEXTURE_2D,0,c,a.RGBA,a.UNSIGNED_BYTE,b),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR_MIPMAP_LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.REPEAT),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.REPEAT),a.generateMipmap(a.TEXTURE_2D)},f.PixiShader.prototype.createGLTextureLinear=function(a,b,c){a.bindTexture(a.TEXTURE_2D,c),a.pixelStorei(a.UNPACK_FLIP_Y_WEBGL,!1),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,a.RGBA,a.UNSIGNED_BYTE,b),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE)},f.PixiShader.prototype.createGLTextureNearestRepeat=function(a,b,c){a.bindTexture(a.TEXTURE_2D,c),a.pixelStorei(a.UNPACK_FLIP_Y_WEBGL,!1),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,a.RGBA,a.UNSIGNED_BYTE,b),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.NEAREST),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.NEAREST),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.REPEAT),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.REPEAT)},f.PixiShader.prototype.createGLTextureNearest=function(a,b,c){a.bindTexture(a.TEXTURE_2D,c),a.pixelStorei(a.UNPACK_FLIP_Y_WEBGL,!1),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,a.RGBA,a.UNSIGNED_BYTE,b),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.NEAREST),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.NEAREST),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE)},f.PixiShader.prototype.createAudioTexture=function(a,b){a.bindTexture(a.TEXTURE_2D,b),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),a.texImage2D(a.TEXTURE_2D,0,a.LUMINANCE,512,2,0,a.LUMINANCE,a.UNSIGNED_BYTE,null)},f.PixiShader.prototype.createKeyboardTexture=function(a,b){a.bindTexture(a.TEXTURE_2D,b),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.NEAREST),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.NEAREST),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),a.texImage2D(a.TEXTURE_2D,0,a.LUMINANCE,256,2,0,a.LUMINANCE,a.UNSIGNED_BYTE,null)},f.PixiShader.defaultVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","varying float vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"],f.StripShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying float vColor;","uniform float alpha;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));","gl_FragColor = gl_FragColor * alpha;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","varying vec2 vTextureCoord;","varying vec2 offsetVector;","varying float vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"]},f.StripShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.PrimitiveShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","gl_FragColor = vColor;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec4 aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform float alpha;","varying vec4 vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","vColor = aColor * alpha;","}"]},f.PrimitiveShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.WebGLGraphics=function(){},f.WebGLGraphics.renderGraphics=function(a,b){var c=f.gl;a._webGL||(a._webGL={points:[],indices:[],lastIndex:0,buffer:c.createBuffer(),indexBuffer:c.createBuffer()}),a.dirty&&(a.dirty=!1,a.clearDirty&&(a.clearDirty=!1,a._webGL.lastIndex=0,a._webGL.points=[],a._webGL.indices=[]),f.WebGLGraphics.updateGraphics(a)),f.activatePrimitiveShader();var d=f.mat3.clone(a.worldTransform);f.mat3.transpose(d),c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA),c.uniformMatrix3fv(f.primitiveShader.translationMatrix,!1,d),c.uniform2f(f.primitiveShader.projectionVector,b.x,-b.y),c.uniform2f(f.primitiveShader.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(f.primitiveShader.alpha,a.worldAlpha),c.bindBuffer(c.ARRAY_BUFFER,a._webGL.buffer),c.vertexAttribPointer(f.primitiveShader.aVertexPosition,2,c.FLOAT,!1,24,0),c.vertexAttribPointer(f.primitiveShader.colorAttribute,4,c.FLOAT,!1,24,8),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),c.drawElements(c.TRIANGLE_STRIP,a._webGL.indices.length,c.UNSIGNED_SHORT,0),f.deactivatePrimitiveShader()},f.WebGLGraphics.updateGraphics=function(a){for(var b=a._webGL.lastIndex;b3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){if(a.lineWidth%2)for(var e=0;ee;e++)k=c[2*(e-1)],l=c[2*(e-1)+1],m=c[2*e],n=c[2*e+1],o=c[2*(e+1)],p=c[2*(e+1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,s=-(n-p),t=m-o,E=Math.sqrt(s*s+t*t),s/=E,t/=E,s*=K,t*=K,w=-r+l-(-r+n),x=-q+m-(-q+k),y=(-q+k)*(-r+n)-(-q+m)*(-r+l),z=-t+p-(-t+n),A=-s+m-(-s+o),B=(-s+o)*(-t+n)-(-s+m)*(-t+p),C=w*A-z*x,Math.abs(C)<.1?(C+=10.1,F.push(m-q,n-r,N,O,P,M),F.push(m+q,n+r,N,O,P,M)):(px=(x*B-A*y)/C,py=(z*y-w*B)/C,D=(px-m)*(px-m)+(py-n)+(py-n),D>19600?(u=q-s,v=r-t,E=Math.sqrt(u*u+v*v),u/=E,v/=E,u*=K,v*=K,F.push(m-u,n-v),F.push(N,O,P,M),F.push(m+u,n+v),F.push(N,O,P,M),F.push(m-u,n-v),F.push(N,O,P,M),I++):(F.push(px,py),F.push(N,O,P,M),F.push(m-(px-m),n-(py-n)),F.push(N,O,P,M)));k=c[2*(H-2)],l=c[2*(H-2)+1],m=c[2*(H-1)],n=c[2*(H-1)+1],q=-(l-n),r=k-m,E=Math.sqrt(q*q+r*r),q/=E,r/=E,q*=K,r*=K,F.push(m-q,n-r),F.push(N,O,P,M),F.push(m+q,n+r),F.push(N,O,P,M),G.push(J);for(var e=0;I>e;e++)G.push(J++);G.push(J-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl,this.transparent)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl;this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},flip=!1;var l=[],m=0;f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;if(a.open)a.data instanceof Array?this.filterManager.pushFilter(a):(m++,l.push(a),c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.INCR),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP));else if(a.data instanceof Array)this.filterManager.popFilter();else{var d=l.pop(a);d&&(c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,1),c.stencilOp(c.KEEP,c.KEEP,c.DECR),f.WebGLGraphics.renderGraphics(d.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,l.length),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)),c.disable(c.STENCIL_TEST)}},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){{a.last}do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader,e=(d.program,f.mat3.clone(a.worldTransform));f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader() +},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl,d=(f.shaderProgram,a.tilePosition),e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){{var b=this.gl;this.shaderProgram}a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(a){this.transparent=a,this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;hs?s:E,E=E>t?t:E,E=E>u?u:E,E=E>v?v:E,F=F>w?w:F,F=F>x?x:F,F=F>y?y:F,F=F>z?z:F,C=s>C?s:C,C=t>C?t:C,C=u>C?u:C,C=v>C?v:C,D=w>D?w:D,D=x>D?x:D,D=y>D?y:D,D=z>D?z:D),l=!1,A=A._iNext}while(A!=B);a.filterArea.x=E,a.filterArea.y=F,a.filterArea.width=C-E,a.filterArea.height=D-F},f.FilterTexture=function(a,b){var c=f.gl;this.frameBuffer=c.createFramebuffer(),this.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,this.texture),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.bindFramebuffer(c.FRAMEBUFFER,this.framebuffer),c.bindFramebuffer(c.FRAMEBUFFER,this.frameBuffer),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,this.texture,0),this.resize(a,b)},f.FilterTexture.prototype.resize=function(a,b){this.width=a,this.height=b;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a,b,0,c.RGBA,c.UNSIGNED_BYTE,null)},f.CanvasRenderer=function(a,b,c,d){this.transparent=d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.context=this.view.getContext("2d"),this.refresh=!0,this.view.width=this.width,this.view.height=this.height,this.count=0},f.CanvasRenderer.prototype.constructor=f.CanvasRenderer,f.CanvasRenderer.prototype.render=function(a){f.texturesToUpdate=[],f.texturesToDestroy=[],f.visibleCount++,a.updateTransform(),this.view.style.backgroundColor==a.backgroundColorString||this.transparent||(this.view.style.backgroundColor=a.backgroundColorString),this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.width,this.height),this.renderDisplayObject(a),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0&&(f.Texture.frameUpdates=[])},f.CanvasRenderer.prototype.resize=function(a,b){this.width=a,this.height=b,this.view.width=a,this.view.height=b},f.CanvasRenderer.prototype.renderDisplayObject=function(a){var b,c=this.context;c.globalCompositeOperation="source-over";var d=a.last._iNext;a=a.first;do if(b=a.worldTransform,a.visible)if(a.renderable){if(a instanceof f.Sprite){var e=a.texture.frame;e&&e.width&&e.height&&(c.globalAlpha=a.worldAlpha,c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),c.drawImage(a.texture.baseTexture.source,e.x,e.y,e.width,e.height,a.anchor.x*-e.width,a.anchor.y*-e.height,e.width,e.height))}else if(a instanceof f.Strip)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderStrip(a);else if(a instanceof f.TilingSprite)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderTilingSprite(a);else if(a instanceof f.CustomRenderable)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),a.renderCanvas(this);else if(a instanceof f.Graphics)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),f.CanvasGraphics.renderGraphics(a,c);else if(a instanceof f.FilterBlock&&a.data instanceof f.Graphics){var g=a.data;if(a.open){c.save();var h=g.alpha,i=g.worldTransform;c.setTransform(i[0],i[3],i[1],i[4],i[2],i[5]),g.worldAlpha=.5,c.worldAlpha=0,f.CanvasGraphics.renderGraphicsMask(g,c),c.clip(),g.worldAlpha=h}else c.restore()}a=a._iNext}else a=a._iNext;else a=a.last._iNext;while(a!=d)},f.CanvasRenderer.prototype.renderStripFlat=function(a){var b=this.context,c=a.verticies,d=(a.uvs,c.length/2);this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},f.CanvasRenderer.prototype.renderTilingSprite=function(a){var b=this.context;b.globalAlpha=a.worldAlpha,a.__tilePattern||(a.__tilePattern=b.createPattern(a.texture.baseTexture.source,"repeat")),b.beginPath();var c=a.tilePosition,d=a.tileScale;b.scale(d.x,d.y),b.translate(c.x,c.y),b.fillStyle=a.__tilePattern,b.fillRect(-c.x,-c.y,a.width/d.x,a.height/d.y),b.scale(1/d.x,1/d.y),b.translate(-c.x,-c.y),b.closePath()},f.CanvasRenderer.prototype.renderStrip=function(a){var b=this.context,c=a.verticies,d=a.uvs,e=c.length/2;this.count++;for(var f=1;e-2>f;f++){var g=2*f,h=c[g],i=c[g+2],j=c[g+4],k=c[g+1],l=c[g+3],m=c[g+5],n=d[g]*a.texture.width,o=d[g+2]*a.texture.width,p=d[g+4]*a.texture.width,q=d[g+1]*a.texture.height,r=d[g+3]*a.texture.height,s=d[g+5]*a.texture.height;b.save(),b.beginPath(),b.moveTo(h,k),b.lineTo(i,l),b.lineTo(j,m),b.closePath(),b.clip();var t=n*r+q*p+o*s-r*p-q*o-n*s,u=h*r+q*j+i*s-r*j-q*i-h*s,v=n*i+h*p+o*j-i*p-h*o-n*j,w=n*r*j+q*i*p+h*o*s-h*r*p-q*o*j-n*i*s,x=k*r+q*m+l*s-r*m-q*l-k*s,y=n*l+k*p+o*m-l*p-k*o-n*m,z=n*r*m+q*l*p+k*o*s-k*r*p-q*o*m-n*l*s;b.transform(u/t,x/t,v/t,y/t,w/t,z/t),b.drawImage(a.texture.baseTexture.source,0,0),b.restore()}},f.CanvasGraphics=function(){},f.CanvasGraphics.renderGraphics=function(a,b){for(var c=a.worldAlpha,d=0;d1&&(c=1,console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var d=0;1>d;d++){var e=a.graphicsData[d],g=e.points;if(e.type==f.Graphics.POLY){b.beginPath(),b.moveTo(g[0],g[1]);for(var h=1;hb?b:d,e=b+m>e?b+m:e,g=g>c?b:g,h=c+n>h?c+n:h}else if(k===f.Graphics.CIRC||k===f.Graphics.ELIP){b=a.x,c=a.y;var o=a.radius+l/2;d=d>b-o?b-o:d,e=b+o>e?b+o:e,g=g>c-o?c-o:g,h=c+o>h?c+o:h}else for(var p=0;pb-l?b-l:d,e=b+l>e?b+l:e,g=g>c-l?c-l:g,h=c+l>h?c+l:h}this.bounds=new f.Rectangle(d,g,e-d,h-g)}},f.Graphics.POLY=0,f.Graphics.RECT=1,f.Graphics.CIRC=2,f.Graphics.ELIP=3,f.Strip=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.blendMode=f.blendModes.NORMAL;try{this.uvs=new Float32Array([0,1,1,1,1,0,0,1]),this.verticies=new Float32Array([0,0,0,0,0,0,0,0,0]),this.colors=new Float32Array([1,1,1,1]),this.indices=new Uint16Array([0,1,2,3])}catch(d){this.uvs=[0,1,1,1,1,0,0,1],this.verticies=[0,0,0,0,0,0,0,0,0],this.colors=[1,1,1,1],this.indices=[0,1,2,3]}this.width=b,this.height=c,a.baseTexture.hasLoaded?(this.width=this.texture.frame.width,this.height=this.texture.frame.height,this.updateFrame=!0):(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Strip.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Strip.prototype.constructor=f.Strip,f.Strip.prototype.setTexture=function(a){this.texture=a,this.width=a.frame.width,this.height=a.frame.height,this.updateFrame=!0},f.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Rope=function(a,b){f.Strip.call(this,a),this.points=b;try{this.verticies=new Float32Array(4*b.length),this.uvs=new Float32Array(4*b.length),this.colors=new Float32Array(2*b.length),this.indices=new Uint16Array(2*b.length)}catch(c){this.verticies=verticies,this.uvs=uvs,this.colors=colors,this.indices=indices}this.refresh()},f.Rope.prototype=Object.create(f.Strip.prototype),f.Rope.prototype.constructor=f.Rope,f.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=this.indices,d=this.colors,e=a[0],f=a[0];this.count-=.2,b[0]=0,b[1]=1,b[2]=0,b[3]=1,d[0]=1,d[1]=1,c[0]=0,c[1]=1;for(var g=a.length,h=1;g>h;h++){var f=a[h],i=4*h,j=h/(g-1);h%2?(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1):(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1),i=2*h,d[i]=1,d[i+1]=1,i=2*h,c[i]=i,c[i+1]=i+1,e=f}}},f.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var b,c=this.verticies,d=a[0],e={x:0,y:0},g=a[0];this.count-=.2,c[0]=g.x+e.x,c[1]=g.y+e.y,c[2]=g.x-e.x,c[3]=g.y-e.y;for(var h=a.length,i=1;h>i;i++){var g=a[i],j=4*i;b=i1&&(k=1);var l=Math.sqrt(e.x*e.x+e.y*e.y),m=this.texture.height/2;e.x/=l,e.y/=l,e.x*=m,e.y*=m,c[j]=g.x+e.x,c[j+1]=g.y+e.y,c[j+2]=g.x-e.x,c[j+3]=g.y-e.y,d=g}f.DisplayObjectContainer.prototype.updateTransform.call(this)}},f.Rope.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.width=b,this.height=c,this.tileScale=new f.Point(1,1),this.tilePosition=new f.Point(0,0),this.renderable=!0,this.blendMode=f.blendModes.NORMAL},f.TilingSprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.TilingSprite.prototype.constructor=f.TilingSprite,f.TilingSprite.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Spine=function(a){if(f.DisplayObjectContainer.call(this),this.spineData=f.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new n.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new n.AnimationStateData(this.spineData),this.state=new n.AnimationState(this.stateData),this.slotContainers=[];for(var b=0,c=this.skeleton.drawOrder.length;c>b;b++){var d=this.skeleton.drawOrder[b],e=d.attachment,g=new f.DisplayObjectContainer;if(this.slotContainers.push(g),this.addChild(g),e instanceof n.RegionAttachment){var h=e.rendererObject.name,i=this.createSprite(d,e.rendererObject);d.currentSprite=i,d.currentSpriteName=h,g.addChild(i)}}},f.Spine.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Spine.prototype.constructor=f.Spine,f.Spine.prototype.updateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var b=this.skeleton.drawOrder,c=0,d=b.length;d>c;c++){var e=b[c],g=e.attachment,h=this.slotContainers[c];if(g instanceof n.RegionAttachment){if(g.rendererObject&&(!e.currentSpriteName||e.currentSpriteName!=g.name)){var i=g.rendererObject.name;if(void 0!==e.currentSprite&&(e.currentSprite.visible=!1),e.sprites=e.sprites||{},void 0!==e.sprites[i])e.sprites[i].visible=!0;else{var j=this.createSprite(e,g.rendererObject);h.addChild(j)}e.currentSprite=e.sprites[i],e.currentSpriteName=i}h.visible=!0;var k=e.bone;h.position.x=k.worldX+g.x*k.m00+g.y*k.m01,h.position.y=k.worldY+g.x*k.m10+g.y*k.m11,h.scale.x=k.worldScaleX,h.scale.y=k.worldScaleY,h.rotation=-(e.bone.worldRotation*Math.PI/180)}else h.visible=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.Spine.prototype.createSprite=function(a,b){var c=f.TextureCache[b.name]?b.name:b.name+".png",d=new f.Sprite(f.Texture.fromFrame(c));return d.scale=b.scale,d.rotation=b.rotation,d.anchor.x=d.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[b.name]=d,d};var n={};n.BoneData=function(a,b){this.name=a,this.parent=b},n.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1},n.SlotData=function(a,b){this.name=a,this.boneData=b},n.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null},n.Bone=function(a,b){this.data=a,this.parent=b,this.setToSetupPose()},n.Bone.yDown=!1,n.Bone.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,updateWorldTransform:function(a,b){var c=this.parent;null!=c?(this.worldX=this.x*c.m00+this.y*c.m01+c.worldX,this.worldY=this.x*c.m10+this.y*c.m11+c.worldY,this.worldScaleX=c.worldScaleX*this.scaleX,this.worldScaleY=c.worldScaleY*this.scaleY,this.worldRotation=c.worldRotation+this.rotation):(this.worldX=this.x,this.worldY=this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotation);var d=this.worldRotation*Math.PI/180,e=Math.cos(d),f=Math.sin(d);this.m00=e*this.worldScaleX,this.m10=f*this.worldScaleX,this.m01=-f*this.worldScaleY,this.m11=e*this.worldScaleY,a&&(this.m00=-this.m00,this.m01=-this.m01),b&&(this.m10=-this.m10,this.m11=-this.m11),n.Bone.yDown&&(this.m10=-this.m10,this.m11=-this.m11)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY}},n.Slot=function(a,b,c){this.data=a,this.skeleton=b,this.bone=c,this.setToSetupPose()},n.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,setAttachment:function(a){this.attachment=a,this._attachmentTime=this.skeleton.time},setAttachmentTime:function(a){this._attachmentTime=this.skeleton.time-a},getAttachmentTime:function(){return this.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},n.Skin=function(a){this.name=a,this.attachments={}},n.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},n.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},n.Animation.prototype={apply:function(a,b,c){c&&0!=this.duration&&(b%=this.duration);for(var d=this.timelines,e=0,f=d.length;f>e;e++)d[e].apply(a,b,1)},mix:function(a,b,c,d){c&&0!=this.duration&&(b%=this.duration);for(var e=this.timelines,f=0,g=e.length;g>f;f++)e[f].apply(a,b,d)}},n.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(0==e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},n.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},n.Curves=function(a){this.curves=[],this.curves.length=6*(a-1)},n.Curves.prototype={setLinear:function(a){this.curves[6*a]=0},setStepped:function(a){this.curves[6*a]=-1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=6*a,r=this.curves;r[q]=b*i+m*j+o*h,r[q+1]=c*i+n*j+p*h,r[q+2]=m*k+o*l,r[q+3]=n*k+p*l,r[q+4]=o*l,r[q+5]=p*l},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=6*a,d=this.curves,e=d[c];if(!e)return b;if(-1==e)return 0;for(var f=d[c+1],g=d[c+2],h=d[c+3],i=d[c+4],j=d[c+5],k=e,l=f,m=8;;){if(k>=b){var n=k-e,o=l-f;return o+(l-o)*(b-n)/(k-n)}if(0==m)break;m--,e+=g,f+=h,g+=i,h+=j,k+=e,l+=f}return l+(1-l)*(b-k)/(1-k)}},n.RotateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=2*a},n.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-2]){for(var f=e.data.rotation+d[d.length-1]-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;return e.rotation+=f*c,void 0}var g=n.binarySearch(d,b,2),h=d[g-1],i=d[g],j=1-(b-i)/(d[g-2]-i);j=this.curves.getCurvePercent(g/2-1,j);for(var f=d[g+1]-h;f>180;)f-=360;for(;-180>f;)f+=360;for(f=e.data.rotation+(h+f*j)-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;e.rotation+=f*c}}},n.TranslateTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.x+=(e.data.x+d[d.length-2]-e.x)*c,e.y+=(e.data.y+d[d.length-1]-e.y)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.x+=(e.data.x+g+(d[f+1]-g)*j-e.x)*c,e.y+=(e.data.y+h+(d[f+2]-h)*j-e.y)*c}}},n.ScaleTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=3*a},n.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.scaleX+=(e.data.scaleX-1+d[d.length-2]-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+d[d.length-1]-e.scaleY)*c,void 0;var f=n.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.scaleX+=(e.data.scaleX-1+g+(d[f+1]-g)*j-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+h+(d[f+2]-h)*j-e.scaleY)*c}}},n.ColorTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=5*a},n.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(c,d){c*=5,this.frames[c]=d,this.frames[c+1]=r,this.frames[c+2]=g,this.frames[c+3]=b,this.frames[c+4]=a},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-5]){var f=d.length-1;return e.r=d[f-3],e.g=d[f-2],e.b=d[f-1],e.a=d[f],void 0}var g=n.binarySearch(d,b,5),h=d[g-4],i=d[g-3],j=d[g-2],k=d[g-1],l=d[g],m=1-(b-l)/(d[g-5]-l);m=this.curves.getCurvePercent(g/5-1,m);var o=h+(d[g+1]-h)*m,p=i+(d[g+2]-i)*m,q=j+(d[g+3]-j)*m,r=k+(d[g+4]-k)*m;1>c?(e.r+=(o-e.r)*c,e.g+=(p-e.g)*c,e.b+=(q-e.b)*c,e.a+=(r-e.a)*c):(e.r=o,e.g=p,e.b=q,e.a=r)}}},n.AttachmentTimeline=function(a){this.curves=new n.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},n.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b){var c=this.frames;if(!(b=c[c.length-1]?c.length-1:n.binarySearch(c,b,1)-1;var e=this.attachmentNames[d];a.slots[this.slotIndex].setAttachment(e?a.getAttachmentBySlotIndex(this.slotIndex,e):null)}}},n.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.animations=[]},n.SkeletonData.prototype={defaultSkin:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},n.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,c=a.bones.length;c>b;b++){var d=a.bones[b],e=d.parent?this.bones[a.bones.indexOf(d.parent)]:null;this.bones.push(new n.Bone(d,e))}this.slots=[],this.drawOrder=[];for(var b=0,c=a.slots.length;c>b;b++){var f=a.slots[b],g=this.bones[a.bones.indexOf(f.boneData)],h=new n.Slot(f,this,g);this.slots.push(h),this.drawOrder.push(h)}},n.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateWorldTransform:function(){for(var a=this.flipX,b=this.flipY,c=this.bones,d=0,e=c.length;e>d;d++)c[d].updateWorldTransform(a,b)},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose()},setSlotsToSetupPose:function(){for(var a=this.slots,b=0,c=a.length;c>b;b++)a[b].setToSetupPose(b)},getRootBone:function(){return 0==this.bones.length?null:this.bones[0]},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a); +if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){this.skin&&a&&a._attachAll(this,this.skin),this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.size;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachment(d,b),null==g))throw"Attachment not found: "+b+", for slot: "+a;return f.setAttachment(g),void 0}}throw"Slot not found: "+a},update:function(a){time+=a}},n.AttachmentType={region:0},n.RegionAttachment=function(){this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},n.RegionAttachment.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,c=-this.width/2*this.scaleX+this.regionOffsetX*a,d=-this.height/2*this.scaleY+this.regionOffsetY*b,e=c+this.regionWidth*a,f=d+this.regionHeight*b,g=this.rotation*Math.PI/180,h=Math.cos(g),i=Math.sin(g),j=c*h+this.x,k=c*i,l=d*h+this.y,m=d*i,n=e*h+this.x,o=e*i,p=f*h+this.y,q=f*i,r=this.offset;r[0]=j-m,r[1]=l+k,r[2]=j-q,r[3]=p+k,r[4]=n-q,r[5]=p+o,r[6]=n-m,r[7]=l+o},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},n.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},n.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=this.animationToMixTime[a.name+":"+b.name];return c?c:this.defaultMix}},n.AnimationState=function(a){this.data=a,this.queue=[]},n.AnimationState.prototype={current:null,previous:null,currentTime:0,previousTime:0,currentLoop:!1,previousLoop:!1,mixTime:0,mixDuration:0,update:function(a){if(this.currentTime+=a,this.previousTime+=a,this.mixTime+=a,this.queue.length>0){var b=this.queue[0];this.currentTime>=b.delay&&(this._setAnimation(b.animation,b.loop),this.queue.shift())}},apply:function(a){if(this.current)if(this.previous){this.previous.apply(a,this.previousTime,this.previousLoop);var b=this.mixTime/this.mixDuration;b>=1&&(b=1,this.previous=null),this.current.mix(a,this.currentTime,this.currentLoop,b)}else this.current.apply(a,this.currentTime,this.currentLoop)},clearAnimation:function(){this.previous=null,this.current=null,this.queue.length=0},_setAnimation:function(a,b){this.previous=null,a&&this.current&&(this.mixDuration=this.data.getMix(this.current,a),this.mixDuration>0&&(this.mixTime=0,this.previous=this.current,this.previousTime=this.currentTime,this.previousLoop=this.currentLoop)),this.current=a,this.currentLoop=b,this.currentTime=0},setAnimationByName:function(a,b){var c=this.data.skeletonData.findAnimation(a);if(!c)throw"Animation not found: "+a;this.setAnimation(c,b)},setAnimation:function(a,b){this.queue.length=0,this._setAnimation(a,b)},addAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;this.addAnimation(d,b,c)},addAnimation:function(a,b,c){var d={};if(d.animation=a,d.loop=b,!c||0>=c){var e=0==this.queue.length?this.current:this.queue[this.queue.length-1].animation;c=null!=e?e.duration-this.data.getMix(e,a)+(c||0):0}d.delay=c,this.queue.push(d)},isComplete:function(){return!this.current||this.currentTime>=this.current.duration}},n.SkeletonJson=function(a){this.attachmentLoader=a},n.SkeletonJson.prototype={scale:1,readSkeletonData:function(a){for(var b=new n.SkeletonData,c=a.bones,d=0,e=c.length;e>d;d++){var f=c[d],g=null;if(f.parent&&(g=b.findBone(f.parent),!g))throw"Parent bone not found: "+f.parent;var h=new n.BoneData(f.name,g);h.length=(f.length||0)*this.scale,h.x=(f.x||0)*this.scale,h.y=(f.y||0)*this.scale,h.rotation=f.rotation||0,h.scaleX=f.scaleX||1,h.scaleY=f.scaleY||1,b.bones.push(h)}for(var i=a.slots,d=0,e=i.length;e>d;d++){var j=i[d],h=b.findBone(j.bone);if(!h)throw"Slot bone not found: "+j.bone;var k=new n.SlotData(j.name,h),l=j.color;l&&(k.r=n.SkeletonJson.toColor(l,0),k.g=n.SkeletonJson.toColor(l,1),k.b=n.SkeletonJson.toColor(l,2),k.a=n.SkeletonJson.toColor(l,3)),k.attachmentName=j.attachment,b.slots.push(k)}var m=a.skins;for(var o in m)if(m.hasOwnProperty(o)){var p=m[o],q=new n.Skin(o);for(var r in p)if(p.hasOwnProperty(r)){var s=b.findSlotIndex(r),t=p[r];for(var u in t)if(t.hasOwnProperty(u)){var v=this.readAttachment(q,u,t[u]);null!=v&&q.addAttachment(s,u,v)}}b.skins.push(q),"default"==q.name&&(b.defaultSkin=q)}var w=a.animations;for(var x in w)w.hasOwnProperty(x)&&this.readAnimation(x,w[x],b);return b},readAttachment:function(a,b,c){b=c.name||b;var d=n.AttachmentType[c.type||"region"];if(d==n.AttachmentType.region){var e=new n.RegionAttachment;return e.x=(c.x||0)*this.scale,e.y=(c.y||0)*this.scale,e.scaleX=c.scaleX||1,e.scaleY=c.scaleY||1,e.rotation=c.rotation||0,e.width=(c.width||32)*this.scale,e.height=(c.height||32)*this.scale,e.updateOffset(),e.rendererObject={},e.rendererObject.name=b,e.rendererObject.scale={},e.rendererObject.scale.x=e.scaleX,e.rendererObject.scale.y=e.scaleY,e.rendererObject.rotation=-e.rotation*Math.PI/180,e}throw"Unknown attachment type: "+d},readAnimation:function(a,b,c){var d=[],e=0,f=b.bones;for(var g in f)if(f.hasOwnProperty(g)){var h=c.findBoneIndex(g);if(-1==h)throw"Bone not found: "+g;var i=f[g];for(var j in i)if(i.hasOwnProperty(j)){var k=i[j];if("rotate"==j){var l=new n.RotateTimeline(k.length);l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m,q.time,q.angle),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[2*l.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var l,r=1;"scale"==j?l=new n.ScaleTimeline(k.length):(l=new n.TranslateTimeline(k.length),r=this.scale),l.boneIndex=h;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;l.setFrame(m,q.time,s,t),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[3*l.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var l=new n.ColorTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=n.SkeletonJson.toColor(y,0),A=n.SkeletonJson.toColor(y,1),B=n.SkeletonJson.toColor(y,2),C=n.SkeletonJson.toColor(y,3);l.setFrame(m,q.time,z,A,B,C),n.SkeletonJson.readCurve(l,m,q),m++}d.push(l),e=Math.max(e,l.frames[5*l.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var l=new n.AttachmentTimeline(k.length);l.slotIndex=x;for(var m=0,o=0,p=k.length;p>o;o++){var q=k[o];l.setFrame(m++,q.time,q.name)}d.push(l),e=Math.max(e,l.frames[l.getFrameCount()-1])}}}c.animations.push(new n.Animation(a,d,e))}},n.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},n.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},n.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new n.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new n.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new n.AtlasPage,e.name=f,e.format=n.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=n.Atlas.TextureFilter[d[0]],e.magFilter=n.Atlas.TextureFilter[d[1]];var l=c.readValue();e.uWrap=n.Atlas.TextureWrap.clampToEdge,e.vWrap=n.Atlas.TextureWrap.clampToEdge,"x"==l?e.uWrap=n.Atlas.TextureWrap.repeat:"y"==l?e.vWrap=n.Atlas.TextureWrap.repeat:"xy"==l&&(e.uWrap=e.vWrap=n.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},n.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},n.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},n.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},n.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},n.AtlasPage=function(){},n.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},n.AtlasRegion=function(){},n.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},n.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},n.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},n.AtlasAttachmentLoader=function(a){this.atlas=a},n.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case n.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new n.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},n.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;h - + + + + + + + + From 6a405543098e7dbc6f8fa265a191ecd876e9464f Mon Sep 17 00:00:00 2001 From: Louis Acresti Date: Thu, 5 Dec 2013 21:05:57 -0500 Subject: [PATCH 89/96] removed example from main swap branch --- examples/swapChildren/bunny.png | Bin 449 -> 0 bytes examples/swapChildren/index.html | 71 ------------------------------- 2 files changed, 71 deletions(-) delete mode 100644 examples/swapChildren/bunny.png delete mode 100644 examples/swapChildren/index.html diff --git a/examples/swapChildren/bunny.png b/examples/swapChildren/bunny.png deleted file mode 100644 index 79c31675083b7ffc272a6370bc189360bde484d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 449 zcmV;y0Y3hTP)SOJFMz`0@qn1GK$9W|wOohG3Lai}FkWLtiT<2<{JbM8>W7|R$! zUuNqg#gmKmsTnILy&K;zJjd^_40xy)%EA1>FWWk~LFpr>Et|!Hv(V>Hs9!2xEQJ>~!qz76HLsxFXdG zs5~GjUDeD6dXvG$_#HtoUok|M-X@BSTy{VK4P?TJZcz}O&FVzD0fZu8Yajr@?2aYL r_Q@_>J=ju&>AqoA-=wzwF98MsNX4 - - - pixi.js example 1 - - - - - - - - - From 99bf7d62f16eea1c5dc9cba928aa59a6b72aa223 Mon Sep 17 00:00:00 2001 From: Louis Acresti Date: Fri, 6 Dec 2013 00:45:37 -0500 Subject: [PATCH 90/96] early-out for self-swap --- src/pixi/display/DisplayObjectContainer.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index 1d54df9..fc8841a 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -214,6 +214,10 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) */ PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2) { + if (child === child2) { + return; + } + var index1 = this.children.indexOf(child); var index2 = this.children.indexOf(child2); From 2c97041de87a65e61ddb8581479050e0d7cce936 Mon Sep 17 00:00:00 2001 From: Louis Acresti Date: Fri, 6 Dec 2013 00:49:06 -0500 Subject: [PATCH 91/96] check for invalid children --- src/pixi/display/DisplayObjectContainer.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index fc8841a..9824471 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -217,9 +217,13 @@ PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2) if (child === child2) { return; } - + var index1 = this.children.indexOf(child); var index2 = this.children.indexOf(child2); + + if (index1 < 0 || index2 < 0) { + throw new Error("swapChildren: Both the supplied DisplayObjects must be a child of the caller."); + } this.removeChild(child); this.removeChild(child2); From 6a7a33c898347e57110017427e94054c5af88f5d Mon Sep 17 00:00:00 2001 From: Louis Acresti Date: Fri, 6 Dec 2013 00:55:01 -0500 Subject: [PATCH 92/96] style consistency --- src/pixi/display/DisplayObjectContainer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index 9824471..eb95624 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -214,14 +214,14 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) */ PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2) { - if (child === child2) { + if(child === child2) { return; } var index1 = this.children.indexOf(child); var index2 = this.children.indexOf(child2); - if (index1 < 0 || index2 < 0) { + if(index1 < 0 || index2 < 0) { throw new Error("swapChildren: Both the supplied DisplayObjects must be a child of the caller."); } From b6f51b34b09ac8612b27b69cb8f43d41d86f30fd Mon Sep 17 00:00:00 2001 From: alexpusch Date: Sat, 7 Dec 2013 14:55:08 +0200 Subject: [PATCH 93/96] Fix setText documentation attribute --- src/pixi/text/Text.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pixi/text/Text.js b/src/pixi/text/Text.js index df1d12d..a2acdd6 100644 --- a/src/pixi/text/Text.js +++ b/src/pixi/text/Text.js @@ -65,7 +65,7 @@ PIXI.Text.prototype.setStyle = function(style) /** * Set the copy for the text object. To split a line you can use "\n" * - * @methos setText + * @method setText * @param {String} text The copy that you would like the text to display */ PIXI.Text.prototype.setText = function(text) From 5d45bbfc4b566da30aa55236eb66ee5cf84b6138 Mon Sep 17 00:00:00 2001 From: josh shepard Date: Sun, 1 Dec 2013 19:41:49 -0800 Subject: [PATCH 94/96] fix incorrect width property for multi-line BitmapText BitmapText.updateText() was setting this.width to the width of the last line of multi-line text, rather than that of the longest line. this made it impossible to center multi-line strings. (found working in Phaser) --- src/pixi/text/BitmapText.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pixi/text/BitmapText.js b/src/pixi/text/BitmapText.js index db4ec3b..7dd15ee 100644 --- a/src/pixi/text/BitmapText.js +++ b/src/pixi/text/BitmapText.js @@ -135,7 +135,7 @@ PIXI.BitmapText.prototype.updateText = function() this.addChild(c); } - this.width = pos.x * scale; + this.width = maxLineWidth * scale; this.height = (pos.y + data.lineHeight) * scale; }; From 9a0560608be55530bae4e862a5d4704fc7b27baa Mon Sep 17 00:00:00 2001 From: Chad Engler Date: Sun, 8 Dec 2013 08:11:06 -0800 Subject: [PATCH 95/96] Merge and close #347, use inherit for cursor style instead of default --- src/pixi/InteractionManager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index bc655d2..fc0dbb7 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -223,7 +223,7 @@ PIXI.InteractionManager.prototype.update = function() // loop through interactive objects! var length = this.interactiveItems.length; - this.interactionDOMElement.style.cursor = "default"; + this.interactionDOMElement.style.cursor = "inherit"; for (var i = 0; i < length; i++) { @@ -352,7 +352,7 @@ PIXI.InteractionManager.prototype.onMouseOut = function(event) { var length = this.interactiveItems.length; - this.interactionDOMElement.style.cursor = "default"; + this.interactionDOMElement.style.cursor = "inherit"; for (var i = 0; i < length; i++) { From da868e7f41ea7a55840f6040c5607e876215d49a Mon Sep 17 00:00:00 2001 From: photonstorm Date: Fri, 13 Dec 2013 13:51:55 +0000 Subject: [PATCH 96/96] Fixed IE11 check. IE11 no longer has MSIE in the userAgent, you need to check for Trident/7.0 instead. --- src/pixi/utils/Detector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pixi/utils/Detector.js b/src/pixi/utils/Detector.js index e955e49..250f609 100644 --- a/src/pixi/utils/Detector.js +++ b/src/pixi/utils/Detector.js @@ -27,7 +27,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) if(webgl) { - var ie = (navigator.userAgent.toLowerCase().indexOf('msie') != -1); + var ie = (navigator.userAgent.toLowerCase().indexOf('trident') != -1); webgl = !ie; }
IVoQLb$(XwH@NKb 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 IM6N<$f>L~g`~Uy| literal 0 HcmV?d00001 diff --git a/examples/example 16 - Displacement/LightRotate2.png b/examples/example 16 - Displacement/LightRotate2.png new file mode 100644 index 0000000000000000000000000000000000000000..a6e63c01b721611585c5c0337fb06b0714d04d92 GIT binary patch literal 173189 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%0D(tFu%iSmUvCHaDcCRA! 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

F_Ld-6A#TJ9MBb=+JbjW65q{B>VenMagW~ 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 z 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 + + + pixi.js example 15 - Filters + + + + + + + + + + + diff --git a/examples/example 16 - Displacement/map.png b/examples/example 16 - Displacement/map.png new file mode 100644 index 0000000000000000000000000000000000000000..b734788fbbf3746500c62e8a6798d2479a35deb8 GIT binary patch literal 96515 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 z zHh_DM=j#97iLw)myoXwS2E8NyyP`}LU{ zNk49jGk&U*M=@^Mc(R$n2eVgyrF|-Q`CQjmBLw&-i_Dd_Y6jCw zh@lT+R`BnnwoExjCZ*JgqqbsRJEQ_m{z}bg&sez+(iws;szN z7Q~T2+D*(fW&za@x`-J;u6Z4wKi9?QF|Z)ru5|7gEJI?!p;HH~l(yEaD!?sDhlMvSi%6k(!HRzdbcv=}XlI?($pAALa4+kH)WJuS45 zWfG(Kk9=JbEZTxYb8eYxubN|?W6#Q?JF=U$fmbn0m^zLhK+~6Yq}?Y#<-=#6oeH`t zRhn3Z#WIhCL|lFZ$A|P4`1zfz@+3 z)p#6&0^)x(j|jFS0nTHCoT84DLMln-ER9GRZBO1ncHOTD4 z>h(x5AOAIZ`yp4alLc9D`l-0xogY+N?qSt#kiu-)^Y1bYOx9;w6QUfqND#WK%sH&& z3Rv+)ldit%jV^;(DZmkWGe;uXcOvci9A=tIn(KaNLj#U)fvw&$2h{Yr5R%{?C8pOWYZoJW z)bAl6BBRjn=Fcr|NW;e{8+{^*W!XVDMMpHo9@=Zkg85)s5T=jBHPEp&*-te#YviPF z< zo+93De;FcX9LDYm>)`u3ht$7Pb4k)$cxfvZFG*~K=Om&!db$v33EQ7(f}@zwb(x=^ z?sau5F2_7X68N#yWtg82E_(=rwsc!H^I73px?g(jD=nZPB}g5sl?~0~i}o|>cUa+T z@rxNmzwu7qpVZ8f@IOfJ3X-63*OwGN%|gn^{rtQ-0#Wbx$nAiRb>w<#@2qVe$Rx4z zp$ec@5+MYoY2REt_)QQB+Hp@m?$`xTqd1`Y8dlylaX5sA=Wmv8Mx2Z<*3ePwGf`_h zCgXnQm7!FS9z)LAUth>}C-m_~G#xQj)PB9*hA~_Y}S-9o=9IKgJg#fhkam1(YQ@)6&ge|M}T`P8uXf*8^~r(%|9_<&s_ z+o|=}&T$oMDfFdyIkNvaoDi&R8pxavM)f#urcf?e$^I3zw^`kMYJ6{8|32I=h=M#M zjpaLp@vtTNvNy!VEGplrEhiiFdpai`eLlYK03uV7_SH}|XpVTQKygLW?JI}wsGf4P zDgF>Ddi0(%db8Rx-){;w-e`S!SmaSu^SBe1rjL=SA(&8zwZ_NRJ+*wdluR1UpGw;#aeD6zjjFRpLC9PM)xWFqeA@pUBHG3F-Q~glAd{G_E6^V% zo2V2qoZ&kr-FELQB1MPYpzp`8B=PMf*r0}qeBDv2JmxX1b9&$ehlI!6TV8#XCMiSY zzdA#pc=0*JUSu6etx0`H#`r`Xk&)$G&Zyh#l88hf9!a#SPbO)-61fP2h7P3eoQ-|! zr>gw2uv17F`zgBFPFWU4v_(LDONqVflLer|m_AEWn*D5oORGF9Xl#1}XgJJ;AZHZz zMXia0-eB~unvbyMG?g?xT$-r$o^SAdJ4GsK5!npi-dU1nOg_QuuQNBrqu}Wu;b&JP zLHt+a=ScDRv5}%qAqU5N!Yt=k);r&MN4gbX`aSC57*%ndxLVv&pO07sZ3* z+P*mw*&wkg%t4IF9?t^$16u*_qD&XHVCU;#OHO~{QkdNG1OgkV2lws-mERaPOv{;H zy)E)SNs&aiFlJ2N%Q6mD9{e+$)D%80cLeKPG1N8&R9T1QqSogi+S#7LH)rKm^dInN zGM09RGj*2xER9c8UANSFvqT5*cB`}uRHVsn>7^Dprk@XP-u})<;n9)u?hHL5ltnpL z#3=80Y2-R_r!;QM8M*5eD9!yPUWHCiCI`HNiV4qzt@mQ0)UZqX$gnE;bp6go?Io0s za##@GlOiWwHCf#?!4`(?Fw;OI=1BX|OEwD@iKOI5P6R$TbT(OroL% zd9PLIFpeBAmNj}%UU_9ry?>?XivSAZ02`B7H;&dkXQY5aOL9m6-WRd02xWOXRq>Xd zo9MTW#!kHrF}7juRF|K;()P;}Vt`I}&of)UHB2>?xUpBl%R76D1nCHkg}`x zW84w49S5i~OlPxbeuq1tOS<>tj5`V~rl7C!DV4jkysDgI^Mw)lS*GYO`ceiAc zJr65{$%+*U6?WAIJZO&>6H`?lkSK-7S|Nz~Ww@aoxLe5Yg?rF^QKX zkp;+y7l&#Oudj@Kw77BbE(V1Bl*XXs(O@YnEZt=XoH9no%2RBfXK87;0U@gS(v!W0 zy8BkipV;J8LI}g|k}=JOlNdJT^kkXcpt9k(tc8!-c;|ZNRGddT#5DV7UkC9av+U5T zB4rG@<~>OID~eOBW9Wr4>3StgVRh@HpFnPsCj`~W<|*hpPpSmW^z#<&btoS2+I_0k13Bnk>T}(6!KdiAclN z-|mimE%zgQu?3ltSr3!qa)uDbWO&J zgjz!$F(W4mMU$3I2f&TzW0JoR|LYYUW6B`C>4$Q>@GLa2zTq29j|+NRN@yLjcL|mJ$NciD>uY0; zabi5C7Y))ID{8B{p!^xLGuB(m7}d%6fN8Y7?DRshVKJ$uSu7it1YT+&f0KF*1;4Zoj?T_+fuD@B!)CSSop!)oLMMU09nRAJTkJ>l;Fo<)PAC8 zX;m|Vh*T^|ewtyg?H1AIg32$&so@nDo|_D)EpQQu!ql=rjuowd6@dvXtP?L{XmHmF zawx$o<#{1c3FozM&rGllax3cLeK22_q5s6Zl_~kSpe9Rm;1H4@dZGG@kxnmjZB$1} z|JtYCx0ik(K)nC*Xm#{(Rmp8#vO(|O8)5p0Sn&Y5F|iY%J(KGAxqf7xplvc{}_Dc<8svnlsv*% zefK#L%Bjj)Cud?4DDmois3O-9Mz?y^`9&zCQWyuLg(7EQ+TvH;;y%&-We?BnIi^|s z?`f(6#Fw~a>8U7OlrY#*`v8W1WY!h;NsuF~%&r`RheRT($tC3?t1VnLBsS-GtAf3Q zE9hN1=>P9|*Owf^)eH0jvz znQo#TW%8I#CB^i$tWGQaEA?+CszWn}>C_L#{3OYEv|wy{`R<<5k3P1W!}koLw9~9q z^{Nn3&94JEGWz@vU(yR=>hGhIQTBETtRH#a+dY(te`m8K*kl&p-Eax7d33QGlOF)KmHaW+ zeZ$+o_2^T>N@2g>LbgiWbKuxbW~6tZKc84&vKsO$feEm+J;n%YlSQbPG;CQfEjyp* zVpHcs_O{`nSkoQHJj#isSvXI+o8X*?*LIB!Udemj$iV3vC{ZE+j&M{TeYZfw z=(sf}OxHRY*k3z4=H8ODruGe%I>;dfVpWnPRUIG`wlJH{+j-Jy>~mv=2B;>*~%iF1UO? zlW#1L3a3>BvzE%a8Ycv|6)r)V@F%sP(4n(ZIr%|>PmR5s1+>s50ea}I^(p(jeaYz} zCR+3amVrVZhnTQnxL)#67jY{JG_>wZEw#IUG+LrH!4x?J&KJI(!q#3F`%8tG=6VZEUn3GvsNHnQKJAY&51uPg0R z<5H5pY*Hc$lR^r#QH!SKE*vyigR+&0(MNgIBmuqaFu)KHuh#ldo~?y*DW(k}jrqOl zgGW~HcUU~RCkYyr&||l^s{?4*MWq^Ur({p0vCCMFqER_N1JbvC(?`h3gx#8{f>eu7 zzeL;~Vi#_d)ap~BUn(}slR7}@ZTQu=wo-R!D3E`j{Cj~LR|6{9S^m$H1YiBR$9v2! z6g``+$e#wr5rUa3iGSZ(yhdbG%YU@R=%n3%bJdLA{ZgvX22#D0u4jA|+%+?;CYL@> z)l-+HrBp3n3C~vVbrl%;OK;}KRwRqh4|L|x)kLbp>-7)C`i@ER0T_S6^U&SUaIrME zuAJfb@$2>vV7Z$|)*zbRY013GnaQLUuSg8IQz-NbN%ge2W$A{^LDEj@P>AP2mRN+?DHHVIunt;*O+GhoXno@JPVK{dn5r*MV}mHn{1- ztHV*3Q2&*f>1)e_2o<=;5Js9<-p1JZ7qMNwNI3vf7B0we`ZQPLa?O`?lUCPayYJU% zctdt7jwI0){u|PsKZ4ZjYxx^XQy>|!%EQZS*0J$2mhVUOB0bCgy5QND*(Wblu22k3 zQ@)ND|B3>U5|RM0Dpty&QvAzP^~-OIeAL&IX2BP}mIW!wv?%#1o11KJ^@fTPSw6WK zLi8ktAA<`e#33q}*8kSgz92X_mqMbwtR{7On$FKV@wd`tnQDj+qHin+#7;;0M{uYI zmlZUDbI0TNK=H-UiPF>2sj&1o41@w-^^m)u%H1?P&YcY$%NF0~-7xfl`M!iA7qU$P z^$+=FYdfTo$4rm1Oi-dt6#LfU@F^*_Im5QknH#En#fzuV=(TW8$J!l)gQV<51JW9C zkod*Y$se?MWh4OrEJv2%6viDg*C^udNP{1)HUQ1&P!_ub(DOA_6tw2Pyu= zTvO$=^@F8mOVWPsdYDZ}Xyk&{Guh_a2PMs={FCQ(XJ;{6UGOpdH-zSnsTgP1U2#rZ z#z~oXSNX1VqZX1U=0XK7CS!;v^V{l(zBwgDx?iSQQvFiJl1Wb8ftiqxD~4^G!BFi( z!)p2|Ftm0POxOUGUOrl%vurUK>1=b8m%y1&GNT~HQk-@YZDZCsAQv6 z5!m{-fu#?OahSarA?(|G+XZ2=vR6kDEsMI1;KSxqZDu9uueg~=ZpmM~D|2k{B#go@ zebvvx9Fw^1m*!{NB%dwit}>%{LwriJ)*0BW=|Y?Lg>fAhW^VFuvkH_eDSzW9(e#nA zNfv$Hc+HA*7?ODg_*rc)#eA}G_VzyUK~4KkG>eU)D9J#EusRNNIh!qBd8K1OZA$x! zzdw!A5s+TKg<2imET=fHFc0TEriA5tl8P5SVPT*^+I9wMOw5+MAy3J|xFkUu&_`nr z(7A_%ku&qv39O0|w;Xg<-;b9ck1nM{)+f2(xoei8%d30$6eRg*U_U=4>%N^#caF5> z)^|`E2=t9jILxR|ID~`#UQ{_>h7P^Vaj{nT@5RxTX5!6p%8sbi2ue|;%XNQ>tU@@Y zJO;;gV@^X$LZr{Zn!sfB4hFo~tlmCN-sPN#?hZxDFAyacSJt@ydnmQGNFyKd``v*8h7zzSc%&w#C{gUg&Y3 zz5N<$6~PwBT=H-Rp9T>iA}^AI3udkWlk+{4jjOfhM!Z`5d%tJ;$Qh89BQCR$D#^!v z@cD;)j;=LMLY2vo=Y;ZC+`OVxDe6h7MfK_0#RX#2I=l_f`QZ-Lr+U2!)`CmO_5Pn4 zJEP%gm^D&A5tsK39|6NTE3oJ|-)5%8-=S2Kas4~422iJ$6ko2z^O&$G%f-gi3a&){ zP?urf^ig)P$mbZrwHyII<=}2ZLK-^73M-@|lne@#OLlnV#DK8lEaA0SGSyFV{QgJX z6qx)x2{{zY{5Qgq*unLl%U%fAk{E4~p4;DJfzkN9?U$fKfyU`eF-DsDb15Q@yN`2l zpr4CVy6)D=ESJA~69G1IKf#PKf)}m)yL)%5D~JbjyL<79ft{5eIPbjo&7 z%TK&>+Shr9Rnz2O@fv6(v+e4*I={{uNd#=k=IV=U)>|I`41U>J~KA8_l@ z`n}0TL}&8foLLV!bPsrF?hjn{E+$I9|0pGC4|_N+$;Sl*>SXZMZJf*6H6W%wk-KQ( z(5$`-gq|5q;%1>n(Zn2w{;h^S0yVW%aAs<#-kRWvAV zw;kcMY^-`;Z7(>Tu>@>uhf3fwGh*C>-meyNZ|1bW0nhg}&~8M6RdrDSQ zaM%ln7SKtpU1_-I#B${XHr31orf3U@4k}~_wgt2xrXYUCoMS3IPD}SyQXKn zI?D$5{s+eW52!K1(K5BGT6Ktggl!6W4kRk=X)vldIMtnIpwD{}n$T2}T z;W!|6J8NM1?8_K!}DHg+v!*!v{hX%ZBUPN|Xvp%D1=ZlW|BvbwL!?&`^;K3E77+_;K|{ zwId0$1kmhVa052K2>th|b;4ChlH2+F#r1qJZ3{DZS^05JFWK$>RpNZiLV=$l%%{Z| zftVljmcIW-TK`XlKA0q63xvZqE+VbFd4hd4kI%=v*L1A%1@9n*ao~dtJ3T zxT3{;V}?YinqgE_#h66pe;OAzxPK>TsG-hbs-TUq_2tUu76jR8RLPj{N4mlg!Sly? zMUD}MkKms=>OeYR>%r6(r!~Un$}C2sbhT9R%<pyX`8i%mdp>Q*`5hFH2J#S|I zPI?gwP>%osagZ0}OX@*OtqY3$3*nZ8gC6s7NcQsxRma%$pxn)kt}ET!~h6MZppA0T5Rh?iVORkF|KT8Y}eg1>5I)GV<>>QHG4EuqTrgFNzPw|wDM0zVTQLlI3h$MH-)Wx-nmb{WwJ2%gsi8~f)a2y)TMLtyXZ zDs#qSlW-HbpvdSGXK8r}@0-H`l%xPOIrmRJscyz z`K=N4kX}i;0bKw4Z;QsV*zaD7N}8vWmwFiPKe(NLb1g*&TDbRreso2xduiz;GM_HL ziUS_xJ09X3{v-ukdL=kGXZ{ZP^= zMHdaKv-saE5bl=TGQJ1D{)yGb`+Kmni5~+HrcR`oZSeg}HbgNK&OvcMLZLSY`q(jD z==;$M;f`ldrOqxR{)Y(h{e?a82%-;l9R;+GIZmx42_=%Zt|Q}#Rg4zu(M<7a7|v3O z5$%%6)q8J>wH%f4RV2L&M3kEvKkNEX_T&WYdEo)BU^c=%p|Hamv`eAukd?vm8!nXK z>F}|05iBu7JVfItu;Fu%{l9xLG)YX-m>v@d&`uzf(OmM-#=lrwH6Y zs;5ce&Z5@bNI@l*DMbnPX)iIXin=BN<6zKjm*_+|E4IhV@ed_N`wa7IL?5>M zEO|!c05KpMQx%obOFr{pGo36eAK-8{XT~Gw zI^K6Ix2cM;}|+T4i^(%(nu; z4u67(L#9+dIHCn+qf#t`bvHXoGCCI-rClc$mKj*MzJ@0T9aLw*o2uO%amfOFrT<6n zyKRZPOm?}M9U~v-AO)h(E3-inL=0}0{-WX!)!noL82LoK)yqu+IoC~E4xy_kkek`R zD3aA z6o+cY9>c%@SB}Fn@PPt#_j>wHVAN4>0iHvm77C#uuQ}$d$)}lb$6jdYmFNo#<^{p& zY@z+OTSU3-h>F}>&qs`GVsW)-278|^d#s83AH`9$5(awwyq7KDLoLz4J~N=Ye4{U1 z3xUtJ?wn$yG-l_VMn?*|ZXWl6gM$6TthO>a0GoTj5;X=)mxMGSw>vS}q3L_BNo)F7K)i}^{3oxwDIqRchqN3#S&yDQ2 zqZ5UWDVkXs`nS%pcj@PKmH@c(q*&eNGC5)+fMxHC%heXMIN(^28OJY8<1_D zo}asv!~*a|wAswB#~$60LW>5HIel+ks8J8@JRuv=i%IT$@xiwog9g-1ls+lN#oU~8 z+=&~!x_02ZxVG=0oN6u0_p3>lZi!Pvgs)J={l&%mf%8En=D}qhut^X=%=({X6*mo# z{6O&Y_UqT1$2^I0M%@1)RYNp-8TWVVzrTB6(Ep9r|4OvQ_rF3|h-iy%nqJJ=-2!ro zaH}G}h)APmtpo87mz zCRuE+{8qT|1Cs|(pJfEUQYjapZ4i0S$z=vQG@%NCSC}|4tav69OFR_j$ZlMgyl8>d z3tt{`E%?LjTv}FruulyDL~Z$Oyc8fqvNO{VhG8PceFF z{>-_NaG%N5Qp!8<>oLUg_0^??zR~{C{(2S4!DaV7%F**%>MpT9}2k#{z9~Ps81+l-f zA@ACk4hjltQcg%N>s?9NTpZ2n-y&vx~n4@feLcT^7d$()}mfq)!doW5Av_ z(c0J`yG3!9+gV2QoP7MK)Mze-OHG_){wKwmt4n=$@n;GsOeacYD}>sX>rMW!VLD6G z*d_ss% zT@^-i1%%w*%vvYlZ;eDlZ>h)vyUHFmLG3xZ57I>}EtT~8tP%!A)0)b7L0GLM3+=wk zUoO%SvG`|am4iYwb?i9m;))a~P40&WZ@4}_s|fV;nCwQaH%%L7NW3%nxd>%MZJ{@! zjDE#G;QQV8e`=s508g9|qMDCSj-l^Y$Rmn<>T0Ewv~3iqBG%5=E)EcJnL{>%3 zg_5pB6kSe>tM%$?av`7|N(@Ji`uj2(GFf1Q5bikb)Hzb~(6owSU>r(!a&Mny1`Q09 zV1<*CSFh;=-}T0smQjj}I9mX-tB+CjDi~=s!uYK#Xz_s{VxMx9XN={bUCz7aEvf_@ zBQ_C4Na#L&)lfe`%A1h4TXbEe!t?AbJ3zy9u@<4BvxHEp+kfemwA?>c6GO30;=(10 zqGgyrPP=9L&s(5yKv`Z`zrg=cnsQo|qdsfr7Z07p6WzaBug_irib3s?@|2uc z2kM^E6-9@^nJupE;Cfb;f_w(fr^)xr`dRPSB70G~D|Yc;B-eizDigo}l-zN`L zD3C3s;iAcEGJQ(R`Dsg0)C&MolKX&|T!cQZoW2uHU!x;_q#D9>>-DEm^tt0ji}&cK zgG0BDETs5epy+<{q&R0_0K9{8+a`e`Cn%pzIS63l4Ias#;Z{qZ8KpLcvVwr`WDkQ3 z^wlGB`@_>Im+L6=dn5ydW7rP}1Bt6xIS2!)C?~~9=d)J_Z0A3=t`*?KPmkBp+`DcZ z{RgM8GNXuc=MoT=nclguSUuCs!lc@P+km{$#8t$@QrS?}_U z9DIV_meqG;j&LN%;1N5(^TVSzynIsc?D_(1svj{&m5D}(SpBA|5XNac#`A;Le^sr9 z>LPG%cemF6{nhF9|3`YU+&>UUI1FUoDta8zxo{m6?M1=#m(y3X`@^L~-#>;&N=r~i z7iD5qLkBW|*LrU3Jw_C|aQf|durjoTh=-t(Yn{+*ZH3b%3X7Jk+*@Y5Z*cV~_q^Is zoT&e7Yv7K&7wisI_qO;29|ot+IiYOim$9h8`P$G8tOH`Ho-Cw_YOK$&tFz80sy6`Ij6SpUbW!wiZ3(Cg z{ly~CtI9t25BI>dTty77%G$F7%E)wQeE;$0a-v;IkxGjGU`2p~@&+b1(}cm3^_p2Fc|F0JCLQ+ZoA7sI}ak&|^HI zKX@tK;(OS4GBVxpfmfR)vQt=0A45P;LalcRxNAYB~_%OnEute^qL->-WI2kIJlM7<~Wh|D-MPokJ{rik?Qs+v`#e z$l2es*H>`S%oAOtn!$@N z#!_yTt$cgOYF>t}c;qqCej)h3l-qHDYCij)PaO+A$Fvp+)2`Kys8(42Im8oMUO5?P zbBF}&ji983P>^G8>lC}dBHcHE^Gdtnl5y9oizcft4`xk+|b=S#&3rCyre9y}9)OdszwvG;U#Qd0R!F|!w9qyzK&hAd8onS5NN`ig65*;X&AeUEKN)j@$G|8neRLcXNRWpu08NgTiv+ypd$% z>Jk@kcu`}jiWAePtKUG5b6P}9rym3o=KQxT zJnde;%&!+toyoyzC=(5m|0CnqTcCt-PLnzqM0@lx#{_=HY;Ic*Iq_?d_8AHFS_UL9 zlqBp^wfubAxdP}=rmm8j+9t^Kz$v?KJ13A*(+y!A9J$Y=SM0Ob>U|I`jwCL-jZdjC8KV=uc`5l=W-vrK3~>x!N(U z!=P^;;yfk&~x?PkDmgKZ$bo;ak9ko7AK>#?*;_ zm|~&^{Sso}7VNvA;^Wi(qpRtJu9nNd`+d?@bHz+0shGz<&ptJ>PQ4|MTS(wP6S$$^ z=VpSKX8{8HYnI2O-6I;V7bw)HSRtHqT&N}b7I5n*yZ-v+#*gS{C_!0Td9P@_#YGGePQFSQCSLPV&P5_eRb8Vq38f(NGNaZFcZqumtkhFgu2Eoa-O2kO0t!y&h z-Q8)j=*^DQ1%8;E(^_cD7#h5iFXlsEAiK+9nuOhz-dUWu%U4)p*0P~ULlP8L)6YoF`hO^)+6t}99V%_$D zSbrwNfJW!;pAxp4D@&_RzMd5P+-HoH6SH4$r)Y>`2IwLuCE13q2CMARu4bQPgN)l* z#Xo(RO{5<_H}cap2D@y|q=s!*L5H9)rwvg!>eFY%~*dQMn`4ntD6fnvOu?PZ78}(Gs`(bZWj4Ez95R1NDZm)=3QQt02qC zbK*JFYoafOSz@~?7U}ZDlAabHAC*G$c28ZugA;|PHd61UC;_LwvChSQbwLrpdu$jQ zur#X7uyiy^!-%Zs^_gXfif&oSRLxk%Jrh~E0NBDyy_4_ES`Ts3BQaC{R> zKd(79p1k%a)%%4?P@uA~Y|8H7{{Ep_6aBtVGWZ#IqhC^({*>=0+AWD@+B7rHQP>Bm z^b@pGMM5|a4~N9YIJ!QHYguBpu9wuqc07)0?bhobp*OG{A$z;s=s`QchOq0%N{EQ; z69;a!I&pZD_JMH?B!i{(Do|)6)}AIzJ&9Od;7!6GEq;e?ZaQMdRJ`omg=u3GutWgY zZD%!k>SNNTK>(>}J}0tajo*Q^PtLpU$&u|exomtGoBc920kWRAZ5{-XbHv`N?nLj; zu?NcO(U(!oDIknq&=zP`iJdtDLUF(-cUHN%|8vwm8FTt%UFPh&lPs@lGI*`=U0R0B zI4R`mdVQ4BrZhj?{}X%6PqqSrV8$WBFVC-%l72p;*E>gbvURNJvYMetE>{rKA3uDU zQwY2N>T;qSHIr3N-E>keyb&vDM9Jv-Lx7|^aUAZs^WB|%6F4mq1I4jG;ZV{#_d!YF9XNsL)|I$FKyYv6+h zSqx1*u3cM54q!rsslR~E&h=p&V1|ZN#P_iY*ik^O%XUmQ6002ZEl;R8X$EZ%TQI9* zmKI?b=1?3xZq|%bC<--?>vCF(oq$DQi^h$2Vfr;EknFA!<|_bGy^f;}5@n7ong-aR z$3N@&E)>>4u5^NdliXdjanguc;l-R|0BTKC+kI-?hwuf`1mhS3EMsXkOT`L;4lmCy z#QM9C^fO0CK0bog0Hi}ry-VjOfHQRfXM|3(f*mRg{rLHl;-Z}8^xF%soE;OusQ;?4!M@>^OLny5kKj#!4vI6O3FINmTMJ7GYA5Y5qJND~3i-MhsrR3#>R zyLK>k$bFK7HmTPRxc4-O*rk=4@nX^xZSmv|JXE8mz6%H|gb;Yk6kzCXu$e>xBf|5E z4PWv6r`@HEByOlk2B9bkM@MTn}e#h2!tyC>#`vKZzqhb4}$O06XPF5KRLqeQKDLR_o#ctT%oZ3 zMH0&I#2JZQKy8&Dl2_sXe=G2}&FI3M_Xz7Jzdodm*3;enT?#6Sd+^{xlLrZ1%@@Br zhjUm|Fo~YiI0d8K#Md4p_*CG9sw&!m54otjnu7q+>V-vOxeR#KAzx=yeS}XZbK^SQ zXo+$S#6A!zlscv(0Q{q_79cDq)qK|tFGFoxZDz-rb+8T5Hm>2HBb9=` zR@7e5O9bdm>F=|obV+MRw_#b=0OfW;IP=~1UrKAm^lnOt()s_00p7pGb<^4x&vSBy zG3%J;kdMCmqM`fvz=H2XsHrO!I)P)k3XrTU(1qP-lJyuSK4w8P(7mHXbMXPe;)#P8 zwQ`CJ!_~W#JI77C+}p9A?^MCQa7pYEED&pg1%4pZAj&qCK84skcA2DmxAFq26Ra)7 z#hzeVDC9F#*h7i;hP&uQUXklOBzO5bwFxK5+eV^1hxEy@9@49{3#a8g^c6~^M~>rY z#7CTP1$I$5gV!}lcg$&@tpxoGsd0uX{a+Tw)lBD_aj7ps*4?~j;?DK zZ5~hU{O(iO?OxhKn&Jq}J1haewK38wW;uR-wX~8X{6$dF1NYWOaO0c=)=>XU)}m-Y==s_i zo;PefSiknc+|LC%Z`Ui~5=SD{M4{ZaP3Cy>V3+d5%cv4mb14>f7wkXRTKZ-JjgvVC z{R$@+U2b`z+}E;@-4l(Bqn6^5mDmJONyBIYu~pjCIbWr#eJKb;4!tH86VJ0)v~ys< zh`(0pY>TX0%!rhnzDv_Fdmu)M=^nS?7G$i4+L3e5gOobR=QU-M79kj z)ge9Y2@jE2UPX<1*?Gef*jjHZ1RJ}{ohy#mS8f8%s-gDkGKnN0gj~m+vs7~kthSqN z&wa8g(4dDh(>(%8eq;jHHHv%jYl>!S@b&II9rXD@8YPW+IF51$mXX_qP;Q{Mknd0B^@$uS-b> zs9oMdvbf6ZpF%n`v{YP3p1~JFzPr<%N(-z|cAQ*REN>JdTq-3=>NRCjawfot7S&9x zCFc{ZOF}JVyv#I&dtt)?QlBTYe(HTf@Xg+Q4NxzLO}2Ro@?kjFtn5iq&s)k)?%AUu zQ53ut|MTQ8@?RzcUU!Esiigka#ZECJ&FwpCK|ZJJ4htBbsQ1S^Mx<%JYU2)OI|h^p z(E@ASeWt46@!XSwEIDNq6!quDF+jc9jL~^cVvYLGr~D|(f3Iq;{HE?3ge{(>CCvjME_cg} z)GIPRpK+&pQuT^vFD)KU5*%bAI>I6QL78vPG1G>d6Jc#G<2GyDkfV+u46`mVu{iqD z^U5`VQg}HOnr%}(08ct%8;#Hr%VNg zg-T=w5C?}@N#B10LK(9%iknaHSdh(;7d=Ma3H9j+HC z(5h+6Ta4GV8`$SP)Vvv9HBk9VwGEPSJv{dLi5#@LaCA!VHc!oGdxgd#d(0X5e2RF+ za=|dYtH=+z`+sJSjp~L9JP>)K)QIBqbhsdUQ)gd74|Yl)lGgGGe$Z6;DJf}=P|6W9 z5hBCQ%KF*W7Tk!MaxdTXCP5)ia6;g3C#xoh~kW@t@1$$f%LeK%G}T6V$A4Lm=1Z zP>HCrxa5#Ow7OzGf+MK=rlJndNr2kZxK{%U`bZ+EE$SbJ$cyh`M2NgX%l3wuaz8`Z8 zx~xO>@z3bCW$=S39v?nJPXa4u{sMb4^A^n@C2m-5I?MVWjZ{oj=}2=%fRrfMAEaC5pa79m{-~37RV(?~O=h}q%-I?& zNhV(NX}w_vu1lct7KB4OYZXjL2F5Cw_p(Hsr5BLO+RXq~26J=uY*?btTO=s%Vt1{E zwTKCct}RYsvo9kL$r8V`OWmt#+&F!xS>nwkkT#W=6ex$Fz8JQPV{J|RjYuLGI&mcbqIkLwf=UaNtk_fh*Jje2qS?|~Nln#9sr z|J($y`TV>%+UPM!5*=5bSjAj4&&NbOpw57Y9x3VfkJEO5rtc__BlJX0aJ@g zK=EM>q%OwYc6V&@yC|nu2@Tm>r09sgK)_G16HB);e+`%$h7)Hy0+{D{N^r?3LbuHY zEHY^7)9s5lx%VTc@qhxEqRtKgR@{lSWlt-H8xmr|AvOc!8-9`Yxf)j1gIzX^5SBOVpe{C35YeO zs?hY2$0PE&Y^opyc0m_U<&mjV-lvfRJRsku-uS%%es;hcwFkWqul>YnBh=|_3VXpV!Yijqu6G>9wfH`e3`R^3-KC_Gfe@xUoWbF}NBx64^tXiO!0hcI`e+L4vgaS-5;^v& zQF0J*BoszmLyB9#MY1~EHQaw7^c=cl8_R%5P2j9ZL0WQNC_h?P#kq3u*y%K+C1imu zi6)x_RSolV?a9ala4$5DO}W`H;;0kZlh(M0K4;}9M_u2TFGaDgmioA0k=5B*8r)u7 zmTOgcp1B(Y4^zE#x$d1w$(FbYDmye5rH+6a10NnV(2~+*8EG|x;2^}P38gU$o)M&oOv*!5(ehzl zrAl%6UWMfRG!Y9I4B|eojw+{C9Z9gsw`naVKzRs50N{2yPR-jtKB`Car8EmB@@Mph z=0nnjOH6tzJqhMz-lm94GiyuozXIji#m0)Nws*=|B=_K2S8>3R|K4=jHu1nNmylMd zp;H;ycqXINxb+#PjQ_>0hyCB(C^@&@C~;1MI(gFZ#RLJF{<}+>#Mofx#VhQL`7sgv zkX(R*@SX-FH7AFIh}uu{r!ZF3t5fW)N2n>O>)XrR z<>XZ^jPaqq;)_$#h$+{6F_+a0r7fXtLQa;VVzm$Tp1aH~>r3|zt`^P$eFi9sO53NO zA)Bw7#*E^RW{UlOe|N9{{t=pr67bXoi=O>@*F%4#y;2f&aS41f-~Vif`t$cMTTCAT zRz*a7)R=U;q$alOww-h*xmhahED>u9aeoX`G?!Vcky;;)O+0%A6@=L9nQypuzzZyw z3pHv>to?-Rw4zZlNA#SB8kA}VcBgIwu^{r6T|DHOrT-n)jVLFj=~my9?-a#afO1-{ zI|W76?!}@l`@CE+YY#J5H`FzcQ=J_OxYGPF=7X=3kSEWPRO1b7rDjW5TG3Q-N^Oi% z1{pcnj^x4ZObLz)3!!#p^(GySj^y5Xgedn=x*^6X|=3^S;XxbAR3X&j@~$ z>anuTG=KIei0WUcAZ!$yzIx*8s9pPUX*UzjwYS_+@{J8<#{IPaQ@Ve_lWwG^u-2h$ zAvLFY`57_!IViFltP=|*zeNUcWifzmW@aL2~7uPH9 zh9BhOnqEz70Q*3v$u!sK+@NhG77ORLx|(gRz74EirYGp`j6Hx-Tw6H=`)j-HW}I)b zu9w|@#H><`s73RhmJuXZ9qPuAVUDSCPA`l!8lXFb{4N1dnsXn0&>p`;h4JjLZOB}D zArTPHI?XxCYNn2cbi!6wc`RN9lH`3ho~hSWL#D`wlZeX1UfaB;^%M2KI{uM|)N<^( zj|@UwzA*qoy>JgrwN1jDZAyxr&viVVe4y`rBJA&!`r?**#iDji_UJ33R^l{Evdluu z>QiM`3EFdCD!G6kq%DC7mP6H_a=MRCk7l<}=Y4zoq%6utX0UFYitU21cqfDhNgj5+ zq;BrzlAQVu(<=kv_RdCghr0po+8-7UXEKfp}slYJ6=EJ4kpa|ihIZ1 z`yl@cFT^UpCw_KAJ}+nROf4^;QCtyW5Pf1Fq=1t?o%ZvI8`1(L!%|}tV2qHxDpjQ% zW=}|k`xmT(xmu(UnBwRPr{q6YlEOV7XV{e{K^JBQF{QkUMERCLvbDzfmJ}!7yuDIg zaWw07Wf&_vxs95&92yfc>KssCAq}1d>aA^rLa^u-U9VA~DH#|Vy6*f&DwN3n zrN_O_4t;ZXB32qM+g|s?kw|T2W7CwXsJ$^NM9AXh|FgD$4lsflApTlr4K-;#&|;pW z-FC3~MQp`KZUOdDt%j>wp1jt}>_t5@U`sEagzM-0NSD)kem2X1M3*L!eO@S7;AOid z=FYQniU7(|6gz--@y#gj@+NNo`v;fcmGDBJ8<1mlYKYsHal+{AXy-LRZYPBr_IlTT zJyd1Ks#AGI9;!<(w2QiAoN|arGgN)P5DQL4wRa1OM&heoSnB;N@~-2!%tWmP>=78G zOCpHSf|-uwtaxh)G1DDtlpJTr!C|wrJp~mVhT0426YwP$()e^Hmg{DvxQX-1SjzN{ zSU}ifz8e|=7#Yl~!9=5a6voT#`?<<(osl;slctMFv-DrI0jTMo{SI~5V@-C@E19fb z{)pjm0-SC!(|4RMhEl__cn0kJ!?V3(5Hf=E#yGwjmG3@0|5-(B2=gKV7Pi6`+H zyGKyfTW@~Mu>(XNu+A58?bgf5(#^YTpF)tNdv)StGEzxxwiwDmYy;icc00!;74&CG z;}iMZQQBN8$K(nNj#;%mVX2zqo2X?i0(n66R`)H)$2GB)ha>0!rp6%aWm02!CQ%*F zJqL=hPYGd_WfiXbB-T~>i|kJ6j+7_>95IKawK1%sYt=yc<{$~b#@hdAJu7dGXV^D| z6`yEd`dD!>GfqpW-Dm;$Xte6PlDB}f%ac491pizBLSGJJ7AD;j*AR&XaMmmtPln3a zHq!cTp`%Bj-If^BU>LAqAIge~e^11=+%dh@41=5*Z?Ta5z$N?6b&l!QQX7jHYb@6Wz$U808#t$gITayrqQ-?W$H{`~MjG62&%hSV@xIEy;G0dHetWxH)}D>L!<{Du9&d z*yl+yIW1Y@0Tk+ZWa`1pbetN~>y>G<>YPJD5yJ|#l`%t*oztO%pKl+^tr{7zK@8yPT=f$`4fcU%7CVjCzolqpb`i*CM^ZaN^dal?^1F@`P?GROOB>G zcrk0x4$vUa2+v#8KTp&cP*-mO0#E&6?xcCj4$+<~vT9)ru~}dKEMCS_?=ybl18d); zW;9k|f`(96ocwK+(CHxsy7=f%W7#Y*{0OH^yM5J#na#52YqF^frz@7D{c38l`uQSr zMrs;HN1W_&Zb1iFTu}xvV@Y+ZTcun-jSQlkCh?B+@2k7wX(F+C8Jt;>W=Jf zUZ(U30Tyr7Ih-7-yG<%8rz#b55wp82)lENZOsD$qpeW8s&UR$nsFlxC{FE#couM-{ zEty6ss~1?~22hPPCE=7L{3j#tY?0YhD7LdtH?sWg>Fz4EJ&%Hspy-q)DD!;=OlrFr zy+DFUF(P*0kphkVnIshqS)$J_uK*VRj#`qdL#G{$a)5r4WMLYcXN8v;@xAWv9}EGw zVcHAS2=jTY{u7yb{onRK?5U$#53jRrL5z;;iNFK!Upct<@*4=Jl*^s1G^QpQg6+o+N$u^gF_xH7KQ?xze zgdd^<(sWm^Q3h|I?ku;$W0G0!`#w}wJ7EO*jIe2Gcr~D9Jsy1h?WJlgP*%@-wfd@l z8qpf-6V!)(KG>gz#(MZ>Pi3|OHHsR}AcvQJ!mXr0doqWnVc=0n2+Z@D<6v#gg)Emf zi~X#wJceMf1a9N)IEMA&y5CGy`s)87tr?t! z6yJT@!<%TD?f9kcBsnH@&>@-=$6<^(%&1&Zf$EQq=7VddL)2#4wVm1%JFep{a^r5J zsL3p?rVz z3C?nWZX?epiQc$uvOS6VN5H27))URv507gIL0y=0WbLucJ4&P)BCD>8ldq_ES8?)X z9jjU_L(Xr)ED3QJP~T+WV`&Pk*F&Ak#8a#!LdbO@R74G(bEk5!Jh+6<;zxuxseIlFob zELu~viQkT*kY|CS0jo7Mrd_$(@wZvN-gTyOnX4q~+acw&NRa@z_4+S4C<~5-N6=`0 zuMTFIaw`e~;k!SeKeu+Vm8cBU!HnY-hs=JLqIdMlM!x?=(u1~asX zevGjhuNVVc)}bjXLgs2W% z|ImHQT$Y?Pj-f8tC;f^Tx%KwH-=y1Jz4wSGDO$(6z$BDSJs3m2w>@u*rE`N5|F|c; zU$UEsq^YAyHPK(ld~ zGHD=JZ-sZC4289>z!WPB7d!pY2Z);ouQmaJf@61byQLIGZ*Mz@TUS`9jHldZ$eTh> z2oLUBjC3b|iHy_%+OJI;pwd(+Kjwj@Imjm$C%U@j+rw7DvL<~)dM5e75k2B(NdC_} z6RPB}>h-_@r$O$_OsCui9nTT2c9dnoBl5I*_$}S^!DR}5%Y^?BvSzDAv;j!Dx{Z4z z8FToh88bR;JIkNtZb(2~p@3X3khJ%`wIsz{KrME*m9g&<7KgC}tbMQVpI5)n%TD;G zPqfXA;hsH@eyRaIaUw&jP8z+3eWbX9jA2z%&hrle3;im%a;(qMF;~ClbWax-9bHfT zPV4J^7glbw`C`#=tC2c4<5{2Xr_)_Mv1!;>W{5;3=3^zGY3>8ZqcF@@FsUhw+h}m9 zDb))AI;-s5RO(TUItH6uPdjxK6hzLT-Y;H1x>Y9317uX9y1l^!Bx_7m!;!9xgw6*? zREP9&!)FV!7aHT6U2&BTTLhKW5de51QWhiM2`4rMk-7!$JtbA`$1!cPmKAInK_k%F z`;=`_o}|}5P1X+uRaQvLJvCyN6_3tMp`TJ|iDQ9-m=?~=EweG}209_ETKe&Smy;%K zwJFUx!~MU%3LfH$P#I<@apZuF7ptE+0$VFQ>mC1|Zz zeK0Alx0(0?n|S6}%J%!q$B5vtpY>;Zzg+My&*zVG|F?auvp{zR>D>ecH+!D_t3F%R z*T2xZfUy%HI&`)Owssg=h5m6_gS)4b+NZfG2zB-(?<2%OC{3ZR3m83!aiQnpnM5iCp;Bc+ObTAsL-HTl-t$KxJyBjvIiAd? zEDoVdexgalA6syDDCk1X`T{+<3;^oo%*Hk-hPnhPN|G z%V+nwrML_%It?m-+MCfZM};elA~vIZt^Ln9_xr4ktN%2-964!rPm5=} z4It{IcPj2T!3W}A3eu%V_w|i@ihf~yyssY?d3!66p#h(vcnn)$*h&#W?6=I*`EtEn zKh7T~^GUSV)nhFo$ufmyzXCS(Ot<@S-VM;S0-rsR(ctW5-zVt`&n!hHEUx+qOfbe_ z;RI_tS_=S=&W0ur3J5Ceg7BE(bKB_Qz&r)BSix%L{Io_{Fx)T$@tTwBF=4k2wLwU= z4ZVj_6bCMXNaQ@I?0&QC!-(+iw%~XT_-yr7ow54K+IKAvi7Sxz!aR_UknT*e@{Tw6 ztETj9e1DG^fr!n+>KDvYxrbbXUoZ*s?hEXDKDhQP2G}C_oJV3+0|MFyK z^Z9IB4PedN`bPBhX3sgZ&b4{fK71|vw^i*9cHxKUL#uMZ3UeCF6AtCM|EvCmocH~L zOTf)KA&03_G5Y9zSPEvD?i1MxPJm9;2s&tzcsjHc;siE+!!EbT&sjss4 zK2MF@4dek+qg_4lD~#pCu>&a3vc-s*{dHL9c+Nt0&YqOZvxHppPYpsv7%%Q~W<@uN zrl8yP?-nRtNmfPfZ+!wbGedehf_ z4VVY=-J&UP?!^mnj6%>B*F#ZRS=IqHt|2;I=xI{mB?DV4xaQyPE60DQ<4jEEj4*?f z^XJ%g-}elZrp<0>ci95=PQY}$Axzoja0$H^%jwCZcCs`Crt9(qbv0Cil$c~sg}`9k z_~KH7mxn8C8U6y!Kq!YFNdGOYYc=qn9aIwpf&#^>O| zj9k~(I|FOh8#80xNupxA7Or|)Ns^2p)Ye+ zIq11%6#4Y@1*_izD@UWsR%nbNY(mC7?Sa@yJJC9ho^PlkYOZAMuYPmf;bCf5^kN(`kW%;6yid%v zpbZ8`3iE{}CLAT=&#*39R$&|-@W*HYv_$9C&ysvDR^Zki(?S6+>DJPm#h2-P(*LGw z(9=k=c2m(%2Q(yzf%KOBt^zS*oy#My&NEeNzSJQk@DeEdI}!Z|Qebl=KzS&e@;TiK zU+%L6fs%nhji*Hp?vw8V(Mw|tdDIByEt5$A=IuINb|UBgfWF5N;%!*+(htUyYx;~o z1H3|qApf~lXm#>60UHs4OSdcI%-%Wb(&F7^ES2-{R(XE%;~(BCmfHP4|I>eygdrJ{ znnani>N^Q6!^0lEEa}!5R?v6-nUU_3@I@!q0hI#g1LG>}pVPkPO?|&@dJG`o*~-%y zB$A`fkSoQSw%nQfruA=S&@i=4b3)!wmaIjY{oV&WrDW{@z8X8SW8V%DHC0@p8yw zFhoOTwrB@21r~@2zha|Y3lf#;RbRMtd2M8Q>j6CR!E_JS^MsLx6gI(dmdX&6P14$;;2yNBr-k&48jRmse`Ukz67zuP8olJyOoR=`rx zWMjhc?DbDS`Tq}WCHhMK{{1_RshI$4))J)3A=1N4t> zZ7pRY#-w2l(g=O%+fnDx?E(j%4f>q!00^?dJoMmfOf? zbSpR*k2&gZs0-{>UOd6ctQGsOzyII=`{RejF_~ZnG96P1!;n23Z8Uc$BXHe5wvX%O z%F>*ul#ML5^UKT7>Uw%t+tU#poWOQ;o9hZlN_`Ir3kIw3OhbNf@{VcXl)Z#Jof=tc zOQ_VUS@xz9q4a57k9QtKxn#Z#yrMrcuf*aC4Q+h41LITRIB zm3602awld($xb^TX&EWEk?zN&*X&b;G^w<7*$Imw;fD!%*&~1DADZEHOk6jIqp^)P zkLLYAbI%P=oJ+#KfYuhYv!(+wH>3?j&&iuSYQevGZ*`1rG(82 zzy5|GSk#jvH1WxUD+LY~S3L)-ba|MJ5Hmmf$&ztS&mLpL4bXq~|oHA`j4#S{bCe*}Nlo{7v-N zN~uq%f$=3DlCRgHkSQ424XJ?>f^`o#_qwp=qq&e@0k-?*40C@$4>s8Y0f=;{*`sjv zT|fs@z=69{?3oMJ#v7~qFVSp`P|4u~ojoGA2;E?CtsoDESQ7hxdwX-<#4lQu-snjk zTWE5J8%EL=gu6R)W+bxp@0_J6%NZ9@1(A_PYc7Q`Pk(M^_mXCmgW!Lx^ahY2fqS&J2~h)6Xw)`Dhgg31No0gEVXbyx9w|t~y_Z{2w6cEd_a7*bZ)m znnSuG8yoF`MM#NGw0Nt>qMS0vMtw4BjZEe4s8veTKF==<{B&0P2D(O z+Xp=+MBzPYg7O_IznO#1p*6n-_jmmfB>q zX>%w%oj&?+^y_3tP6hvIofxy&V?+Wd#BhF@A4HvmuLAkjh`LQ$rS?xGaS;{xz1 zQWbyo03p4>UMRK{8dl;!ZOo%ve4QYyP6CwPX**KQe}8a1FY|i)^ksIAC5}fF<51k` zq{&2;y^_W!w;Yk)`ahK^-Mdlc%vK02JJu>;B+4%v4zHj;+%n}av%5iGxqbiGXa2Zc zKR){BUoddcfDA(dKC21L7 z;9}b#EGqss24WLsJBJ-*3;}qn8Y|U-l)ry4qhpXV@}RyB*vros`W{a6*zJO)auWsuHaUkd<&UbBGn+dxcJi zECQ!4jX$VOn|*~Blcie9*!poT=5t62ji|4jQo&8tg=%ID@x-yi=05s`ktdJDuVFVt z@fE>5Pf-lUZX4A}SVPFJSP;CAcXJzWP@psePZ@`#5_P@kozhZUn|(d-5NJF3taP&E zA!(e=Qgh@g3^Pcr=+?%*p8_?466cFdmb!y?O%%u-5MvZQnH4@jo?|cR3>B+Sb`Y3` zrBBfhGtVODn5B=dM1060?}!6N5`X~CNF59qxlKXJ!4Dl^mN?fFj^+=L(lD5axKcKS z$pxkpIRvcIfHU|P(_pQOzpzQnL*qdJo&4_>(ON{z7Pq8+d44&AWlcZ1xAi@t24bU4 z@DQQaHyA_Qsq-<1qTDvBhn5jSG0X_Y;X6-~0=+1n8|TBsaq`!hPMn>S;I_ydBjt$% zlheq_E;-(W6u~O)`!E-+1Ey$WBs7JG%x&xV&0+pEecDJxv3|hLkrHy;JhMwve(;pG zeY;O4>ucC1$_sI9How~fOd7np9MxPN-i@-cZjNT}u-e&CflzqHpu+Z{yxhBgE82l0(2l(CsH(rEfm`tSEH!FUBxg0Y!F+MKb;@pq)?FMc3r7tf^pw{k$^s;V1{+o%q#)9pEP zeyEX#3?xPA5&kWHY;hb+{4%+BT*`yClmEUjtO@o(nad!RQJ$TwGZ-N5M>EuVc2+z(A8m{m4?|+ z0Iq|6A7r-78z9fI8~!zA?WJiKx&Z7UL@5O;=-@>hTYbEg4@|0fv8Kn0c3-|Me2nV& zCLPO)umo>@<|OF{f4#Ugr!&ff?o(@z+ViNY0!H=+9M4|GhLm$0to+D(M-+*}#vql^0xPm{mRH9#V*UJ|6O(GRe<#ZdB z%J5kBeD2HvP9B@SwA51m#G@bByL%+?kZMy+o<4aY#`;$T07yUW^ZaU*^pi14leC~k znra(NsWEHT>VTds!64nWop>heMAFoG*?f{jkUrvyM?phtD7_8$4yuV4M~XrWHoNG$Y+B|8q9Px~(5 zaugCy9&oak{Z`A-F%6H|;0w&VBe#|(66I&zeXG9yz3olv9ThS#MZiu=HhmsUWzR+O z<$xh!VB2| z*jV6sIZ#b<0?vV^u$~A#o+|#VifHDTsCVesw&h^@YZ|EG>GL;As?UvWw%O<4%b3w@z0;`oyc~pV1Nj$tyPJIb~Wu z?mVuXu{V`e7)c~5hm1F^I_@7+3!fmJhM!na@}VjDVK*DXGVn@Zh$lr&3hrQ9z@=Q>S)Ba zND(5|0y7EV)P~t5wa;ulFCJhpbd0|rTVbjYn_tg@Wu_|?1CLTGNiQV`Zv%oJMGB07 zQ@G{_fRpE%T%=tmP+4TWc7SYoTAMZCG=g;2Zz*Z`sQS1Jm`{I=NW6*3GneLWHuuMU zQgFY2e88jFWaBioW`rP%D4yuTdk{_$;+UWqMvfr^(w$MojFkn}Q7QPLH3V7dNPa?3 z$9|sXkX~lh@se^pTPD(T@Dey2scLdQVLroa`LTbRV5Fo%RV$IR+P~GT>4E8~9>dR| zQFG>)HwBKL9MGoPo-jmP8d z7W~EmgsKO&x1(aAE>&}D4O1vp#zU$2^)LS6HH@Zreuvr=mQ`mbJM4j?;1*xcaH^xX zaUj#8VNzOvg3TCm!QKHI^Oo)`h0L!G4Km}V<-p85U`2;eV`)o}{5=}xxnG!RyDVN7 zT7u?0SypMwq$^?|gdAG6r=?6i>ca^=qn$yOpU{2|6OYAJ;mQ{}YIbwJ!T7453;s4` zz@-W7p6`IfNvj~{!3qtwW&2xa;k4j1_1A5(n4X{hjHR}D80#A#$H*Yc=W!=8`B%)- zzgG^zd&8@%v?;eeKU%9G+&2_IEr8WF+?O6cH#(eLg9t~;-DLgsn9I)c1R$Vg9(tSI znwwO#HoZZ~Uu?dPfL0lI7;Z+km~Hq>5^3mPm*wt^ZoTPy-Cde)LgA;2dz@-E;^#0U}&|=gcRJMvr`!C^DbPmMhP7PPE+MkOqPfMBQ8lB|yU~BfFH`96Ol6x+wj_C2a@~CL)M-Z7L7V zd`MhoW)O<{HM#CfHjq9vh*rxxh=-1GOi_m0ikT3C@j#rF$$-HW^cNJYS^{qFi|nky zI`KOpAkN-(@Yi`zcn{`shq&KaIg)4adLLI7*8YKFg$DeAg3wT)xmSVZv& zetx03)^op4ll-+Pj2tu(8_bfD!>G0g@L&NUCyJo!!J2~>;asp z?Jl}&R2t@H)f?NV4{6zvCm_qND#h6}qulFbkU0e?kZx@_^Pk;X>!p9QJhGSP{!c)! z^O*4}83$z5x~538gU#a}j*s>$587zMm^Fnrs}n0gu_zADc+Z&K5m9VH8N5p8a?GwL zsDCEV(~Bn=XGM(_>~}9t_({VpEQQ0!peQ*nta{Bq-28`lC^lFrb2l?9MTT&yhr@Z$A zx?n~n`3-Z+mNHo+FP2((@{-_uXuLboX2>RUjCF0#6-70Rac=phm`+Zx{ z%Tg8@4%G~&A$yrNLC?=m$K;Ca76;|Nm;GKwh`S%OZn$iIqW#o=u>j+57Gd_qT!t>E z?G1K}i0o$WP@O&d87|VFqMa1`aizZ;f|*&K$u^JN?;$`c%g7*>(QS}P@<>WYkReUl z7$tVFT%5b6xk;NC_^L;S)5xTsoWPKoil5SC6mPq1Fo9}&bmMP1wfxv&Ox9Hs)q@;tU2b19aUDdaCTyR*yaL8p}(y=t1} zFZ{|U_F8i*Np*kABw^x1giDvdJA(pelg;ddav7!pcyg^gyn@U$)B4Gj<*e8@!S&RC zdtZ@scJT8zx~y3V1iwUh?yeR*bGaOG;pDWrhatnuR2AU@9R^;=;p_LumlsQ8`eqXQ zZ(qLIEzk?Bx4r|+k5QB3+9-Tu^Si-L!hDbV%VmadAD$ZG=8q#NpoI}XH4W;X7fXGn zYHm655tD$X7+_=n{g&TJa(4!(tlMtEb)j9InAXqqu{W z&k_eA`53ec&jfVISg1~7`RAJd*7e(fNJN|UC`JR!B_MbC9_XB{N?>#A6e2bLF45Y^ zTe}bmRAMZ+1Nss=(`*p#f^Kqd(kxp|b!u0t$5ej6h*PlV+jMVz({vz;}ppzGr z1l$9Rr#ceT58zY2JSMYmu&6Yr=RBk4Ge~5<&h79FIE?M&NUwTmge;|rE-f@Uxlf1Q zB_FibF(zxnQ>E?7nK%SGSpz5ISJZxKGMH3+#;JEgd!M|%>_a(*Fv||Xogr{-FoZ2IYu}(skqn}12`xd2- z^W!KU+gH&%c&*ulerqK;t>45 zM$Jd+KU>=i%s#L11yWb)8^D&ts?-*Pd(2?v8O8t0*T4SiPy07y_3|XOIlzuI237y& z%82O8{$qbWebK+a%fk0vS{myESdRrwjNyL(jZPtIV0sN+*TWNOk;trIIihxHm!%B% zzpshG%%ut@0V|9aa_ zeeJ*?l%ps+{LgGC_ZTRVqfGz5zB+}I1PMR2vpFU{0~@t1aJ@c-vm&aPD#8Q3sMpot zA7DNfV)vDEofOs0Bs>6)zLc{2Z7zC80nEGE=ZVZdS;BW&j&3=`lmQEh zRx7+qrCZb89w+*+n8*`lrFa2ToaB$9WULB(8LN|iG)}h+cll_QhiNU1H$tK{JJ9(x zfL-eh8FIObUw;f5yE_$18US&NW-QIA#K+`5q)`DZoiIfnB5+f|s~LFs4yMo5 z`4YMnkLPy2(2jb&Tuw~0k+098#E69+rYM1Wkwss`{#(f2#)pM>V=1GQmnRo`=18u$ ze587q`Ih}%D)QfyGvERpYFPQEjF6*|N^92uhCy-<4P+nr@oVmozi&Ambd45_$1K!vmjxf;8=8 zl`AM0eIyX)(fN8?o2U8*;7SMG!g|~+LxFm82n*^hjvXESx0Wd0_#~$npY1d9ARO2 zvmOivRKx19P%er2B;6HFb(dYzQHK*0fka>axCB<@E+}$3bd@QoFvzZzl;s&Mn*wAK zH72zPAe=NW8gC8eN?yu?pjd5b4YH*Y+3NbBR7jC}I)eN15ILm35h%&hq)$r@sEC6o zr(Oq4v%+N(e_mS=cc~D96$PR0HOxn9X(aJ;i#G1y>q(XNXvnex7_=GQ+hZl z&=?F{EGo>j@ay@sK4{FnChlK$U$T8Y0mHm`N(@f$oxO)jf4Q+^+5p7K!UU{T`t$k+ zDP}C0tY%UROxQHjF?hku_`FSK)XJq@Le|I9Kc_TnFKub!Dvb$4?135?FiM6^EdFO> zvgHA;6JfC^8A-*@#LM!$x8s;djnkPs@emMOx;P9{!d>)%d*+c73MK3t05&xx;LOmk z%*rxn_vdiow8%?y5_SP7J+Z-y&T{WbvUU>oZ9yNBs|x`QZE$h_k;6|CY=Sb2B%Kjd z3(iy}ZdC7gRw03&u!NU*GAC;cD!V!9Y(MXIB5}%_m*~#e8};>n*dR53d=yVWvA^6a znf_A>dEK#vj*$r|NwD7UFUx&^V=*N-+lbgQFSf@g=|(Ln(N3PRe=vSyM3_Y;p~&Vn zlReF@uh(Al7*>jp{x|yShZEiJKM`T(R-|fwTM`<%aQ%aBL8g(HKxJ9x(L|Y&OW7u| zDq)71JnHBgCVG+pnW8|U#q-{29uR&ozBJp&J++mPclmw~>wB~=57NpSs(~T5O*v%J zO6=nS7lx)m&lb^M&edyZ7dpeapE9YFvV zjz`sg*k2GbqD$xKg?Ex2mPb-J?O;hCsS8&gI6;uGp@&!JoNC+?q z_I>M@0DSim&a^Byp>x3$xIKWZG>b0hvlS2hxb>sX$E5c{HwRXiyBU{fj<63ss)cqb z@j{T}5=N8m)S|C{XJW^$lts4fGSQ3G|7?ZN7c*k~+Fx+4ex$b|xclw(_5Bse#~*~8 zSUD`7;YX*f$nHB`EW1f8x}D8UlhD#zI3CaYT?1xrfm=)&aDfx6pfYEPA;UUYB=KVU zjtc6UL!iUt^l-cDJ)A{-jNt}R6WO|qF_2FiN^$(ZQLe2^xsDfm716S2_?yLdn~>2I zVuf7Wu+X44dR>MVfqY831T3WmsajJ;^rw5?!723QcFMCUG0SH(-5}Bxf#h zPv$G}?d#Y6nSS+;pZ4*q?*O-CL<3-u>wyHzUDX1$1kN3yd!0|n|Y18#MeyP|^9 z^a2B5t8(s&ko#OhiA|33WhmgF+qpA%b zEsfk4ru5u%t&{P9yFw`JVt=qxD3gsxOoeS>9ocROHq5pOY#jv!pNyUU(k)&EHAIUd zL7EdTd_zWRFadZ?vuv!ud`;Zq2aJ0l%Wr|1dqGDFSXRVc>uabI?;L~Q}0l1VeC zP-f-nLbARP5}rHjdb^6Iwlfn~vT%Dpy|L@H*%4Kt-(J&!mZsUGVtg{=YB24>sckc| zmv3Lc_222s{rmUtKY#rE^`q~CAAJk_#>`Bs-?CqM{9FCRgBVu6zWAS?7{KuamoBuq zyR4Ek<3%!030`G)h8Hu4+wI=12RLr50CjB&{vq?1mnt*;`0=3IWvmK=^pY0|aGv3nPiRJAoXJNP*@d$K?$&oF-Kn+syg5#dS0LOz53eD3Wa z;ZLrQAJ=!dy|bwjIWN*~Sp94&{>RPi8HkalA+wS^v_ZS)A5g{vDMc`URLJD!?#{*C zO_&+363DP8s02MG(kp26VFCz@TdsBW^?)fh={7kl=c;#^1mz^Il(PgD!`Cte-7G(8Ff8qvrYNQF}%3>!0wOIDb z9b5JCG5L#oixv(!xhhJFRZw?E$n@3QU;4gH6Y2YPrlt<59)8;*7(slH0sFRHucz&P zJxCJ}X{=2uQ3Ys$GJpfu=59q2j+o|TM4PFxU(b}qT&NJR;-`P=UhMxw;r~M)w*LS8 z{-xD#e$<2efG7*Z1Tske*+@!Q{dNUhp3gLOM6n@pFIi=q<7w3rHSOTIDj)p)>O`Z+ z3v6y3!QjKmGS%;aZF93;u+H5mU(l_%M3yufql8=fx0G6}zY2UXXh{(w82S zQT&uI9uin)T~-8U+8KJ1xQunm%k#6{GauJp_xE=9CszGW?t{MkQUAXqiHQai^nJHd z1Y~Js*Y_oV0emXGLEi+I(^LP_{S@{jML3z-)tw9HCnDHguN==^8F%SlsVrPa^SfZi zww>heeqxaK>WNBRx%4+9+)-V_W`KbbyzP$h7$D{>l4T&KJO@==T_a`G`SCeB!^N!x ziQep0eRluN)g$<9tm=Ly0#;=SF(kkCjCbeN2b(?5JB->Gd%(UCY{1DQEtnvE2jq_u zxW|+YXnpGLK`ht|$GX+x=2=1NlYg-dA@)7i3j-aJf-u0^x1~(_{~l60!3%powyx*v z>2?D4rySD$P8k4+Rg6ZY--br4HwzO>Ob;J*k0OJ*%fftE!u2_JaQkh531cU1BsQR&z32iT%=<# z833z#fMP`n)|I<`I4|OpIUR0*elq%49XG&H#GM*p8P)tWNII#ZiU`hHe<2t~GTT#d z#x7nJm^kPCe4xo4)xHDsN%nksFML$*QhdBgCa{~eM$|7Zu;6=2IA$Nq2p?o1bjg2Y+YEd9x`!@9R0U%os;aM_=E ze@l|XEJ-nniBh20!;-B|prvN|`29ILnQ9Yc~1 zq;lKy>~9JOGCPyCu*5@k%XAFxD1MozcAD$OF!~JFB*DbIzIc1BV&)UBF}vy1Zs0_S z>0o3B9{08he)nG*?(^s4jjQs5ENh8T28-KjpD(uf?c)po4+33Zq5aIZmOY{z3QbwI zerEN3Yc7r!lMIIG+sv~bf#Hp3^AfeLo%t6GF!IVhn-}0`4%dBG+r5u#Mv6>;K+JMZ)fJXM7#EO_j5Q;rD~qtW0GS! z2ZuCvH*Kxe=$PvWhl)89F*=Tf)<`M(%C?1X$((%FnA0<`Tf?b9y^ymZXmtg zP>qO~h!=s3iDxKm3_Yd1^2^u03Hk-l|7bJ3c+|9#|LQs9zA-5D0k!lM-xT^}70@k0 zV^ugg+_~b^*Sr}RmL$uJswDYYusf@N9L$ki??TSogZ|3%ks``Bh8wFqm^N8CIkx6r z{+jZ6wR@0Z9hdx)}j_j|kIeD;aHN$p&o!c0Z}NjmrfU$r5-xkC8Vy3%irnKh2< z%=t>8W)xM`ojzQkK%KEh8x<80L&ld7$Ok&St+!hy04iND9x13}_d%N912%Ihb($S@ zjE2*Wes7H`z7RtSa(dtk|8#KQ?Q+y14P3 zJpXqdz+n8p5sy?IfwBZ1_npF+5n2wO66b){ z_uAS2hT;o106EqM0a^R&W?tDiX~MQ>=)K5+Lo8#SJ2`xGg|Am2mF{J;8*Ot64Dp{8MlbTM4%VFBdy z#m;_P>)*b8!Sa{KMDKu+KELTfYh+jEI7Es1KwW0$)wcHg|9~@nc&kmG9!z1`#;=2B zhp`3LzJ22mAUg-TIX$z=u}q?BEq^@pZNKUIrTKKzKx2-VBQwxGS!ROvyz5IxJi+67zy+h zp5c8c>L%ObYkdr7rc^K0O z2oLLi&S!QI0RV;JI0Vqb8b@^wXHQq0zNBE@T6$r0Zs_f6drmN(Cf3l!+Zc1{e-&u+~6dcgVl-Wm=a}2Hl-U9r&(ewA9;S zabfLL52g#7txCaTU;oW^$i9^8Ei7lW8&-5<;pCN&$+)MWRLG=uiE%QfBKmL6zxo@4`ClQdD8N6c;6t_ySE9+#a}Tpc-UT<>p#XPx z5!S9qV5OC5a0Zo((4M~NzkS0Ge{mPs9(b}S?|eNJT2BctMFK0Xh5lIYY<$sgVDMm@ zz)04n%$)Ea&;?*kwyiO)eV4%BA$iO86xc1n$D}{e+2=&8K zlvQ$`D4y{-KIKkfkZ zzqV5qOS3~{lUVw#pf>e4x39ro@BnAE3*hzlZ>cQbDKWc}qT?)UxL6z3e?Ci|Z{^SB z>5L}$%t;s)=8_)_#z}pXqYUUpyzD;iYJXjMf^DN5DHI{B@;#eYop5N)WJF!vz8l<` zJGrHpFh^go#^@VIHQrIPC*>ZL3j0^rH^4qA9l~%fSai_IWDS+_qB|nN+0&a1O?j%{ zWn{hdA9r*1ygmpi7|{+oj**@(m*JA*?vrXuZhJ78d41Wt(=ViQ62 z7Upjk7{VCl|H}D-O&o04_8T>jDfA8gH^Wmr&9HPN=^;vgNc5kdFVAPp2m7BEmjO8b zgH$;yZ*bCyV`taSJ2rw92ljfHtK?)tKJ0w^3(8iT1s2N$7aM2-fXNx%CHByR+r^?F zS}O}ySFh9hao9#^9Oj$_N1$qCE*&xktNqR-qpf+ekNZ~GCowy4H^t?m)o^mRD+|L~ zjZtRZ8O=6${#hjiw+`R^CR*a8J~=uTw?HWoWM#eb3ZG=$11x~ld)=Y$q`?5$%SfCq z4|^-6*aP`;d5B#7kmB^#ALW+8y2*i9bHo_b&dCpX@~KHqXK}6DK@2Fkic&>YF8jzc z=1Ji(9drae!A}k(H6g!Hz!z!OP#AE;=2GKzgw{aIRTWWe)jtX!RzCD``M?cu z;{=AccfjRt=VxF0De9loX;PVv`&Bo9GkBY;3&>KW7_R^oON2k*P=iOfO+nI0Qpf6($1dRa%mSVq&G=WzEq@U9T z*AF??{2&T+!bn6@n&D|Bb~+ns9QNP}!%FM-+%PJll#-ZvT;Vx=dti z;V`59t#^l+NVXTecht2iWn6DAs-XVgnj(M4r8JYOUYg80yap?YICE~CUmKYkF6Vv$ z4_%~|vo_$qfiH99NrG&@5w0`fEwI9yUHZuS&b1_8B36{gEjgLvfe^L|Xq~O=_e`%` za)kDD_sr2WRb+{zfGuya{GHin-%Lx~3!eK8uDAU&8b1nB%;Y4DNL_7dxCu|uqDlm; zg6oF+Mop76&k3V;SF>9s#h{njTyIA3c@gdju;=T`7j1@T(n#Si(W_vVY5+Y~5_bCI z^ac1wGz$|K|I+feA6_*8e(O8nhCYO0Uu1THW@mN(^W~z&Z(tG9-T#1sNgm;QL{Nae?ed}TnWaB!u;&-mLA?Pu(@~}@kpY%CN3tT95HHq#(2PFVo%`)azBGit zJOC0^A3&QnbpfZ-y0|r(`t({^bJrc?M-8E!F*#hp&vbG`9jU$Y8JvO83tRCRwsh=#L47S~L0oXU3 z#7j;Oeyg?%bO}_Xb?@N-Ge>;eptrwpX+1qAEB4P`(9f{^$av5^J0i6q{vy@13}+p| zxq$z#NJHXQy@#Q}Lh4k-yjN)l)u-j|z9a*g&|kL_Y-w4X1*jV=%M(QHC%IyA1K{{4 z{Qm;NfB&PtIubT^FDZMuig{V0;s!AsPyLsD@mbGnRnKoqY<}Uxj(=1?Zy5dphPB%| zJpaLZL-F&>91muB^zQdr_0J|-F_H_a$I2M;iTkL3V%gq}_5T51Xu1qV(omQ`*i4<8 zW^=N*NN6A;M2KL#o|L{GA#C7oUp*?#t{@}Bfy_3Pw=_RuK@oZ_>gND$pwVga;maeQSQ84(G!&M{()Ywx69@0}(+iQ8@zK|1KM@aS zmmE&nCn>8x=U%n+hv@4MYril3-;~x+W!8Vh2n;OikGEc`aATupHi6j*C5UO1pD)jk zA6Af^&+Y;SqaKD;VNuw*d6SzwX@0M!F?c840}P8@vMt;gi?2?1J}ic{V#3ycT%|SB zD6`1ovb8#KEAR3d>;KWHrYb8ftxCIgmr=etlqYz$ksu+jfV_afqGz)ZX(z~*e;Qzs&4%EB!T;-uZsSqsr<#u3xpaT zjMByT)nEF-`SA;N=zZU>?_mB2`O(%l%G-riKac+xe!~U;E7o4C zEznQ*zZrAiH;QZC*kZgf`rwEYBNBAvwT$Jp6cQ{LpSDd#O9Y%<15eS?&KiYNL`<*u zaAnmXOec2<7Xn*Xy;3s6lj4L>H+vbOzD?@Yc$*!9ZF5}xm=I^nTku5RwdJ74NlL43 zVh2T!DmLr@sR> z0b;fC?KZM-czE}PbZW*r$t#e!Vnp=&N~6Nt{jA}w*%{D|caMR|@lW?aw8wcQGAixe z$)a}y7m5s^uX)ifvfLevs7yin-qSq4$zuiA_;Mf!{$jmctT5mEE(0wDmseG&th)(KGzk(8b#)=)c*Q8&qZ1^8SdApS%IA z`Zuw`n=MYC8QbepV84UsawgjIqSF6`?S~a&m*>7ZtuZ}u`pbS%Y(L)Urtf+C5TV-{ zMj!82m5dYm$@Z5;uayj3{ueo#T8|B!i2(#0+`_q}@kCW}4{opz>@GG2bX+trh6tv) zp%i(c@YREQoeb=fiTi;V-ON;`19p5%um3^YTt^@z zm}^`pw)hv6L4`q2n2yPKy2h&(Ts^|1q)=q&@cS-F;j_oS;rnpa&*j;@FXJL7Bk@8TAU6 zOP3dLs$;FTsmiV*8hr>71)qfXaDU}i0^rRPg57D_Fg`x%eo96Q5S9iJD1fY4r^O%p zatNyTQYl9(K%YPdXT*zOy~J~_o=(SzjHZH7x?vj%E)vRIw;M}i>K{YCEx(q8Q7b->eheU4zljTnEPZv!jwc(|E3Gp z#Te?lJS97nkO;3RT(&}yFc_DE^~>WmxtUMX2yKG6+=&B{oV@f`uOGgYRQ`mgg#Gu^ zjODBi!09jK2LmZHrsmKW*0UVFfpTH}wiP{JA-4H~@$)l|e-6JqQp7{r>>9rThcv2% zP266oZ|*x0w?N-)AM}>1b>v`YMcyqm8ZyL7Yu^wcPC`y@GpzF(OK0%uZyzC}7^c(5 z5q6QQ%!X`-SLGU~>}j4m+)54>8zKlP223+Cx&~1jzTNv>ygQX<8YJ;zIvUD3FlCI< zKShUUPwVMV%Wmq)Z*+V_gi_(%fykFB*1+$9*ckMx zF}dO@gACR}rB_t(hJ;(bS47jY?pvV$X9x0evfMHr$<4!hlIO6_Wa>2K;LZcDkaD}O zH8w&hX_N{M9iv?&oE|IXQmH(CXxe^R*h1K#*HrZ%s%L@*DerE;r<;lih7=E!Ug`2ceU0D2>qbLu59{aD{X%qgV2Ee%w zWsLoog=8m8oY4a?bSI3>oPNyepI!x&PjLC~f`pWj6&lM`^7R56pAwFqqHSVIP(g+8 zY~KkSjP{t`As|STx}O7tS60eImXuBL?xaY(owjKDvod0xPBWZscTs9!@P9WGlwPOw zM)~o>bB5ak&DLL~-M&^B%T)&bCU36zPCRXlMl7}i|q zZs8~;-65ksCzChXx~*iMfjf<))8-lOXfFGm)z?GcEKAer;sM>NhCB}>>k^>R8qObu z)_XBJ%>+`sS%$x^DYU${{8#MGzA6dor#&l@UG~n)a=X(0(LH8}G%vRLHyFWD{iQl8 z^Z<&T2hu5R{I31bUrNx;7r5H5r7||DcNKe$=(pB}z?4~4ha1HmWOkujJ=VT;cF6SC zn40;sWHN02Ta2?~18Mqc8Isu=*J;GEwTFN>5fl@e@io#nY}Ad#_YPSj!ef3vZh)WS z``D`d?GxV{>G*DCuo3b%ngh@t=!>Z?vj%`;XAQp)vnS(QP##R&Y{nKG`dZCn@&Xze zkzxG?5BEL%rG0j32gky7_++d96085>ENjdeN)*~uR2cNR-{{`{PM%%g0EeP-b*ACb zOvfXftk#geNVVyg08I-gu;l3W}~sf*|o_0c5=4O zyMQVKpmcZvQlaU&%LEVmpvZD!f&JyuPHR6PH%cuQH54PyBlN+0^rufd``J@vwLs-E z-uPzYy+z=C<7HCAom&&KBkj;tEbcgQgdApv-x{efs%qj)cRR%FaIjpp`EkUuo{YmD z;M{3u=EGyc13|rnunTkp!0f+CaW=XG!B4Q=eo^r9M`HKuSp7`*=_S+|Z7--6FXWgq zz5A;RENL)dz3=(FoL0vFQig?C1eD=#?{6|S>YMO2oQ>Z8yb}8-YRNCLq)1o9u}IMA zNt_RO1akw3{V9$nqlJMyn`hkzJRG5*79|dk5$2#g%vJPM-JO=J$`*Mo4Zaq*GQfl$-~gXyD>#Ol2z&_&uGl zSAk0y@~>Wd&aU#z@T$YpE}Y&E3^J_ZKcBaD+SEw;u!jK3ky*y~d)c_=R$fXEOc}u2o}oe=I`r(m0aAoAgYvmfxQl&-wZ6$8o^o5O>1iRvd=$+EXqFv(auXVG&UB zoatOXoeC)eT<0PQi4e&xhsy|YvOVSqAlBXWLmek5{(qDo23JvB2ejFGBLf-Ju92j) zXl_8Z1(V47f`_{JFA0nxHFyE_(@GL(|2aB6c8116<7=x>0yBQYcNm$zn!Lul(&}16 zc9jCSpPXV1%7tfnoP`N5K4??*4~q2_E@9Lcu)ea>|Lzmu-Rldiy)}(1UEK$p${=0# z$1tS`j`+U7YN~@7DwJOwPEcq-;WS3@LGf2syb`Ch!axoNr?}I}jxT!6D;GrH1LEIQ z2kvd$=6b9CC72;8Ho;>Wl$-r8Yu)Op)q#7Ouc60;!f3e6@fCOv(mG zRCr7{>)jea8JWCN+{^VJeu{9|dIiOQaySf)uN20YOTeAbmO)(njS{nO8hzR1OZj4i zZOktK7T=gb*#*?g9^^LRNif6U4>{JaSCM~?3Hr=F-ZX#d3#fLu1D-v~Lp%$fAO=(( zay^le9vfd=ef|F;pN3WDFY7SSMO}ola%RQ=k(OCys8Q}S+Wr_`++5nD_OGIZONUh z+Z69Az7WV^t-^J~hqm;2>sw$ypLZHsV$wyT71Mm-jWP*8i5 z3utMUt#h=H02P?YCj?^_F>!N_uyJ?$;@8RKfa1Snj$L?P2g~4HUTzEw=3@KpM?ODf zE@a~;OSvF$CVJHhuBcf_KT%j9Z;5{R+tE*pEvx;XUY^cRCQPAbh=kmJQknD?hN5qj z8Q67WgwtOvzg`vM)Q{@my-kI&V;k%8q?Jz>_b2QCa|>4FURlVU=giS4cGvsIhZF`F zWLpUY>lZPAsKaDEjJ<<7fWLF*b0|M&1RXgE&kn8Qdh;1pX{80aGufqRq;H^`v3Iy= zH1{=K3~3!u<{oJZ`HMJX2)v7;+>CH<#&s@IrVO7K7w75-i7^qk>wq3W#Qyp?tqs&Y zX0y~5=qH&7s8JMWAv+@XdIR77zSGy0{c)SNT2pRfiV)*RwbuwqOTlt;U9jhndn}Bb zU%TUrgP+6dD@-Lu^N^bB{f@g+e&1E~5^s48FHt*&(dnw(r}qfR+n@#?9E8f)u&=Q* z5;W*0>bm;BAg=%GFI)a#{-7m=?=t|j!u(q6LCsQ2b^mXw>H)Y$isc(frihc$*wVNN zg()YpCyT}Z;@@!kKN$f?CVSR6a{KJOb8b)b3G9%~K z@V9=9=Q-lu@5<(pN_TaVOH37{U^MuBU87EG&X8_5A7cT`-ysqy{9K!zA}2dX&$qJ? zJ8viPZMM_!Qb(BH5)tGvKc8H(V^%({gZ!zSe}sU%)-llzk)piBYFOq=E)x;}(}^@h zx(5;Ve)kWR_wO#)i(mf8c3aN&8oZO_GBw_PNDil5PQs4JDswfKPH< zWpWA(`xt{x%KwKyG^4JC~LC2pwt83&5n!VhhOK~}t z4I9oX<8^J1Y|x3=CLLI>t&V;(Eyy0euf}S!Qo5KKxg|8W_n8un3-IyDH zqdKfMd4epE#)BwrF=Q_WdaCRFHaV*Z`7zR)oyLfoUD)+hRXzs2zhVhmzy0%%rVgC6 zVFUDn#V5|NiYhh`C41 z8QL5HPbx&3y#ETpAkzj`CU+o59&6DQDK@{Y9)mgsP$rM`HH*oeC&B%$d8Qj0Xoua>6NI*#&>PoD$#6sJjqMbSO3Sb?zd^~+uPU>bdaXCoXLVQFVf1Rbr-Y-lotT;q^$%# z?D+rdFB*#?TgDE5JNpgx2}f%SHv!q%550mMJ%#o;LoZ{*)ZSGW{OWgBe z=Wt_)jqWCsxC7VZiOvaR9yM@gD&9gasvVOM3BU|6`0k5x{}S8L5yLoebtD%Q_ce)w z+eM7KDQtO+TVxpQAciA~mY<<=U>7Hd2fQyWWAA1(*G3lF*;`8?a??sg z9v={ue_;L7P6vnI$NMnSm7^#mI(M_1J;Ea_mm(S>MFNKT;KRWFuL$A(0$UY7{9jyY zY%{M-&hO4XFt?R=0I!DmxVoO?YF8LD!v4>Vy!;2fQX?Ive@<<}FVA0|UEyqspXW0M z0L1>uwrq!z)vtUV%+Jfz1+=h6cGK>OlRG9~gt;k5^ZE5NVccl9L? zZz=dKz+E(Q>>x5f#ItAqHE7aubc@yRM?aW8T>P5%s`BC2EUA|%Sr3C>Ji|rszY%AkWMMdnZ|AylqJPUc58ov52 zPy;Vl_2}|Zn7X^uItKexXLuN@-M&Zw>+OI%P2reTDL+&l)X$Kb!aR3CAHCW)cZmhu z9Z#$&G<7r#(0F#G(wZ&N6~`m?9^6>+I+#N1+zl64SRPe=&8B4cZnTg`;*2v8!f+3y zHK$qkrkdr(9o1h`D88ND(|43HgKVg`mX&#`*X=Y1(rfYS#~>>EP7qK}=zl1>Gr0n^ zt{Y<6iDc>-lnV3YxMIhNb_>^N`RJQZAq5}iSw-vUo6@W;5_V^B034R>Xo479UIZxU zY`S{Z>POT2W!?Z}yGiVV9+V0!zMDjlAvm;>%N*o>6YmLrHC8|LW&Ka7FZ;X}m7rx? zQ7N#rb$PaLRQE&wg6gM``qLnnbIY&9r@jm@5T+3Qe)f;cI$m23?!p_sYWW^(}y38!;Rn zgAudsPfII?{OfGQG#uS%n0-LZZWlFHPD^eZu`n9M8&f;h)1;UbpVUmJgjT@MCsE3X zmDj?ImeW}}{r|(O^S3?Vbp-kWbKgDO4t^+&5057_y=L(nK&o~v|C!ia{*Ir1mdNk#COkAE_`sMbzoY}!z<=$^SY7E|; zY1g;G9khctpM>95|2_EzL$6c&NdkFy1_f*jVpdm~OyJ08o)FHe1yd01Ud} zHnxHFDhOvss5{jL6oRpX2H^v#+%g6|)DgF^@oazF0~&ILM>Doim5Rb%VT+9E<;!j2 zpc*Qa)}}~ph}nyekukFNS{*%0qBRzm5qBq>WIUvG8eq%OtcM<1nA=&W0Vb$qnqFoO z7U%nDnzKZNA}VJ#w_S$+~!mi3>1 zmB;`L=!<$^*gl8zjYTE^*kyptpHSHRdA-T6?f#FeUoFSxiOlr>NpzFQVOJSr9oqza zw-#6w3C&!WdRHL?9))aw^P`;&y5%(=;hC z+Qxw1qCQxv%ylwY@uPezq@Bvs|w87 z5n7XGDn{sET&iC@Xwjp~eCv;B055;C(^pdku#JiR9>+LyiWQwiUgO=p(;4{5Eu$%6 z#FtxVXY|Q zclk@O@#P%)AJ-z?CZC*f^fhdKqx-evpUmf#1+cRr>8g7r==o->YCg~_ZowPtj(@vw z(3R@_k$3(`?rT#N3jaMS`#L!`HQNbGTiOkyY+fM7DoC_{m>OAQi7x%EEFkgY)a_f@ z`w)vEHyZsC9+2|Fo02wS3*d>Z;=q(JbJ)Yu$HmkwjrVDuec2X0ZR9XeJm5u*N0j#8 zGOJr7|G7NgPLYgl?D=?3P#safDdxIPP8QuQPu$Ok;Xs~-h;#=992S{mN91vjMEc0; zK0-MjjP5o^aI3*{K`;}GWvFs8?#|QsNtxNtQQ}9@{lcP~#tQ^q9E+pZlvh4B?RxtI zOF2V4X)M7X;4UF|U7N|?VOsnTm94=(7asd;y}>+^optZbFK1aF%2`^C2VE7fZ=7^9 zx!^a*PJdoe`f&7n{PXcIbYhVq30`f3`^$V@#-$932Ee+Bz+8$;##X)q28tGGDpP() zyMUuaM(F2FfezB#untO#EE4B3_!#81oV_CId*ckFyhN4}X>Su}xJ2%alhqPT6Z5!4 z%nfy0T9S{B6>JI9-`s81hH~;K?a)fa@H0HZqM+Ax>bL==KIHGW zd0yNejKe~*ET(l8XPX+EQ5N~;V6;}7HIcxnhl9Ji@)e<_p4Q0hmS-}HpLx!5^$$Zu z9Q%xQamHnq6cel8u%!=MkIOxJNWd{NhU+ zVT>Drp%_?hVRc8IeD!YFh-D~i#bfl;Y&I^~0jh~50K?t@d)es12Sfv6Fq1j$8E47) z8<6nyay~_MG2GG*-A2_fE*`GZ62#3ym4f{a)1-<-i@XDNbKbg{`O|&9t?;DAH;Uby zQ)Q6{a6@G#`$H7H6Wtu)eE8V|Hr2GZnd8tV=b?Z8p?$IyRb}T*71VV_0|_FtwuI#) z$k@nBXiH?C`y{T-vll!bX~EFN!o!Z6(bQd*W}#^p)x|$xto2=|KkOyQdjstAAFH3X zTApL@MP)y31B||&`An7t$A7jQAYxnnIgszsub|)1`TY6yhy8Dq{{M!ic%-^sCfZ6b zTsX_PplM9#ZweUF=J3zft;YObMxyt2KX#@nRV%X@CfSnPa}s(s7tvzpDiXNz#`Iw1 z#hGwqfpTSU#pR1Q;YxipbI_03XZX&qT;|y6nes92lw(g3&uRRN&5ThAOldZ^k`lwB zp)dZveD1J?(svm@-_?|=<| z|Ht=n2L$8o6II`kp zM^Oc7ao(}+Rya`i9UvL0WoIOXZF%Ckts#3kSNqXc{wdH$njLD$jskFr5~UHOONdFE ze5KO>d)f^9w~?mM(!{NvZxkOfMvWT&5o5~C^K5eux$QBeI`SGBT!G?(zj~6qd@Ox) z;PNovXr(~6zFlM3L>WCywFrBftFB!JW-0m$n&1Cg{k;_-(V961Dt*4aFg5x3x7GiUY*H4u8$Bz%6Ba;unBvQjidQ~M+b-OVf?)>71e@dG9LmDa5j&YS29kZ8>(ngMw5~@9} z6shq%>z|b2sJdt>cql1$sL_Kf4R0sQK2|@*y&QDWTI+`Z|9%=HPovl9|5k+bYY9a^ z5B?yTsttJgf=mN=%S~f16hGIykvzb5Fij02%(zYhJD@{Z{AVV@i;xPk6(T$|#0k2aExtpwZ6b@S#7-(++` zqemD-n%X+<{o3}nxA4?f1K4JVwbo8NJEc94mT-|p60j})gO-NP`N53s#z$M_L$unr z1!sg5iiGl4+X(x*Z)ODA%Ya*7F=Wykwd|O70bOS%^wOVbG`3E2zzGqtU%8E7sL<5d zm(s**a`o@f`jiQ`6%|7f5nH(Ddg-GrU>m^md-0oQ^)R9(;6KMVMYqu*iR~Tq3SNlPQx6%V`9JWC;K6v$&B9j5*lW(l%ZNDNI2$ zt!t8hg*2whbxXfo6WJJO#aESaVVcX55ni~5shyo*2)ONF@&p6hk3Gl>^rw*%G=Y6> z0$~bsAKMf-*Opd4bf2lQp}IJjrpj-9G18k1-{|(kd~0YO zKWOe^_7+(Bkzv-i1B;)3+jZIi7=H0(yU^S8i5mb=PQUK6Eib6In~rb14F&Cx;)KHUVsE zw-#Y+=!=zh;~DW`aX6w$F)#DkU-em+GAWkk^nPvw`lRl#e}?JvS&-1~dh1=T_`7s8}jnh@2mcs zX$`)TafIXl8OJ{*W-ffa?Nm8`j2tKb_-V(#M34Wy`h7G{?)PSWHhPVIAFkoO*w2G2 zwr^e`k<%1CyNW=|m+9)EeKKFSL3rT9(Ta_uv#_^)&ZJ=wqPTa8V#u$&^kuD?jMJBx!^mVOL6`l#&*?& z`kYUlj$=?2+;xxQ3sQKdO6YKl#^V!|DN~J^M3o*>V)X71yHnkxme;AMQTc2`r*QIo zb_4pr*gKK5&2_L0l_mQuwCpwUIfu6brDUdTwB?U;{->L25$gZ-+vJVlVE#w_-JbyI z6)rD;$`bYxU!*Xz5d?RwS+)Ai*~oULb0^vE748yv76|g|RZwqCC@fC@`LPNZw*OnL z1&JAGu;-QUE-d!#WdReoubA+I=3omddJS{TLu)r7;w1W3PwZ4V-vaf^d`L%rLp+F@qM4>B%aKp&F+D9%&sB*K(A5*rUUyZi0FqXu6+Ko``~yOW;ak zgAciYcw#S@CoOh>Zv#?RnNrQk*l^}@LY|!K$pFWewz3Dt3Slep=Z_mYU=#d;!d*Ud z43Ga8p3kS%PcyA=BfOqNuP>lH!&hsY8{bO0QNM&j+OOw8OFKCEf&=*fS^XLd;#DKP z;+f??H$a#$naTdK_OCokp~ROdTUN$w2B@N95%0X^cVuJ`8HIutR{d7d&O{c z7DE1xi!zP;yobqR9%K$>BKG14w&_~Xpl8WK)9 ztU&V`MNq_O=(j?kGg(QednpuKQ4Qi+qH1{6pqqxXYhmDfepH_J7CS z4Qv6;=<5r#m4E%^1}j$ke}TKi)8(bN=xAT;b_$un4as(#_+s@3`b385@B8il1N(f! z{(I?fFq73k;@I`FaYd0(i=Fv+SuK*wK>uY4%O8w#@s=%eJ6tjioAK~E!jqQ1?Af+a z3&D9;iMP?=F_3E~R{`gq*>V>5hFZ#+*5;r@zvev5Z?Nt7=^$~PZQoUR(9#F@8to&M z|fon@#9U#)NQllu$1K!hKb;#Atj>IdEE4yx%ZTup!D$d|g32~K@q z{BKsja35TWB0JH^^oe(lCv73^3uSKa^Kgi%f6X!-Y;NAGw%a0un zhZ}AK6*A7!nV1pNDr_F=q#2rxwK*!YA)S$y`qfZblea>!NFw75f$i)$p&_awX84n; zq$c;nhzRl)Uh-woWh1%9Lt_?@ukD8z0EFOxzr-+vl};{0IuVIJm9zO_GU;WH#Rz?P zc#DRtv@qAI=MQund8M?)B0c|g_2<5%NwD)VuL+V4Anq8qM$K(rUpF7&LxHFekr zRhRXEyDYa@K5WD>JF8l zF_?kGF`i0JVXJ7Ch!C8CLN=7jl3~}`eB_3-!2yFX7ko-!v3=ozTxe` zc|@f7yDU%vTb_}&Q5oGenFz|@E4MrcS41v&3cw34aE1cdF>lO_z70@5mBmaC)8y?u z8G5Gt4?Zl@#qwa(;_cDwj_$EQW!7#w)tdWZ)MZYOb+wSI@4~XosTlVdr<@X3As;~z9Jho9(gk92vnC|@f+{#CuypTLE#K1BNs^hE9RO~#5GdYRY-8cWt` zDKi$=-oX!4K7FUrM()?7Fs8cff3x}ped43vGF1FTh~=qQ{{}aeHQx0IBOvS@CaIE; znbEg-F;Ebc2GF@a?171;V|$=iMz{x@+s1_8@!lY7*c#&N{odT!XH5^<7u*8+>(~S2 zTsI%vOnafV-ogQx+)jJH;f~Y!-hVjlY7ECVP_T#dlBc+$Jf{KTOe!XcYvu-qx~Ww5 z2mQ3r(zM?+AIQwvM=m1~@PP(5c|Om}-+dyOot$T9ixTnB;VM147R&W1i>#IJOOCNtmCugwDYWokC8wu8&_Nwyv>o3`h+PD|3 z=;hgyv{%?_F-GZ5#1pF@cJ4oZd4vrC*x$WM``@g79RJo1QS`$oKYHwf>5U4qtn2?{ z?OYVwxRoRdV1|_Su(SXFk!wrVljH!4uBvWeXeZaoT{&?QKVpdlFpci2Q{iH#4v0z~ z^MAj8*eWX?{O+B2AQ&>_KDt)&6pvac_5jWT+XH#cOsr*N)F7Di`;RL^#n3T+`uVTp2zW7Rho7TO3$0CyhkH1^}7UOky%j`&B{aEx; zJbVkY%NLV6Tj7tXWVL&;C_5rmJ{WE=|@rLTR$`XSF zzVpH#oGu<7BNy+^1L^xq&jGudJC}40Rd&;sW1q?UH0YsSwJx}CA)R;$!upWfaDI_P z&RzDX3P;D7U$h?u5ZOTq3&|kw6`ofM5}uzd2K*6ea^SO^_`Kt01wiN;q%u+mJ(EOI zttOpOonvef@Z!3`I)UIpj4&oNNmB20l|)?Qi;>%&UmY!t4bqG9O=|q@x2xZbPUh{h z{`v!(KB4uI(m`QjYQWQKgL1%RFO^VhOuL?6C31L#)4+U|BnRYrl^^hI{QUA@+ zzV9#3nG;iQn{QOf(jFGux|F$$_au;!_3GNd=2AAOSTS@n{y*TAdCUGJ0D@kLAqoM@ zrFxo_by!o83Y|YNy*kyuZ2Taq$?6Vle!cN5RFj8FW<3N=P=LPrhcUAd9r4CuBR*c( zcG)j|Maogs)UGp{`1mBsQ)%&3d0OMszQN)3Fz6EC8&c)(_V$Y_j^MB7umMXR9-Bu- zxb`3ZkK^9?9%7nPd@8be-aXth#>W2imCkR{VQmAHw9KK7@T;Q?>Wc#pKGpP@PHXcI zY*~h`>0*cfH2Y+Qo1A+f#U4PXWMPsLQ~}wa149F|AmWs=Jig!9H{&?~xK%D56hu>U zL3EjnJUMxQ&HO;HPmQ7Hr<3WMsU0}sKTsIqS+K2YFBV=9ri*KYXU1on=TF>I#Pe)) zq^p{NS;kqi%~~M~=N`l1UF~VZlfe4SL{6erTkzYifHtXVCsdbGkMDg3(W;!o7fQDY z(4~)-1ZhDu-(O?RizoZ`+RG5&L$^o|**w}lO@q+lEREywhG+l7!vKmx^B{%u9Tz{t zeR1~`*Vb1**bX@RZM^%W>+TOb{GVX7??3p5ZJ+4C_D^Y$y`VFtBo@QA!L-{h=hfhv zi&0HRwm8aJtIw9Tt{UX@U%sf>hqVl$5;luXhbZ-FzKD4rkdncB{_KJpQPDUP#2854 zGqG{0zuV4p3|T{Kb&+<|udRd}W^(^L+$l|1mbn?JbTe#&5Ap?%z7-Cq(++W{0CvyY zLNgv`awfzWX<2~=M=n$Qu? zbf2-=Z~9YAyS(Fx)&Is@FQ#4QF#B$m&*OJ5o79``K&#K{t93VwZFY zqk-UEq-ed@$KnFD(&lS`?rxS=x72m{ct6=#HY>V>^}6_QtXK<)poJ$9?gJwgSkZqB zA*T305Acp;kQjwIRLiUw>9lXHiX9Jr{x5e%i*#;$49L{hybYKl*EJ=-I=3?#;O}sS ziu@lMn%}TKtM>-V)gEYNWW4W^0Q`a!t6EDvmAq%x74K;IgJifT`LmnEc*7W@t8b0S zdg)9rLTCY@2#%aD{g1c)jj7SdtK%lx#-ule)U-`}l%5C00)(Zj?u zr4@o)X|oMNoC|v7#~SM8d5FVq8z7$c6lgc5I50c#GNM#X6>a=Ot9%ONW<0N`Bwg0r z<~`7V3Y{F6?BfzxmF~njaI{?cS>OSc()D4^Zuqk1DM$;CWGbagnPUWWk!|Bg;*x0p zPrl=Q4g3mx4v$G}0@-d9CT|6qCFOv*CL>YFSBpEI2){m+BIwu39Nr;tyf?Lg!Xks0 zX?hIMML*@fT5Aoms>_+*1B~$T{=xe$kA7_fQlsC*(DnGB%dB4ACJ{$d)N^wDK!o@7 zQ}&Bs(e!uu4hW(g@4IkZa`i7v4Jx(9WB)pR^vaW zna+%JoEo=23|(AFs%^k4L29#F z$nAzX)Yw_d&+LNa%&SLxd%L8!53czGRhAP6cai*34+Kh0$}b-d$r@C+IR-7KITU{1 zU!ARZqoLCro*K@Yjm8_u#s=dqzXwRVlD%QR9vM?#s( z9%|gY?Q>6@BB-`zYx!d2El0{7mt~B)V)eg)<4o{;bmgl%ya4p4nx@AjHP%*VSSpL%zQE0dkC9MZpL3ox zE=7jo4TD~L7Y_&7USrB*NG&}I;2qqUk`gyO`y=w`up~;`(iJYZ!~;6m7%bSsQ$`~~ zw1{RN@T34WdT0B8a$>IOU z7^`aircd#YE)q48)Lo^th=MziBPd^~J`NHLb;tN5-el!Oxh&3JpO0Zy19FpjqcC`};`n;! z%ONmzf+8jI*G!!9)`&hgH?^Bl0O47r%Onyvv}!DmvUF;W#f>3bP9r5Ur#WjdjaXx6 z1E@BkyC53#K$V7zL9;&v=o1g9+{JA}LEfDO+wQd(5U+XZ8$hZb{9OHa4pLNn z%RtI`#ScsGDvG+Cjg=vmCnTr7y|~c&(Iq}clta(w>FLv}zrWH5uhirX)z2N#ax}(~ z_|#uhyj(Q9y~^YN{IW`o%w#U!Qx|ppaBymY;;mUi-`)>wrXKYrfJ<1#y=`OVGs2EE zB_;(caZKiptOKhVU5k-whrB|Jn%$=5lb*^=7MIw*`Y&65Frm3LrE`@4KHD32=FK>} z6gznfGNerr#O)`rxKlcao1Dx{5l;CdIa_aa?&h-7>ksg1*27>&MV~X0yuu%jgf@}9 zCRX&Q(J_xbYr18(-t)yD0D24rDL3%Cyr=<`ezo)^OF_3|F2%xq!vTD-v?!*zb5T8$ zTu9flrBB$zfv(F{9BG`GNHG%4lWHS+i+?;x?7;f}>F3kw{jSs*#~>u+|y5;t^o`yFp)JCN-Z3NH5mHrnZ_}>piL;Z%Q&%emR2|~ z7h8xYG&)qaO%iMcYe-NYu=4lYF*-;^8>r1Xq{^V=qcd1t_k8BrI7NeLbyPq zbaE)1`)OL0r>x0s$qJE+UmL)80$)#EjaAEE75B2EiC9$I6qA^A*G(lXIDC$+i%Ipl z_?;!Eb${>C)j0J@6Ga0}85XqJDIEf<-^3TlDyFlM>V8j=5mx9QJoSIK`oAi>UVR_r z%BT`E!LuX8k>jKwNir2*o+Y>e%xExq(sC}Gl2QUgdJOJ(&$VB?2I*VI~j?Uf>YWR&TU|@hOXjq#g#KJCN z9|7TZxeyt7-kQsghPN_Li#&%@u?T-BE?wuzeX2xcwEy`Lw04Z|) z`$_NLv&jS6qLuqpHLpy?m29jzSS6SaZxmS5RZNPU>zs{lb^ha7Z>;`a?EFQaf!98F zu6VoAZiK)@nWZeiOmOk@nbF;N0!VwaSFR&wozadd3I~+5=15s#3b&GA6R5c$Cxh1m zyss;bkY%)$q_9L)(End+1yd)izeed;9LYx(Fl>`Vl6#pvFo$Ep3dzPI0|aj^dDvi4 zr=0C`TaEH;`D|P9FDSJs;W#3m7<(MED5S^wj}RE_U8Q!__t%E8##K9~d6+!|e|~BA z1oV;0rJZYD==9MLBD*4tm(90I^YCy!3$}nlI{L!Po9ty>4n*;Mfg-T~2F!k}r90~T z111WxoM2m2l(01*gnDYcteiN923F`zFx}@Toc<MmyDao^cXOMaDt9257}~KxZaxlNo@d5 zTn6wffEleNU1)33?Q?iT{8HS1uJl#3@{oXK3uv|!lQO~=ASr_$)9ZFE%{ISa#TOCy zqRY@1d5aY_ie=X?>*WBV+ZlSk5-7G*qWs4L%%-3CJ_WFID%I0IMBz8Z)Yv&ANx9Vt zlUsK;`k=(&QB(aUkj7nj|559_`ZXcg5V96K!Sk0}a_o2qyvj@TU$wg$Lw`VA=pFGQ{KLh&by23=#PSbN>wzWtpKZ$iI-Dx0Loh>B>Npj*d z8*;qg587yN=TvsVypRvTQs^TrlVli7PjBU-APsu`QmvD7SNa%NHTc=qPy<8Dsr9tD zVOM&dy4vL0c7R=5$$7S@^nTqgnhfakXI)-0`=K(5;ps)VTpPQlxgvVz3Af#;@8XNO z;WR|f!;zfYbj-)u-yBY?g`NWRsE0s`WSKSqFZeITwB;-Bnfnjso&lR56GQrj<&DZ5 zJPB@Y9kIxQ$LHmXT0KRLt1bBbqv4~~4}JgBPcgNy2cCLmls>ok?F;A!y{&$;7k~Zh zFM{R1+W0|il>=&cdwDl+dYaJMtZmQq*VA49{`PKPI}_pi*YJT0xb&U=<}vJTgh1e* zRxCE+dlH7Px)3K916gEIBNGPWeH-?daH+BrXe!hqm5ZU@PZzwYgmkXUV7r-Ic!{wlOEtb@ASi54vZ!XPs&}|ZXwy|*IPsWfJ z*2!4jNzcGGJi%>1DAEj#zQQFozZFDh$Zy9&N@NvFQ}ake<Kv`xUr`zK5d1cQB*WRbcpG4aAr&9k}rOs1A)4!H}RsThMla_`_c3czj zFTm=zihww^8YQE%{A`mu<55_m#a{fv?CWV*Lm-WVpWSRn$J#h?SlLeq?-;wYEnUH+ zX24rKL-33OFqBp{YFh9x03~h_?elQpBN98IW-qmL3+JjTV#8=TDK7z!h&F;0_UkrH z;H@@eS4IWZruyoa-`~c);5tIaf12v#xWQuM3IGUKSt126VeW$^b9L*ZeUU0 z?F7e(-T*PDrN2Z@n&q^$u6326#2XaR^`df(kcmDuay^4RA zJRrXN%k9x_y#&2+IWa(+Jl$tmET0~)I!-3{I+F~IQ=vZxa^3+9aEvilOK8IcIkZI^ zQ^M7R!6G3sSPy`Rn!_D$MFm=6WCcm>*ss;qiXyfyH*{(vA<6m*aVy}i$veh^X1Kmu z>Sz$*NkHLHQus}biwQb0GeqA9hBY+0`^8z$^Qi$I7vbnRRBcPvogn0O7%Jm21m{X^ zX|`wX*Y|ZkK!5EEW*hHu5k&sh3LXNIz-Io^Pg z23Eo`Xwo7p-W)?ByD0Zt0koAR*+nskCz%Zd)p~hxe6z2Au-tyWzPuLcafE-decSy%d1iq1hj~t##d2Qnj|r!PzSI2@FYTa%j2z!9GxEk}SwdPpV7RZU-7k zunDYGW~bH346qN#NY~(q5o?x4U6!>CAuG0B?xjw?B2COrV)-!pOL>FffTJmyj{-;A zcdBu2juS!Jmi{5sfCDwDsS*PNp}r=-@Z>}-^5R_KOp!moS%4{(TK{78e|?Cur*DA= zakcJwMW=3;6|d2xEz;nG<`b$gUO#a0?RSq+=J*p}Nzm^l=$A*;tu*b3Ql5z z77ouK*cyAFXb+@wcv=vKf%Q1cC7K*FvXl{Z!@=kKWjpqJf#V$$yE`pP&|;mXokM)fZ6sFjPs zB*m>tp)oBmL|10^G^;jRATNe&j(^&9$us(RiA)4r$CKSBmOZi2$Kx0JAau8-Z2y1& z2}{giu6PNeVoOP*xr=)1QWiK(ao~g|q#`0SPBd_TcJ=p#^cP5S)4=N+EeFhZ;_45c zE>K@5+l^8jnc#wJzyI}HsKjb%@mL!;%C4RRAETBy=#dT7Zb{)@Vow1(DIHrn(JYx< zlV)Fq{r7o~LTlIw5~YQW%U)$$pSI1AAD@Yf`2cs>QUF|g!`ml@t@9viwjiQeXyphW zHe1|74SG?A=+$QwrfV}3X!Asxt=2kWM@`Lm*_6b}vI>cq2!c)cFTf9*l;ANv$b3$$ z&5;WF%|Y_nQA*MJj0*49M_gQ=hWR3hk5=cnjbXUkkQS+UfMZ-|eZjB(&y|?bp=gSN zhe$_zUk!y#6$S*A9|{mqTxr0xgj9S%b_;cS|6=v`&l^N7r|H7z1^MZnhR_ESJ8&7n z+pux&#s`s&deLnC@nj;?{`vg=PrE#nl`TW-DtJ?VGHyz=F~+!o9qYX1dx`@ zlTQP?xK~G%id{8r1GUK))@J?qOCD|%ZYl3`leQ2Q6T6=RbroJo%M@_u*g1x$jeN+| zW+-D;({pG2%GX`;JZ$Oug=M5+M`l3KU}fep2Ie}$)5Gcmdjqp2m$11n#bc@4pok8z zkRAJ0@t;U=>&3>i(G<1(g-w5cHiz-){9$9q^Jhn0rtiNw_JYTj{QrDogx)tN{780c zSooE)dB{<=4+fcG;H4lZOK|=1{eO)t^taoL2`~LjThbCQ?#HwT`u#?4m8QWMx0(*D zgx^nd0Ilt2C`3C8E9E(;I_6r)c7)O{T8?1KQQlW-ut)MUL7j}{>IYc=cfM)OB@aHt z4e;lL`OMxc%}T~2k)`_FmqzE=-p*3ZB&=vfNm)=8^%9!;SzYXEwN2@i9QiR`Ay0Xz zc}xPXhs;S}f^c&FX2gt|(}%CwHK`E@k06M753IAH2fIMQ0`xO1Eb;xkcfFo290;r3 z#?9!0#^O8e^>EVzk?uMNu6{7J95-!4_x8zImpL16Zz=6`na@}7t?p3y+{tQVXFtx? zrq$2o&mc2kg}D5G^sVqu&lx|c7e3FC#18B@tV4WB`j-;D=tDas!~ug|u#_^~OcV>z zvjv7&|0SF4t1|8b?bI)|>#Sp_UeD(g)phn(PbTri6?L`>4NrOA4u`%d*MlW`^;e=% zdnPA*2?f&#z2sM?9+4@o(H=FxZB8XjZq>;SS_m}z;|}gt+)yD50oqVrG6=xq0H#m? z|9$OBcRj{qL-`$gkjS{nVZ6lsXdS5ZGCB7n1!AEp(-UF%XxNFkM?CoC+HoXsYpzJz zTz`$#j7F!&^s3(+}titV|TV-qwyF&69Z753yX zVozkJEO?vIOsu;2>X;TWC69189D6j$Q@B5h08iN#OOzomd8;NA?MD$i`0HTEF|H7D~ag zvzOO56kiGvz@^um_5bniv9_7}=K~|8o!Zhq`1n|?X^E#i zj^(l}6Ni0TQz>7!jFc5oSnS#NIEL#0wl%-7d$K^Z=<{9>7em@ZmsPGZ{yB zMUR-iW*^r^NTgQl;*WtTD3xnpRtQf5jWDsL>;q=Pu&kCTu@u!M7ZR2-XyoDtzl@b{ z?+y{toJ%dwehD~(KgpzC>dsqjpY8V8>c6`+jv~QYnsa@n5r+c`Di;ziTK#A~Zx?{w zKTw6qVrEZ(@1iMge{l1*0=L=G--zt7p;TVN8O)_)w|FSy7=dUd@t0o79Jmp1@HWi{ zc$=(@+0BI1_D#^A5sO2O`&)+7<&5V1VO%PVqM1sID3ft&JDx51<&{;oVj%mAFkb)# zf9^lW#p|qEm*b}iBdDs2g;v!}w^HmtEVKPsh1XeQ@O``S*9d@XX@tYQ9O@Q7Hf;N8 z!qUt+G2?GXq%T~+N(fMJB%%W{r?h!);kZFL#Ln(Wiy3u|aq||IOAm}WyO;i5g8sKR zFMEW|eLc~I2KXF8h5MR3w@)7Y?86#g2#a2(UZuw4=r@ti4cQzDx9NY@w(*hFcOZNQ z&xA|-aJJ_)u`26?dvH!B89_EWB50$C<)|?pU zv6|?pg%)aimX!g>x@9)yRLh=6Bw&blCwY>PCwN*HfpKLX@5SkIUK9?;lh6t>%X%D7 z`mCo^4B%QG%1q%23ji0=xnv0c@HhbXHoGux0{c(wXzo~kJPYa8%4$Nor6;JCQCDb5ZLW&vWzV&A> zOwEJ-tl90qkS2ZqAZ43ahGy!$g<9jV`0D4q+_F>c()$Li5a<%{7#L6Y`~UVL=uJq2})E=duE4+4$XPc8z!c57Py%`X+CdLYx#5z$=OXzlJ zf!Bqp4xnvkd#Ml`Orx#00OkA}Ov@Al&#=f3^jfAY+^_?dKtOAttDL;G`SLmW@NtpE1yE7H5H z=EuTUiV<~s$^k5k600!iwa?MC*27^;kk8&RIcXiX<=Ly;T%-n^ zL>8hSItsI!^=sK_!D$oW!KMQ(fT1tY?945|AV=gD=9@uYpMbVeDU}_&)_X;1THpI| za}@by$D^F%GMte5cOPjF79vP-_8M@S795yiEvU|o-U6?}mW^0is(VoRyb76X^DIZt zMcT;4*ZrqPybSwUFn6Qz5(mH6JYcO*+~(Q#3~>R>@M7QWUV?W2i=X{JOyF+=UxP|K zKK_e|n`2QtO^|WWlcgxFeWCjZ2K|vjpd_kITX6kz0(RqIy-|!;;2dA(Vu+h~?1AQX zGn`v%zj%;HEKiIy{biw$fGoE*rq5%IMf`Bs(%H}jm@v^{-T+1W02+I=#MMf-Cqj!( z`*_~O6CkeRZ6Gd0(89goAIsd-0w$5hm1fEe8z8+LKKbc*AI+zEkGd&;a$edAP-kaa zsHoMWt<18&_|nHU7vDaDoo+Rc7e4Qi5AgdB{M?@=R`jKB))61c9glZF*dj(xbfJ4> z=G}tkK#Vg?xf#PGhMIkl>qwyDvvoX46eVEgDgCPt!=eb_kr+t|QH&IYoQU(5oa$tv zJEH_jHh{7!-^w8jdDxA#)-)GvS$r8aZUeSK0d#HBra>!8Uk=8-&bVJNYEaFD1+BSp z4pho;+>V&AL^T6b-PPj2Z$XKh7QoP#iFX?LbV>8C2G0tT>KEG9*!ijDnr1HU1yW| zy!Kn~8<}!)w*V~Bw?q23A8X(Ka*?Mz(VI9N)t$IPsf-%5rU}i7w9JhSYFSO*S*?v@;V}$o!VGKf549`)XAVt-sP@pM z;c4LaX*1(lj`1=ls!x+5-wEKJFqoh+AIk1DjIq#bRh=GFMoYi!JNzYN*$ih@n31B5 zre6viYU~AFtv6n9Ji099ns)`@tSZ{$bKB5&`#HXGs)Y{c$PF-H+gtxT*yvjK@Ct1g zU-PjiJVEq7U2}^cGCE}pu4w$)ue#~p*~-7)A>|kvxzKjP)i0!jZX?$7p|k$Up<4Y1 z(|_@?_7@^MM!~OYD`a6tcA!I??(~KOpR1n<@BL>^7uv~Wy@GO+UY3e+SmH%u0QDiF zw*9?jKyJ3hGLYOdiSL6Jaae(iKsGP58g?zI>_(13Zwhbu9`@#k5ET+rk|a%G{V!I( z7$(W$y)I)Xu%BKL4bM-nGBCp*gwgU5Azf!j70@3gO!GW7uViA~bD0yYo;9Xu@{sO8 zH7)1g5GQt4vN|9rfWkRMbQ3=74Aa(y>z!ucC0u>5};<=xevy|656nd8)8U`++-U#qqQu{bC4Uz!kJd zK|R+4#%&GdkWv?uP=2CRP3wO5G-$gMHtVED1uxAqApW`7-P%^MugBn&j^VghZ`=jYe(7$`3I@u`0)>A(J1xn%q6!Zhr(>*3`sva%`6S&;OW+m)e2Y<|89 zC|K=k(J$`puvP|d6(`P*UW)GlJFg=Bf{jCtbSNC64FLA}W#u$P(lr-P?2iB4(_lYC zQ2b0%X9}AE(*`Quso}G>?EAYT&}V@GC$M}tD93%`9tIX;&hwo@Pp9ctn*W{$0Xglq z?eHI`Hqo=%fZ8f3V9G(Q0S={>VQ%ni(K87Er@7Vlm+F=W_8}@s(*1vV=D)O&n(;eI z56-u_f*h;gZoF3Z+$%&+ghfH+`qC#tUCARZz24|+k+>fub*}y=X2zrb** z&of(F%cQf(B7o-5z z{@s^5kX9gVFi|Hua={Yqf0Pf_PVe;Ey!E9Iw!{<9eyjX@(f|Lo`oDeqW`pSd(!PVH zy~o$9affEq8r`~(nh`Qtw>s1LdF0p`%fYhsUe16O+gS?4dSCJz24Q|}g$OC$O%n~d z1>WIqnKnF@x(F+RNi~WfQIz7hjV}6+8$KIOlP5KDlIj1)L2-{P~q2O`5POrNe0j-px{jM|o3Zsw5N2 zd5q3)7~ZQiASf{l+!xE}(pH{ZeO> z3Cee!EreoW0yy+<@7%YJkS-bV4?dI(Q(@KAQqdkV+hEZ96W`eL={w=yc?^EP`u~#O c;Qs^|0DHVr*{xQ8x&QzG07*qoM6N<$f}^bJQ2+n{ literal 0 HcmV?d00001 diff --git a/examples/example 16 - Displacement/panda.png b/examples/example 16 - Displacement/panda.png new file mode 100644 index 0000000000000000000000000000000000000000..215a4a9331fbe6bb3efe9501b672df8e5d8be76e GIT binary patch literal 69177 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 x1 && x <= x1 + this.width) + { + var y1 = this.y; + + if(y >= y1 && y <= y1 + this.height) + { + return true; + } + } + + return false; +} + +// constructor +PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; + + +/** + * @author Adrien Brault + */ + +/** + * @class Polygon + * @constructor + * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, + * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be + * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the + * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are + * Numbers. + */ +PIXI.Polygon = function(points) +{ + //if points isn't an array, use arguments as the array + if(!(points instanceof Array)) + points = Array.prototype.slice.call(arguments); + + //if this is a flat array of numbers, convert it to points + if(typeof points[0] === 'number') { + var p = []; + for(var i = 0, il = points.length; i < il; i+=2) { + p.push( + new PIXI.Point(points[i], points[i + 1]) + ); + } + + points = p; + } + + this.points = points; +} + +/** + * Creates a clone of this polygon + * + * @method clone + * @return {Polygon} a copy of the polygon + */ +PIXI.Polygon.prototype.clone = function() +{ + var points = []; + for (var i=0; i y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + + if(intersect) inside = !inside; + } + + return inside; +} + +// constructor +PIXI.Polygon.prototype.constructor = PIXI.Polygon; + +/** + * @author Chad Engler + */ + +/** + * The Circle object can be used to specify a hit area for displayobjects + * + * @class Circle + * @constructor + * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle + * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle + * @param radius {Number} The radius of the circle + */ +PIXI.Circle = function(x, y, radius) +{ + /** + * @property x + * @type Number + * @default 0 + */ + this.x = x || 0; + + /** + * @property y + * @type Number + * @default 0 + */ + this.y = y || 0; + + /** + * @property radius + * @type Number + * @default 0 + */ + this.radius = radius || 0; +} + +/** + * Creates a clone of this Circle instance + * + * @method clone + * @return {Circle} a copy of the polygon + */ +PIXI.Circle.prototype.clone = function() +{ + return new PIXI.Circle(this.x, this.y, this.radius); +} + +/** + * Checks if the x, and y coords passed to this function are contained within this circle + * + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return {Boolean} if the x/y coords are within this polygon + */ +PIXI.Circle.prototype.contains = function(x, y) +{ + if(this.radius <= 0) + return false; + + var dx = (this.x - x), + dy = (this.y - y), + r2 = this.radius * this.radius; + + dx *= dx; + dy *= dy; + + return (dx + dy <= r2); +} + +// constructor +PIXI.Circle.prototype.constructor = PIXI.Circle; + + +/** + * @author Chad Engler + */ + +/** + * The Ellipse object can be used to specify a hit area for displayobjects + * + * @class Ellipse + * @constructor + * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse + * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse + * @param width {Number} The overall width of this ellipse + * @param height {Number} The overall height of this ellipse + */ +PIXI.Ellipse = function(x, y, width, height) +{ + /** + * @property x + * @type Number + * @default 0 + */ + this.x = x || 0; + + /** + * @property y + * @type Number + * @default 0 + */ + this.y = y || 0; + + /** + * @property width + * @type Number + * @default 0 + */ + this.width = width || 0; + + /** + * @property height + * @type Number + * @default 0 + */ + this.height = height || 0; +} + +/** + * Creates a clone of this Ellipse instance + * + * @method clone + * @return {Ellipse} a copy of the ellipse + */ +PIXI.Ellipse.prototype.clone = function() +{ + return new PIXI.Ellipse(this.x, this.y, this.width, this.height); +} + +/** + * Checks if the x, and y coords passed to this function are contained within this ellipse + * + * @method contains + * @param x {Number} The X coord of the point to test + * @param y {Number} The Y coord of the point to test + * @return {Boolean} if the x/y coords are within this ellipse + */ +PIXI.Ellipse.prototype.contains = function(x, y) +{ + if(this.width <= 0 || this.height <= 0) + return false; + + //normalize the coords to an ellipse with center 0,0 + //and a radius of 0.5 + var normx = ((x - this.x) / this.width) - 0.5, + normy = ((y - this.y) / this.height) - 0.5; + + normx *= normx; + normy *= normy; + + return (normx + normy < 0.25); +} + +PIXI.Ellipse.getBounds = function() +{ + return new PIXI.Rectangle(this.x, this.y, this.width, this.height); +} + +// constructor +PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; + + + +/* + * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV + * you both rock! + */ + +function determineMatrixArrayType() { + PIXI.Matrix = (typeof Float32Array !== 'undefined') ? Float32Array : Array; + return PIXI.Matrix; +} + +determineMatrixArrayType(); + +PIXI.mat3 = {}; + +PIXI.mat3.create = function() +{ + var matrix = new PIXI.Matrix(9); + + matrix[0] = 1; + matrix[1] = 0; + matrix[2] = 0; + matrix[3] = 0; + matrix[4] = 1; + matrix[5] = 0; + matrix[6] = 0; + matrix[7] = 0; + matrix[8] = 1; + + return matrix; +} + + +PIXI.mat3.identity = function(matrix) +{ + matrix[0] = 1; + matrix[1] = 0; + matrix[2] = 0; + matrix[3] = 0; + matrix[4] = 1; + matrix[5] = 0; + matrix[6] = 0; + matrix[7] = 0; + matrix[8] = 1; + + return matrix; +} + + +PIXI.mat4 = {}; + +PIXI.mat4.create = function() +{ + var matrix = new PIXI.Matrix(16); + + matrix[0] = 1; + matrix[1] = 0; + matrix[2] = 0; + matrix[3] = 0; + matrix[4] = 0; + matrix[5] = 1; + matrix[6] = 0; + matrix[7] = 0; + matrix[8] = 0; + matrix[9] = 0; + matrix[10] = 1; + matrix[11] = 0; + matrix[12] = 0; + matrix[13] = 0; + matrix[14] = 0; + matrix[15] = 1; + + return matrix; +} + +PIXI.mat3.multiply = function (mat, mat2, dest) +{ + if (!dest) { dest = mat; } + + // Cache the matrix values (makes for huge speed increases!) + var a00 = mat[0], a01 = mat[1], a02 = mat[2], + a10 = mat[3], a11 = mat[4], a12 = mat[5], + a20 = mat[6], a21 = mat[7], a22 = mat[8], + + b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], + b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], + b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; + + dest[0] = b00 * a00 + b01 * a10 + b02 * a20; + dest[1] = b00 * a01 + b01 * a11 + b02 * a21; + dest[2] = b00 * a02 + b01 * a12 + b02 * a22; + + dest[3] = b10 * a00 + b11 * a10 + b12 * a20; + dest[4] = b10 * a01 + b11 * a11 + b12 * a21; + dest[5] = b10 * a02 + b11 * a12 + b12 * a22; + + dest[6] = b20 * a00 + b21 * a10 + b22 * a20; + dest[7] = b20 * a01 + b21 * a11 + b22 * a21; + dest[8] = b20 * a02 + b21 * a12 + b22 * a22; + + return dest; +} + +PIXI.mat3.clone = function(mat) +{ + var matrix = new PIXI.Matrix(9); + + matrix[0] = mat[0]; + matrix[1] = mat[1]; + matrix[2] = mat[2]; + matrix[3] = mat[3]; + matrix[4] = mat[4]; + matrix[5] = mat[5]; + matrix[6] = mat[6]; + matrix[7] = mat[7]; + matrix[8] = mat[8]; + + return matrix; +} + +PIXI.mat3.transpose = function (mat, dest) +{ + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (!dest || mat === dest) { + var a01 = mat[1], a02 = mat[2], + a12 = mat[5]; + + mat[1] = mat[3]; + mat[2] = mat[6]; + mat[3] = a01; + mat[5] = mat[7]; + mat[6] = a02; + mat[7] = a12; + return mat; + } + + dest[0] = mat[0]; + dest[1] = mat[3]; + dest[2] = mat[6]; + dest[3] = mat[1]; + dest[4] = mat[4]; + dest[5] = mat[7]; + dest[6] = mat[2]; + dest[7] = mat[5]; + dest[8] = mat[8]; + return dest; +} + +PIXI.mat3.toMat4 = function (mat, dest) +{ + if (!dest) { dest = PIXI.mat4.create(); } + + dest[15] = 1; + dest[14] = 0; + dest[13] = 0; + dest[12] = 0; + + dest[11] = 0; + dest[10] = mat[8]; + dest[9] = mat[7]; + dest[8] = mat[6]; + + dest[7] = 0; + dest[6] = mat[5]; + dest[5] = mat[4]; + dest[4] = mat[3]; + + dest[3] = 0; + dest[2] = mat[2]; + dest[1] = mat[1]; + dest[0] = mat[0]; + + return dest; +} + + +///// + + +PIXI.mat4.create = function() +{ + var matrix = new PIXI.Matrix(16); + + matrix[0] = 1; + matrix[1] = 0; + matrix[2] = 0; + matrix[3] = 0; + matrix[4] = 0; + matrix[5] = 1; + matrix[6] = 0; + matrix[7] = 0; + matrix[8] = 0; + matrix[9] = 0; + matrix[10] = 1; + matrix[11] = 0; + matrix[12] = 0; + matrix[13] = 0; + matrix[14] = 0; + matrix[15] = 1; + + return matrix; +} + +PIXI.mat4.transpose = function (mat, dest) +{ + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (!dest || mat === dest) + { + var a01 = mat[1], a02 = mat[2], a03 = mat[3], + a12 = mat[6], a13 = mat[7], + a23 = mat[11]; + + mat[1] = mat[4]; + mat[2] = mat[8]; + mat[3] = mat[12]; + mat[4] = a01; + mat[6] = mat[9]; + mat[7] = mat[13]; + mat[8] = a02; + mat[9] = a12; + mat[11] = mat[14]; + mat[12] = a03; + mat[13] = a13; + mat[14] = a23; + return mat; + } + + dest[0] = mat[0]; + dest[1] = mat[4]; + dest[2] = mat[8]; + dest[3] = mat[12]; + dest[4] = mat[1]; + dest[5] = mat[5]; + dest[6] = mat[9]; + dest[7] = mat[13]; + dest[8] = mat[2]; + dest[9] = mat[6]; + dest[10] = mat[10]; + dest[11] = mat[14]; + dest[12] = mat[3]; + dest[13] = mat[7]; + dest[14] = mat[11]; + dest[15] = mat[15]; + return dest; +} + +PIXI.mat4.multiply = function (mat, mat2, dest) +{ + if (!dest) { dest = mat; } + + // Cache the matrix values (makes for huge speed increases!) + var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; + var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; + var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; + var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; + + // Cache only the current line of the second matrix + var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; + dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + dest[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = mat2[4]; + b1 = mat2[5]; + b2 = mat2[6]; + b3 = mat2[7]; + dest[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + dest[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + dest[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + dest[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = mat2[8]; + b1 = mat2[9]; + b2 = mat2[10]; + b3 = mat2[11]; + dest[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + dest[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + dest[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + dest[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + b0 = mat2[12]; + b1 = mat2[13]; + b2 = mat2[14]; + b3 = mat2[15]; + dest[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + dest[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + dest[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + dest[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + + return dest; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * The base class for all objects that are rendered on the screen. + * + * @class DisplayObject + * @constructor + */ +PIXI.DisplayObject = function() +{ + this.last = this; + this.first = this; + /** + * The coordinate of the object relative to the local coordinates of the parent. + * + * @property position + * @type Point + */ + this.position = new PIXI.Point(); + + /** + * The scale factor of the object. + * + * @property scale + * @type Point + */ + this.scale = new PIXI.Point(1,1);//{x:1, y:1}; + + /** + * The pivot point of the displayObject that it rotates around + * + * @property pivot + * @type Point + */ + this.pivot = new PIXI.Point(0,0); + + /** + * The rotation of the object in radians. + * + * @property rotation + * @type Number + */ + this.rotation = 0; + + /** + * The opacity of the object. + * + * @property alpha + * @type Number + */ + this.alpha = 1; + + /** + * The visibility of the object. + * + * @property visible + * @type Boolean + */ + this.visible = true; + + /** + * This is the defined area that will pick up mouse / touch events. It is null by default. + * Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children) + * + * @property hitArea + * @type Rectangle|Circle|Ellipse|Polygon + */ + this.hitArea = null; + + /** + * This is used to indicate if the displayObject should display a mouse hand cursor on rollover + * + * @property buttonMode + * @type Boolean + */ + this.buttonMode = false; + + /** + * Can this object be rendered + * + * @property renderable + * @type Boolean + */ + this.renderable = false; + + /** + * [read-only] The display object container that contains this display object. + * + * @property parent + * @type DisplayObjectContainer + * @readOnly + */ + this.parent = null; + + /** + * [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage. + * + * @property stage + * @type Stage + * @readOnly + */ + this.stage = null; + + /** + * [read-only] The multiplied alpha of the displayobject + * + * @property worldAlpha + * @type Number + * @readOnly + */ + this.worldAlpha = 1; + + /** + * [read-only] Whether or not the object is interactive, do not toggle directly! use the `interactive` property + * + * @property _interactive + * @type Boolean + * @readOnly + * @private + */ + this._interactive = false; + + /** + * [read-only] Current transform of the object based on world (parent) factors + * + * @property worldTransform + * @type Mat3 + * @readOnly + * @private + */ + this.worldTransform = PIXI.mat3.create()//mat3.identity(); + + /** + * [read-only] Current transform of the object locally + * + * @property localTransform + * @type Mat3 + * @readOnly + * @private + */ + this.localTransform = PIXI.mat3.create()//mat3.identity(); + + /** + * [NYI] Unkown + * + * @property color + * @type Array<> + * @private + */ + this.color = []; + + /** + * [NYI] Holds whether or not this object is dynamic, for rendering optimization + * + * @property dynamic + * @type Boolean + * @private + */ + this.dynamic = true; + + // chach that puppy! + this._sr = 0; + this._cr = 1; + + /* + * MOUSE Callbacks + */ + + /** + * A callback that is used when the users clicks on the displayObject with their mouse + * @method click + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user clicks the mouse down over the sprite + * @method mousedown + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases the mouse that was over the displayObject + * for this callback to be fired the mouse must have been pressed down over the displayObject + * @method mouseup + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject + * for this callback to be fired, The touch must have started over the displayObject + * @method mouseupoutside + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the users mouse rolls over the displayObject + * @method mouseover + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the users mouse leaves the displayObject + * @method mouseout + * @param interactionData {InteractionData} + */ + + + /* + * TOUCH Callbacks + */ + + /** + * A callback that is used when the users taps on the sprite with their finger + * basically a touch version of click + * @method tap + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user touch's over the displayObject + * @method touchstart + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases a touch over the displayObject + * @method touchend + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases the touch that was over the displayObject + * for this callback to be fired, The touch must have started over the sprite + * @method touchendoutside + * @param interactionData {InteractionData} + */ +} + +// constructor +PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; + +/** + * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default + * Instead of using this function you can now simply set the interactive property to true or false + * + * @method setInteractive + * @param interactive {Boolean} + * @deprecated Simply set the `interactive` property directly + */ +PIXI.DisplayObject.prototype.setInteractive = function(interactive) +{ + this.interactive = interactive; +} + +/** + * Indicates if the sprite will have touch and mouse interactivity. It is false by default + * + * @property interactive + * @type Boolean + * @default false + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'interactive', { + get: function() { + return this._interactive; + }, + set: function(value) { + this._interactive = value; + + // TODO more to be done here.. + // need to sort out a re-crawl! + if(this.stage)this.stage.dirty = true; + } +}); + +/** + * Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. + * In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. + * To remove a mask, set this property to null. + * + * @property mask + * @type Graphics + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { + get: function() { + return this._mask; + }, + set: function(value) { + + + if(value) + { + if(this._mask) + { + value.start = this._mask.start; + value.end = this._mask.end; + } + else + { + this.addFilter(value); + value.renderable = false; + } + } + else + { + this.removeFilter(this._mask); + this._mask.renderable = true; + } + + this._mask = value; + } +}); + +/** + * Sets the filters for the displayObject. Currently there's a few limitations. + * 1: At the moment only one filter can be applied at a time.. + * 2: They cannot be nested. + * 3: There's no padding yet. + * 4: this is a webGL only feature. + * @property filters + * @type Array + */ +Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { + get: function() { + return this._filters; + }, + set: function(value) { + + //if(value == ) + if(value) + { + if(this._filters)this.removeFilter(this._filters); + this.addFilter(value) + } + else + { + if(this._filters)this.removeFilter(this._filters); + } + + this._filters = value; + } +}); + +/* + * Adds a filter to this displayObject + * + * @method addFilter + * @param mask {Graphics} the graphics object to use as a filter + * @private + */ +PIXI.DisplayObject.prototype.addFilter = function(data) +{ + //if(this.filter)return; + //this.filter = true; + + // insert a filter block.. + // TODO Onject pool thease bad boys.. + var start = new PIXI.FilterBlock(); + var end = new PIXI.FilterBlock(); + + data.start = start; + data.end = end; + + start.data = data; + end.data = data; + + start.first = start.last = this; + end.first = end.last = this; + + start.open = true; + + /* + * insert start + */ + + var childFirst = start + var childLast = start + var nextObject; + var previousObject; + + previousObject = this.first._iPrev; + + if(previousObject) + { + nextObject = previousObject._iNext; + childFirst._iPrev = previousObject; + previousObject._iNext = childFirst; + } + else + { + nextObject = this; + } + + if(nextObject) + { + nextObject._iPrev = childLast; + childLast._iNext = nextObject; + } + + + // now insert the end filter block.. + + /* + * insert end filter + */ + var childFirst = end + var childLast = end + var nextObject = null; + var previousObject = null; + + previousObject = this.last; + nextObject = previousObject._iNext; + + if(nextObject) + { + nextObject._iPrev = childLast; + childLast._iNext = nextObject; + } + + childFirst._iPrev = previousObject; + previousObject._iNext = childFirst; + + var updateLast = this; + + var prevLast = this.last; + while(updateLast) + { + if(updateLast.last == prevLast) + { + updateLast.last = end; + } + updateLast = updateLast.parent; + } + + this.first = start; + + // if webGL... + if(this.__renderGroup) + { + this.__renderGroup.addFilterBlocks(start, end); + } + +} + +/* + * Removes the filter to this displayObject + * + * @method removeFilter + * @private + */ +PIXI.DisplayObject.prototype.removeFilter = function(data) +{ + //if(!this.filter)return; + //this.filter = false; + console.log("YUOIO") + // modify the list.. + var startBlock = data.start; + + + var nextObject = startBlock._iNext; + var previousObject = startBlock._iPrev; + + if(nextObject)nextObject._iPrev = previousObject; + if(previousObject)previousObject._iNext = nextObject; + + this.first = startBlock._iNext; + + // remove the end filter + var lastBlock = data.end; + + var nextObject = lastBlock._iNext; + var previousObject = lastBlock._iPrev; + + if(nextObject)nextObject._iPrev = previousObject; + previousObject._iNext = nextObject; + + // this is always true too! + var tempLast = lastBlock._iPrev; + // need to make sure the parents last is updated too + var updateLast = this; + while(updateLast.last == lastBlock) + { + updateLast.last = tempLast; + updateLast = updateLast.parent; + if(!updateLast)break; + } + + // if webGL... + if(this.__renderGroup) + { + this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); + } +} + +/* + * Updates the object transform for rendering + * + * @method updateTransform + * @private + */ +PIXI.DisplayObject.prototype.updateTransform = function() +{ + // TODO OPTIMIZE THIS!! with dirty + if(this.rotation !== this.rotationCache) + { + this.rotationCache = this.rotation; + this._sr = Math.sin(this.rotation); + this._cr = Math.cos(this.rotation); + } + + var localTransform = this.localTransform; + var parentTransform = this.parent.worldTransform; + var worldTransform = this.worldTransform; + //console.log(localTransform) + localTransform[0] = this._cr * this.scale.x; + localTransform[1] = -this._sr * this.scale.y + localTransform[3] = this._sr * this.scale.x; + localTransform[4] = this._cr * this.scale.y; + + // TODO --> do we even need a local matrix??? + + var px = this.pivot.x; + var py = this.pivot.y; + + // Cache the matrix values (makes for huge speed increases!) + var a00 = localTransform[0], a01 = localTransform[1], a02 = this.position.x - localTransform[0] * px - py * localTransform[1], + a10 = localTransform[3], a11 = localTransform[4], a12 = this.position.y - localTransform[4] * py - px * localTransform[3], + + b00 = parentTransform[0], b01 = parentTransform[1], b02 = parentTransform[2], + b10 = parentTransform[3], b11 = parentTransform[4], b12 = parentTransform[5]; + + localTransform[2] = a02 + localTransform[5] = a12 + + worldTransform[0] = b00 * a00 + b01 * a10; + worldTransform[1] = b00 * a01 + b01 * a11; + worldTransform[2] = b00 * a02 + b01 * a12 + b02; + + worldTransform[3] = b10 * a00 + b11 * a10; + worldTransform[4] = b10 * a01 + b11 * a11; + worldTransform[5] = b10 * a02 + b11 * a12 + b12; + + // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! + // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); + this.worldAlpha = this.alpha * this.parent.worldAlpha; + + this.vcount = PIXI.visibleCount; + +} + +PIXI.visibleCount = 0; +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * A DisplayObjectContainer represents a collection of display objects. + * It is the base class of all display objects that act as a container for other objects. + * + * @class DisplayObjectContainer + * @extends DisplayObject + * @constructor + */ +PIXI.DisplayObjectContainer = function() +{ + PIXI.DisplayObject.call( this ); + + /** + * [read-only] The of children of this container. + * + * @property children + * @type Array + * @readOnly + */ + this.children = []; +} + +// constructor +PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); +PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; + +/** + * Adds a child to the container. + * + * @method addChild + * @param child {DisplayObject} The DisplayObject to add to the container + */ +PIXI.DisplayObjectContainer.prototype.addChild = function(child) +{ + if(child.parent != undefined) + { + + //// COULD BE THIS??? + child.parent.removeChild(child); + // return; + } + + child.parent = this; + + this.children.push(child); + + // update the stage refference.. + + if(this.stage) + { + var tmpChild = child; + do + { + if(tmpChild.interactive)this.stage.dirty = true; + tmpChild.stage = this.stage; + tmpChild = tmpChild._iNext; + } + while(tmpChild) + } + + // LINKED LIST // + + // modify the list.. + var childFirst = child.first + var childLast = child.last; + var nextObject; + var previousObject; + + // this could be wrong if there is a filter?? + if(this._filters || this._mask) + { + previousObject = this.last._iPrev; + } + else + { + previousObject = this.last; + } + + nextObject = previousObject._iNext; + + // always true in this case + // need to make sure the parents last is updated too + var updateLast = this; + var prevLast = previousObject; + + while(updateLast) + { + if(updateLast.last == prevLast) + { + updateLast.last = child.last; + } + updateLast = updateLast.parent; + } + + if(nextObject) + { + nextObject._iPrev = childLast; + childLast._iNext = nextObject; + } + + childFirst._iPrev = previousObject; + previousObject._iNext = childFirst; + + // need to remove any render groups.. + if(this.__renderGroup) + { + // being used by a renderTexture.. if it exists then it must be from a render texture; + if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); + // add them to the new render group.. + this.__renderGroup.addDisplayObjectAndChildren(child); + } + +} + +/** + * Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown + * + * @method addChildAt + * @param child {DisplayObject} The child to add + * @param index {Number} The index to place the child in + */ +PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) +{ + if(index >= 0 && index <= this.children.length) + { + if(child.parent != undefined) + { + child.parent.removeChild(child); + } + child.parent = this; + + if(this.stage) + { + var tmpChild = child; + do + { + if(tmpChild.interactive)this.stage.dirty = true; + tmpChild.stage = this.stage; + tmpChild = tmpChild._iNext; + } + while(tmpChild) + } + + // modify the list.. + var childFirst = child.first; + var childLast = child.last; + var nextObject; + var previousObject; + + if(index == this.children.length) + { + previousObject = this.last; + var updateLast = this; + var prevLast = this.last; + while(updateLast) + { + if(updateLast.last == prevLast) + { + updateLast.last = child.last; + } + updateLast = updateLast.parent; + } + } + else if(index == 0) + { + previousObject = this; + } + else + { + previousObject = this.children[index-1].last; + } + + nextObject = previousObject._iNext; + + // always true in this case + if(nextObject) + { + nextObject._iPrev = childLast; + childLast._iNext = nextObject; + } + + childFirst._iPrev = previousObject; + previousObject._iNext = childFirst; + + this.children.splice(index, 0, child); + // need to remove any render groups.. + if(this.__renderGroup) + { + // being used by a renderTexture.. if it exists then it must be from a render texture; + if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); + // add them to the new render group.. + this.__renderGroup.addDisplayObjectAndChildren(child); + } + + } + else + { + throw new Error(child + " The index "+ index +" supplied is out of bounds " + this.children.length); + } +} + +/** + * [NYI] Swaps the depth of 2 displayObjects + * + * @method swapChildren + * @param child {DisplayObject} + * @param child2 {DisplayObject} + * @private + */ +PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2) +{ + /* + * this funtion needs to be recoded.. + * can be done a lot faster.. + */ + return; + + // need to fix this function :/ + /* + // TODO I already know this?? + var index = this.children.indexOf( child ); + var index2 = this.children.indexOf( child2 ); + + if ( index !== -1 && index2 !== -1 ) + { + // cool + + /* + if(this.stage) + { + // this is to satisfy the webGL batching.. + // TODO sure there is a nicer way to achieve this! + this.stage.__removeChild(child); + this.stage.__removeChild(child2); + + this.stage.__addChild(child); + this.stage.__addChild(child2); + } + + // swap the positions.. + this.children[index] = child2; + this.children[index2] = child; + + } + else + { + throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); + }*/ +} + +/** + * Returns the Child at the specified index + * + * @method getChildAt + * @param index {Number} The index to get the child from + */ +PIXI.DisplayObjectContainer.prototype.getChildAt = function(index) +{ + if(index >= 0 && index < this.children.length) + { + return this.children[index]; + } + else + { + throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); + } +} + +/** + * Removes a child from the container. + * + * @method removeChild + * @param child {DisplayObject} The DisplayObject to remove + */ +PIXI.DisplayObjectContainer.prototype.removeChild = function(child) +{ + var index = this.children.indexOf( child ); + if ( index !== -1 ) + { + // unlink // + // modify the list.. + var childFirst = child.first; + var childLast = child.last; + + var nextObject = childLast._iNext; + var previousObject = childFirst._iPrev; + + if(nextObject)nextObject._iPrev = previousObject; + previousObject._iNext = nextObject; + + if(this.last == childLast) + { + var tempLast = childFirst._iPrev; + // need to make sure the parents last is updated too + var updateLast = this; + while(updateLast.last == childLast.last) + { + updateLast.last = tempLast; + updateLast = updateLast.parent; + if(!updateLast)break; + } + } + + childLast._iNext = null; + childFirst._iPrev = null; + + // update the stage reference.. + if(this.stage) + { + var tmpChild = child; + do + { + if(tmpChild.interactive)this.stage.dirty = true; + tmpChild.stage = null; + tmpChild = tmpChild._iNext; + } + while(tmpChild) + } + + // webGL trim + if(child.__renderGroup) + { + child.__renderGroup.removeDisplayObjectAndChildren(child); + } + + child.parent = undefined; + this.children.splice( index, 1 ); + } + else + { + throw new Error(child + " The supplied DisplayObject must be a child of the caller " + this); + } +} + +/* + * Updates the container's children's transform for rendering + * + * @method updateTransform + * @private + */ +PIXI.DisplayObjectContainer.prototype.updateTransform = function() +{ + if(!this.visible)return; + + PIXI.DisplayObject.prototype.updateTransform.call( this ); + + for(var i=0,j=this.children.length; i} an array of {Texture} objects that make up the animation + */ +PIXI.MovieClip = function(textures) +{ + PIXI.Sprite.call(this, textures[0]); + + /** + * The array of textures that make up the animation + * + * @property textures + * @type Array + */ + this.textures = textures; + + /** + * The speed that the MovieClip will play at. Higher is faster, lower is slower + * + * @property animationSpeed + * @type Number + * @default 1 + */ + this.animationSpeed = 1; + + /** + * Whether or not the movie clip repeats after playing. + * + * @property loop + * @type Boolean + * @default true + */ + this.loop = true; + + /** + * Function to call when a MovieClip finishes playing + * + * @property onComplete + * @type Function + */ + this.onComplete = null; + + /** + * [read-only] The index MovieClips current frame (this may not have to be a whole number) + * + * @property currentFrame + * @type Number + * @default 0 + * @readOnly + */ + this.currentFrame = 0; + + /** + * [read-only] Indicates if the MovieClip is currently playing + * + * @property playing + * @type Boolean + * @readOnly + */ + this.playing = false; +} + +// constructor +PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); +PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; + +/** +* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures +* assigned to the MovieClip. +* +* @property totalFrames +* @type Number +* @default 0 +* @readOnly +*/ +Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { + get: function() { + + return this.textures.length; + } +}); + + +/** + * Stops the MovieClip + * + * @method stop + */ +PIXI.MovieClip.prototype.stop = function() +{ + this.playing = false; +} + +/** + * Plays the MovieClip + * + * @method play + */ +PIXI.MovieClip.prototype.play = function() +{ + this.playing = true; +} + +/** + * Stops the MovieClip and goes to a specific frame + * + * @method gotoAndStop + * @param frameNumber {Number} frame index to stop at + */ +PIXI.MovieClip.prototype.gotoAndStop = function(frameNumber) +{ + this.playing = false; + this.currentFrame = frameNumber; + var round = (this.currentFrame + 0.5) | 0; + this.setTexture(this.textures[round % this.textures.length]); +} + +/** + * Goes to a specific frame and begins playing the MovieClip + * + * @method gotoAndPlay + * @param frameNumber {Number} frame index to start at + */ +PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) +{ + this.currentFrame = frameNumber; + this.playing = true; +} + +/* + * Updates the object transform for rendering + * + * @method updateTransform + * @private + */ +PIXI.MovieClip.prototype.updateTransform = function() +{ + PIXI.Sprite.prototype.updateTransform.call(this); + + if(!this.playing)return; + + this.currentFrame += this.animationSpeed; + + var round = (this.currentFrame + 0.5) | 0; + + if(this.loop || round < this.textures.length) + { + this.setTexture(this.textures[round % this.textures.length]); + } + else if(round >= this.textures.length) + { + this.gotoAndStop(this.textures.length - 1); + if(this.onComplete) + { + this.onComplete(); + } + } +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + + +PIXI.FilterBlock = function() +{ + this.visible = true; + this.renderable = true; +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.ColorMatrixFilter = function() +{ + // set the uniforms + this.uniforms = { + matrix: {type: 'mat4', value: [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1]}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float invert;", + "uniform mat4 matrix;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", + "gl_FragColor = gl_FragColor * vColor;", + "}" + ]; + +} + + +Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { + get: function() { + return this.uniforms.matrix.value; + }, + set: function(value) { + this.uniforms.matrix.value = value; + } +}); +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + + +PIXI.GreyFilter = function() +{ + // set the uniforms + this.uniforms = { + grey: {type: 'f', value: 1}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "uniform float grey;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord);", + "gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), grey);", + "gl_FragColor = gl_FragColor * vColor;", + "}" + ]; + + this.primitiveFragmentSrc = [ + "precision mediump float;", + "varying vec4 vColor;", + "uniform float grey;", + "void main(void) {", + "gl_FragColor = vColor;", + "gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), grey);", + "gl_FragColor = gl_FragColor * vColor;", + "}" + ]; + +} + +Object.defineProperty(PIXI.GreyFilter.prototype, 'grey', { + get: function() { + return this.uniforms.grey.value; + }, + set: function(value) { + this.uniforms.grey.value = value; + } +}); + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + + +PIXI.DisplacementFilter = function(texture) +{ + // set the uniforms + + this.uniforms = { + displacementMap: {type: 'sampler2D', value:texture}, + scale: {type: 'f2', value:{x:30, y:30}}, + mapDimensions: {type: 'f2', value:{x:texture.width, y:texture.height}} + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D displacementMap;", + "uniform sampler2D uSampler;", + "uniform vec2 scale;", + "uniform vec2 mapDimensions;",// = vec2(256.0, 256.0);", + "const vec2 textureDimensions = vec2(245.0, 263.0);", + + "void main(void) {", + + "vec2 matSample = texture2D(displacementMap, vTextureCoord * (textureDimensions/mapDimensions)).xy;", + "matSample -= 0.5;", + "matSample *= scale;", + "matSample /= textureDimensions;", + "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x + matSample.x, vTextureCoord.y + matSample.y));", + "gl_FragColor.rgb = mix( gl_FragColor.rgb, gl_FragColor.rgb, 1.0);", + "gl_FragColor = gl_FragColor * vColor;", + + "}" + ]; + +} + +Object.defineProperty(PIXI.DisplacementFilter.prototype, 'map', { + get: function() { + return this.uniforms.displacementMap.value; + }, + set: function(value) { + this.uniforms.displacementMap.value = value; + } +}); + +Object.defineProperty(PIXI.DisplacementFilter.prototype, 'scale', { + get: function() { + return this.uniforms.scale.value; + }, + set: function(value) { + this.uniforms.scale.value = value; + } +}); +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * A Text Object will create a line(s) of text to split a line you can use "\n" + * + * @class Text + * @extends Sprite + * @constructor + * @param text {String} The copy that you would like the text to display + * @param [style] {Object} The style parameters + * @param [style.font] {String} default "bold 20pt Arial" The style and size of the font + * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") + * @param [style.stroke] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" + * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) + * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used + * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap + */ +PIXI.Text = function(text, style) +{ + this.canvas = document.createElement("canvas"); + this.context = this.canvas.getContext("2d"); + PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas)); + + this.setText(text); + this.setStyle(style); + + this.updateText(); + this.dirty = false; +}; + +// constructor +PIXI.Text.prototype = Object.create(PIXI.Sprite.prototype); +PIXI.Text.prototype.constructor = PIXI.Text; + +/** + * Set the style of the text + * + * @method setStyle + * @param [style] {Object} The style parameters + * @param [style.font="bold 20pt Arial"] {String} The style and size of the font + * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") + * @param [style.stroke="black"] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" + * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) + * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used + * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap + */ +PIXI.Text.prototype.setStyle = function(style) +{ + style = style || {}; + style.font = style.font || "bold 20pt Arial"; + style.fill = style.fill || "black"; + style.align = style.align || "left"; + style.stroke = style.stroke || "black"; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136 + style.strokeThickness = style.strokeThickness || 0; + style.wordWrap = style.wordWrap || false; + style.wordWrapWidth = style.wordWrapWidth || 100; + this.style = style; + this.dirty = true; +}; + +/** + * Set the copy for the text object. To split a line you can use "\n" + * + * @methos setText + * @param {String} text The copy that you would like the text to display + */ +PIXI.Text.prototype.setText = function(text) +{ + this.text = text.toString() || " "; + this.dirty = true; +}; + +/** + * Renders text + * + * @method updateText + * @private + */ +PIXI.Text.prototype.updateText = function() +{ + this.context.font = this.style.font; + + var outputText = this.text; + + // word wrap + // preserve original text + if(this.style.wordWrap)outputText = this.wordWrap(this.text); + + //split text into lines + var lines = outputText.split(/(?:\r\n|\r|\n)/); + + //calculate text width + var lineWidths = []; + var maxLineWidth = 0; + for (var i = 0; i < lines.length; i++) + { + var lineWidth = this.context.measureText(lines[i]).width; + lineWidths[i] = lineWidth; + maxLineWidth = Math.max(maxLineWidth, lineWidth); + } + this.canvas.width = maxLineWidth + this.style.strokeThickness; + + //calculate text height + var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; + this.canvas.height = lineHeight * lines.length; + + //set canvas text styles + this.context.fillStyle = this.style.fill; + this.context.font = this.style.font; + + this.context.strokeStyle = this.style.stroke; + this.context.lineWidth = this.style.strokeThickness; + + this.context.textBaseline = "top"; + + //draw lines line by line + for (i = 0; i < lines.length; i++) + { + var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); + + if(this.style.align == "right") + { + linePosition.x += maxLineWidth - lineWidths[i]; + } + else if(this.style.align == "center") + { + linePosition.x += (maxLineWidth - lineWidths[i]) / 2; + } + + if(this.style.stroke && this.style.strokeThickness) + { + this.context.strokeText(lines[i], linePosition.x, linePosition.y); + } + + if(this.style.fill) + { + this.context.fillText(lines[i], linePosition.x, linePosition.y); + } + } + + this.updateTexture(); +}; + +/** + * Updates texture size based on canvas size + * + * @method updateTexture + * @private + */ +PIXI.Text.prototype.updateTexture = function() +{ + this.texture.baseTexture.width = this.canvas.width; + this.texture.baseTexture.height = this.canvas.height; + this.texture.frame.width = this.canvas.width; + this.texture.frame.height = this.canvas.height; + + this._width = this.canvas.width; + this._height = this.canvas.height; + + PIXI.texturesToUpdate.push(this.texture.baseTexture); +}; + +/** + * Updates the transfor of this object + * + * @method updateTransform + * @private + */ +PIXI.Text.prototype.updateTransform = function() +{ + if(this.dirty) + { + this.updateText(); + this.dirty = false; + } + + PIXI.Sprite.prototype.updateTransform.call(this); +}; + +/* + * http://stackoverflow.com/users/34441/ellisbben + * great solution to the problem! + * + * @method determineFontHeight + * @param fontStyle {Object} + * @private + */ +PIXI.Text.prototype.determineFontHeight = function(fontStyle) +{ + // build a little reference dictionary so if the font style has been used return a + // cached version... + var result = PIXI.Text.heightCache[fontStyle]; + + if(!result) + { + var body = document.getElementsByTagName("body")[0]; + var dummy = document.createElement("div"); + var dummyText = document.createTextNode("M"); + dummy.appendChild(dummyText); + dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); + body.appendChild(dummy); + + result = dummy.offsetHeight; + PIXI.Text.heightCache[fontStyle] = result; + + body.removeChild(dummy); + } + + return result; +}; + +/** + * A Text Object will apply wordwrap + * + * @method wordWrap + * @param text {String} + * @private + */ +PIXI.Text.prototype.wordWrap = function(text) +{ + // search good wrap position + var searchWrapPos = function(ctx, text, start, end, wrapWidth) + { + var p = Math.floor((end-start) / 2) + start; + if(p == start) { + return 1; + } + + if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) + { + if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) + { + return p; + } + else + { + return arguments.callee(ctx, text, p, end, wrapWidth); + } + } + else + { + return arguments.callee(ctx, text, start, p, wrapWidth); + } + }; + + var lineWrap = function(ctx, text, wrapWidth) + { + if(ctx.measureText(text).width <= wrapWidth || text.length < 1) + { + return text; + } + var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); + return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); + }; + + var result = ""; + var lines = text.split("\n"); + for (var i = 0; i < lines.length; i++) + { + result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; + } + + return result; +}; + +/** + * Destroys this text object + * + * @method destroy + * @param destroyTexture {Boolean} + */ +PIXI.Text.prototype.destroy = function(destroyTexture) +{ + if(destroyTexture) + { + this.texture.destroy(); + } + +}; + +PIXI.Text.heightCache = {}; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" + * You can generate the fnt files using + * http://www.angelcode.com/products/bmfont/ for windows or + * http://www.bmglyph.com/ for mac. + * + * @class BitmapText + * @extends DisplayObjectContainer + * @constructor + * @param text {String} The copy that you would like the text to display + * @param style {Object} The style parameters + * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") + */ +PIXI.BitmapText = function(text, style) +{ + PIXI.DisplayObjectContainer.call(this); + + this.setText(text); + this.setStyle(style); + this.updateText(); + this.dirty = false + +}; + +// constructor +PIXI.BitmapText.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); +PIXI.BitmapText.prototype.constructor = PIXI.BitmapText; + +/** + * Set the copy for the text object + * + * @method setText + * @param text {String} The copy that you would like the text to display + */ +PIXI.BitmapText.prototype.setText = function(text) +{ + this.text = text || " "; + this.dirty = true; +}; + +/** + * Set the style of the text + * + * @method setStyle + * @param style {Object} The style parameters + * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") + */ +PIXI.BitmapText.prototype.setStyle = function(style) +{ + style = style || {}; + style.align = style.align || "left"; + this.style = style; + + var font = style.font.split(" "); + this.fontName = font[font.length - 1]; + this.fontSize = font.length >= 2 ? parseInt(font[font.length - 2], 10) : PIXI.BitmapText.fonts[this.fontName].size; + + this.dirty = true; +}; + +/** + * Renders text + * + * @method updateText + * @private + */ +PIXI.BitmapText.prototype.updateText = function() +{ + var data = PIXI.BitmapText.fonts[this.fontName]; + var pos = new PIXI.Point(); + var prevCharCode = null; + var chars = []; + var maxLineWidth = 0; + var lineWidths = []; + var line = 0; + var scale = this.fontSize / data.size; + for(var i = 0; i < this.text.length; i++) + { + var charCode = this.text.charCodeAt(i); + if(/(?:\r\n|\r|\n)/.test(this.text.charAt(i))) + { + lineWidths.push(pos.x); + maxLineWidth = Math.max(maxLineWidth, pos.x); + line++; + + pos.x = 0; + pos.y += data.lineHeight; + prevCharCode = null; + continue; + } + + var charData = data.chars[charCode]; + if(!charData) continue; + + if(prevCharCode && charData[prevCharCode]) + { + pos.x += charData.kerning[prevCharCode]; + } + chars.push({texture:charData.texture, line: line, charCode: charCode, position: new PIXI.Point(pos.x + charData.xOffset, pos.y + charData.yOffset)}); + pos.x += charData.xAdvance; + + prevCharCode = charCode; + } + + lineWidths.push(pos.x); + maxLineWidth = Math.max(maxLineWidth, pos.x); + + var lineAlignOffsets = []; + for(i = 0; i <= line; i++) + { + var alignOffset = 0; + if(this.style.align == "right") + { + alignOffset = maxLineWidth - lineWidths[i]; + } + else if(this.style.align == "center") + { + alignOffset = (maxLineWidth - lineWidths[i]) / 2; + } + lineAlignOffsets.push(alignOffset); + } + + for(i = 0; i < chars.length; i++) + { + var c = new PIXI.Sprite(chars[i].texture)//PIXI.Sprite.fromFrame(chars[i].charCode); + c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale; + c.position.y = chars[i].position.y * scale; + c.scale.x = c.scale.y = scale; + this.addChild(c); + } + + this.width = pos.x * scale; + this.height = (pos.y + data.lineHeight) * scale; +}; + +/** + * Updates the transfor of this object + * + * @method updateTransform + * @private + */ +PIXI.BitmapText.prototype.updateTransform = function() +{ + if(this.dirty) + { + while(this.children.length > 0) + { + this.removeChild(this.getChildAt(0)); + } + this.updateText(); + + this.dirty = false; + } + + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); +}; + +PIXI.BitmapText.fonts = {}; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + /** + * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive + * This manager also supports multitouch. + * + * @class InteractionManager + * @constructor + * @param stage {Stage} The stage to handle interactions + */ +PIXI.InteractionManager = function(stage) +{ + /** + * a refference to the stage + * + * @property stage + * @type Stage + */ + this.stage = stage; + + /** + * the mouse data + * + * @property mouse + * @type InteractionData + */ + this.mouse = new PIXI.InteractionData(); + + /** + * an object that stores current touches (InteractionData) by id reference + * + * @property touchs + * @type Object + */ + this.touchs = {}; + + + + // helpers + this.tempPoint = new PIXI.Point(); + //this.tempMatrix = mat3.create(); + + this.mouseoverEnabled = true; + + //tiny little interactiveData pool! + this.pool = []; + + this.interactiveItems = []; + this.interactionDOMElement = null; + + //this will make it so that you dont have to call bind all the time + this.onMouseMove = this.onMouseMove.bind( this ); + this.onMouseDown = this.onMouseDown.bind(this); + this.onMouseOut = this.onMouseOut.bind(this); + this.onMouseUp = this.onMouseUp.bind(this); + + this.onTouchStart = this.onTouchStart.bind(this); + this.onTouchEnd = this.onTouchEnd.bind(this); + this.onTouchMove = this.onTouchMove.bind(this); + + + this.last = 0; +} + +// constructor +PIXI.InteractionManager.prototype.constructor = PIXI.InteractionManager; + +/** + * Collects an interactive sprite recursively to have their interactions managed + * + * @method collectInteractiveSprite + * @param displayObject {DisplayObject} the displayObject to collect + * @param iParent {DisplayObject} + * @private + */ +PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObject, iParent) +{ + var children = displayObject.children; + var length = children.length; + + /// make an interaction tree... {item.__interactiveParent} + for (var i = length-1; i >= 0; i--) + { + var child = children[i]; + +// if(child.visible) { + // push all interactive bits + if(child.interactive) + { + iParent.interactiveChildren = true; + //child.__iParent = iParent; + this.interactiveItems.push(child); + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, child); + } + } + else + { + child.__iParent = null; + + if(child.children.length > 0) + { + this.collectInteractiveSprite(child, iParent); + } + } +// } + } +} + +/** + * Sets the target for event delegation + * + * @method setTarget + * @param target {WebGLRenderer|CanvasRenderer} the renderer to bind events to + * @private + */ +PIXI.InteractionManager.prototype.setTarget = function(target) +{ + this.target = target; + + //check if the dom element has been set. If it has don't do anything + if( this.interactionDOMElement === null ) { + + this.setTargetDomElement( target.view ); + } + + document.body.addEventListener('mouseup', this.onMouseUp, true); +} + + +/** + * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM + * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element + * to receive those events + * + * @method setTargetDomElement + * @param domElement {DOMElement} the dom element which will receive mouse and touch events + * @private + */ +PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) +{ + //remove previouse listeners + if( this.interactionDOMElement !== null ) + { + this.interactionDOMElement.style['-ms-content-zooming'] = ''; + this.interactionDOMElement.style['-ms-touch-action'] = ''; + + this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); + this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); + this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); + this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); + this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); + } + + + if (window.navigator.msPointerEnabled) + { + // time to remove some of that zoom in ja.. + domElement.style['-ms-content-zooming'] = 'none'; + domElement.style['-ms-touch-action'] = 'none'; + + // DO some window specific touch! + } + + this.interactionDOMElement = domElement; + + domElement.addEventListener('mousemove', this.onMouseMove, true); + domElement.addEventListener('mousedown', this.onMouseDown, true); + domElement.addEventListener('mouseout', this.onMouseOut, true); + + // aint no multi touch just yet! + domElement.addEventListener('touchstart', this.onTouchStart, true); + domElement.addEventListener('touchend', this.onTouchEnd, true); + domElement.addEventListener('touchmove', this.onTouchMove, true); +} + + +/** + * updates the state of interactive objects + * + * @method update + * @private + */ +PIXI.InteractionManager.prototype.update = function() +{ + if(!this.target)return; + + // frequency of 30fps?? + var now = Date.now(); + var diff = now - this.last; + diff = (diff * 30) / 1000; + if(diff < 1)return; + this.last = now; + // + + // ok.. so mouse events?? + // yes for now :) + // OPTIMSE - how often to check?? + if(this.dirty) + { + this.dirty = false; + + var len = this.interactiveItems.length; + + for (var i=0; i < len; i++) { + this.interactiveItems[i].interactiveChildren = false; + } + + this.interactiveItems = []; + + if(this.stage.interactive)this.interactiveItems.push(this.stage); + // go through and collect all the objects that are interactive.. + this.collectInteractiveSprite(this.stage, this.stage); + } + + // loop through interactive objects! + var length = this.interactiveItems.length; + + this.interactionDOMElement.style.cursor = "default"; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + + //if(!item.visible)continue; + + // OPTIMISATION - only calculate every time if the mousemove function exists.. + // OK so.. does the object have any other interactive functions? + // hit-test the clip! + + + if(item.mouseover || item.mouseout || item.buttonMode) + { + // ok so there are some functions so lets hit test it.. + item.__hit = this.hitTest(item, this.mouse); + this.mouse.target = item; + // ok so deal with interactions.. + // loks like there was a hit! + if(item.__hit) + { + if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; + + if(!item.__isOver) + { + + if(item.mouseover)item.mouseover(this.mouse); + item.__isOver = true; + } + } + else + { + if(item.__isOver) + { + // roll out! + if(item.mouseout)item.mouseout(this.mouse); + item.__isOver = false; + } + } + } + + // ---> + } +} + +/** + * Is called when the mouse moves accross the renderer element + * + * @method onMouseMove + * @param event {Event} The DOM event of the mouse moving + * @private + */ +PIXI.InteractionManager.prototype.onMouseMove = function(event) +{ + this.mouse.originalEvent = event || window.event; //IE uses window.event + // TODO optimize by not check EVERY TIME! maybe half as often? // + var rect = this.interactionDOMElement.getBoundingClientRect(); + + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + + var length = this.interactiveItems.length; + var global = this.mouse.global; + + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.mousemove) + { + //call the function! + item.mousemove(this.mouse); + } + } +} + +/** + * Is called when the mouse button is pressed down on the renderer element + * + * @method onMouseDown + * @param event {Event} The DOM event of a mouse button being pressed down + * @private + */ +PIXI.InteractionManager.prototype.onMouseDown = function(event) +{ + this.mouse.originalEvent = event || window.event; //IE uses window.event + + // loop through inteaction tree... + // hit test each item! -> + // get interactive items under point?? + //stage.__i + var length = this.interactiveItems.length; + var global = this.mouse.global; + + var index = 0; + var parent = this.stage; + + // while + // hit test + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.mousedown || item.click) + { + item.__mouseIsDown = true; + item.__hit = this.hitTest(item, this.mouse); + + if(item.__hit) + { + //call the function! + if(item.mousedown)item.mousedown(this.mouse); + item.__isDown = true; + + // just the one! + if(!item.interactiveChildren)break; + } + } + } +} + + +PIXI.InteractionManager.prototype.onMouseOut = function(event) +{ + var length = this.interactiveItems.length; + + this.interactionDOMElement.style.cursor = "default"; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.__isOver) + { + this.mouse.target = item; + if(item.mouseout)item.mouseout(this.mouse); + item.__isOver = false; + } + } +} + +/** + * Is called when the mouse button is released on the renderer element + * + * @method onMouseUp + * @param event {Event} The DOM event of a mouse button being released + * @private + */ +PIXI.InteractionManager.prototype.onMouseUp = function(event) +{ + this.mouse.originalEvent = event || window.event; //IE uses window.event + + var global = this.mouse.global; + + + var length = this.interactiveItems.length; + var up = false; + + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + + if(item.mouseup || item.mouseupoutside || item.click) + { + item.__hit = this.hitTest(item, this.mouse); + + if(item.__hit && !up) + { + //call the function! + if(item.mouseup) + { + item.mouseup(this.mouse); + } + if(item.__isDown) + { + if(item.click)item.click(this.mouse); + } + + if(!item.interactiveChildren)up = true; + } + else + { + if(item.__isDown) + { + if(item.mouseupoutside)item.mouseupoutside(this.mouse); + } + } + + item.__isDown = false; + } + } +} + +/** + * Tests if the current mouse coords hit a sprite + * + * @method hitTest + * @param item {DisplayObject} The displayObject to test for a hit + * @param interactionData {InteractionData} The interactiondata object to update in the case of a hit + * @private + */ +PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) +{ + var global = interactionData.global; + + if(item.vcount !== PIXI.visibleCount)return false; + + var isSprite = (item instanceof PIXI.Sprite), + worldTransform = item.worldTransform, + a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], + a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], + id = 1 / (a00 * a11 + a01 * -a10), + x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, + y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; + + interactionData.target = item; + + //a sprite or display object with a hit area defined + if(item.hitArea && item.hitArea.contains) { + if(item.hitArea.contains(x, y)) { + //if(isSprite) + interactionData.target = item; + + return true; + } + + return false; + } + // a sprite with no hitarea defined + else if(isSprite) + { + var width = item.texture.frame.width, + height = item.texture.frame.height, + x1 = -width * item.anchor.x, + y1; + + if(x > x1 && x < x1 + width) + { + y1 = -height * item.anchor.y; + + if(y > y1 && y < y1 + height) + { + // set the target property if a hit is true! + interactionData.target = item + return true; + } + } + } + + var length = item.children.length; + + for (var i = 0; i < length; i++) + { + var tempItem = item.children[i]; + var hit = this.hitTest(tempItem, interactionData); + if(hit) + { + // hmm.. TODO SET CORRECT TARGET? + interactionData.target = item + return true; + } + } + + return false; +} + +/** + * Is called when a touch is moved accross the renderer element + * + * @method onTouchMove + * @param event {Event} The DOM event of a touch moving accross the renderer view + * @private + */ +PIXI.InteractionManager.prototype.onTouchMove = function(event) +{ + var rect = this.interactionDOMElement.getBoundingClientRect(); + var changedTouches = event.changedTouches; + + for (var i=0; i < changedTouches.length; i++) + { + var touchEvent = changedTouches[i]; + var touchData = this.touchs[touchEvent.identifier]; + touchData.originalEvent = event || window.event; + + // update the touch position + touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); + touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + } + + var length = this.interactiveItems.length; + for (var i = 0; i < length; i++) + { + var item = this.interactiveItems[i]; + if(item.touchmove)item.touchmove(touchData); + } +} + +/** + * Is called when a touch is started on the renderer element + * + * @method onTouchStart + * @param event {Event} The DOM event of a touch starting on the renderer view + * @private + */ +PIXI.InteractionManager.prototype.onTouchStart = function(event) +{ + var rect = this.interactionDOMElement.getBoundingClientRect(); + + var changedTouches = event.changedTouches; + for (var i=0; i < changedTouches.length; i++) + { + var touchEvent = changedTouches[i]; + + var touchData = this.pool.pop(); + if(!touchData)touchData = new PIXI.InteractionData(); + + touchData.originalEvent = event || window.event; + + this.touchs[touchEvent.identifier] = touchData; + touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); + touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + + var length = this.interactiveItems.length; + + for (var j = 0; j < length; j++) + { + var item = this.interactiveItems[j]; + + if(item.touchstart || item.tap) + { + item.__hit = this.hitTest(item, touchData); + + if(item.__hit) + { + //call the function! + if(item.touchstart)item.touchstart(touchData); + item.__isDown = true; + item.__touchData = touchData; + + if(!item.interactiveChildren)break; + } + } + } + } +} + +/** + * Is called when a touch is ended on the renderer element + * + * @method onTouchEnd + * @param event {Event} The DOM event of a touch ending on the renderer view + * @private + */ +PIXI.InteractionManager.prototype.onTouchEnd = function(event) +{ + //this.mouse.originalEvent = event || window.event; //IE uses window.event + var rect = this.interactionDOMElement.getBoundingClientRect(); + var changedTouches = event.changedTouches; + + for (var i=0; i < changedTouches.length; i++) + { + var touchEvent = changedTouches[i]; + var touchData = this.touchs[touchEvent.identifier]; + var up = false; + touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); + touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + + var length = this.interactiveItems.length; + for (var j = 0; j < length; j++) + { + var item = this.interactiveItems[j]; + var itemTouchData = item.__touchData; // <-- Here! + item.__hit = this.hitTest(item, touchData); + + if(itemTouchData == touchData) + { + // so this one WAS down... + touchData.originalEvent = event || window.event; + // hitTest?? + + if(item.touchend || item.tap) + { + if(item.__hit && !up) + { + if(item.touchend)item.touchend(touchData); + if(item.__isDown) + { + if(item.tap)item.tap(touchData); + } + + if(!item.interactiveChildren)up = true; + } + else + { + if(item.__isDown) + { + if(item.touchendoutside)item.touchendoutside(touchData); + } + } + + item.__isDown = false; + } + + item.__touchData = null; + + } + else + { + + } + } + // remove the touch.. + this.pool.push(touchData); + this.touchs[touchEvent.identifier] = null; + } +} + +/** + * Holds all information related to an Interaction event + * + * @class InteractionData + * @constructor + */ +PIXI.InteractionData = function() +{ + /** + * This point stores the global coords of where the touch/mouse event happened + * + * @property global + * @type Point + */ + this.global = new PIXI.Point(); + + // this is here for legacy... but will remove + this.local = new PIXI.Point(); + + /** + * The target Sprite that was interacted with + * + * @property target + * @type Sprite + */ + this.target; + + /** + * When passed to an event handler, this will be the original DOM Event that was captured + * + * @property originalEvent + * @type Event + */ + this.originalEvent; +} + +/** + * This will return the local coords of the specified displayObject for this InteractionData + * + * @method getLocalPosition + * @param displayObject {DisplayObject} The DisplayObject that you would like the local coords off + * @return {Point} A point containing the coords of the InteractionData position relative to the DisplayObject + */ +PIXI.InteractionData.prototype.getLocalPosition = function(displayObject) +{ + var worldTransform = displayObject.worldTransform; + var global = this.global; + + // do a cheeky transform to get the mouse coords; + var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], + a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], + id = 1 / (a00 * a11 + a01 * -a10); + // set the mouse coords... + return new PIXI.Point(a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, + a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id) +} + +// constructor +PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * A Stage represents the root of the display tree. Everything connected to the stage is rendered + * + * @class Stage + * @extends DisplayObjectContainer + * @constructor + * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format + * like: 0xFFFFFF for white + */ +PIXI.Stage = function(backgroundColor) +{ + PIXI.DisplayObjectContainer.call( this ); + + /** + * [read-only] Current transform of the object based on world (parent) factors + * + * @property worldTransform + * @type Mat3 + * @readOnly + * @private + */ + this.worldTransform = PIXI.mat3.create(); + + /** + * Whether or not the stage is interactive + * + * @property interactive + * @type Boolean + */ + this.interactive = true; + + /** + * The interaction manage for this stage, manages all interactive activity on the stage + * + * @property interactive + * @type InteractionManager + */ + this.interactionManager = new PIXI.InteractionManager(this); + + /** + * Whether the stage is dirty and needs to have interactions updated + * + * @property dirty + * @type Boolean + * @private + */ + this.dirty = true; + + this.__childrenAdded = []; + this.__childrenRemoved = []; + + //the stage is it's own stage + this.stage = this; + + //optimize hit detection a bit + this.stage.hitArea = new PIXI.Rectangle(0,0,100000, 100000); + + this.setBackgroundColor(backgroundColor); + this.worldVisible = true; +} + +// constructor +PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); +PIXI.Stage.prototype.constructor = PIXI.Stage; + +/** + * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. + * This is useful for when you have other DOM elements ontop of the Canvas element. + * + * @method setInteractionDelegate + * @param domElement {DOMElement} This new domElement which will receive mouse/touch events + */ +PIXI.Stage.prototype.setInteractionDelegate = function(domElement) +{ + this.interactionManager.setTargetDomElement( domElement ); +} + +/* + * Updates the object transform for rendering + * + * @method updateTransform + * @private + */ +PIXI.Stage.prototype.updateTransform = function() +{ + this.worldAlpha = 1; + this.vcount = PIXI.visibleCount; + + for(var i=0,j=this.children.length; i> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; +} + +/** + * A polyfill for Function.prototype.bind + * + * @method bind + */ +if (typeof Function.prototype.bind != 'function') { + Function.prototype.bind = (function () { + var slice = Array.prototype.slice; + return function (thisArg) { + var target = this, boundArgs = slice.call(arguments, 1); + + if (typeof target != 'function') throw new TypeError(); + + function bound() { + var args = boundArgs.concat(slice.call(arguments)); + target.apply(this instanceof bound ? this : thisArg, args); + } + + bound.prototype = (function F(proto) { + proto && (F.prototype = proto); + if (!(this instanceof F)) return new F; + })(target.prototype); + + return bound; + }; + })(); +} + +/** + * A wrapper for ajax requests to be handled cross browser + * + * @class AjaxRequest + * @constructor + */ +var AjaxRequest = PIXI.AjaxRequest = function() +{ + var activexmodes = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Microsoft.XMLHTTP"] //activeX versions to check for in IE + + if (window.ActiveXObject) + { //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken) + for (var i=0; i>>>>>>>>") + console.log("_") + var safe = 0; + var tmp = item.first; + console.log(tmp); + + while(tmp._iNext) + { + safe++; + tmp = tmp._iNext; + console.log(tmp); + // console.log(tmp); + + if(safe > 100) + { + console.log("BREAK") + break + } + } +} + + + + + + +/** + * https://github.com/mrdoob/eventtarget.js/ + * THankS mr DOob! + */ + +/** + * Adds event emitter functionality to a class + * + * @class EventTarget + * @example + * function MyEmitter() { + * PIXI.EventTarget.call(this); //mixes in event target stuff + * } + * + * var em = new MyEmitter(); + * em.emit({ type: 'eventName', data: 'some data' }); + */ +PIXI.EventTarget = function () { + + var listeners = {}; + + this.addEventListener = this.on = function ( type, listener ) { + + + if ( listeners[ type ] === undefined ) { + + listeners[ type ] = []; + + } + + if ( listeners[ type ].indexOf( listener ) === - 1 ) { + + listeners[ type ].push( listener ); + } + + }; + + this.dispatchEvent = this.emit = function ( event ) { + + if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { + + return; + + } + + for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { + + listeners[ event.type ][ i ]( event ); + + } + + }; + + this.removeEventListener = this.off = function ( type, listener ) { + + var index = listeners[ type ].indexOf( listener ); + + if ( index !== - 1 ) { + + listeners[ type ].splice( index, 1 ); + + } + + }; + +}; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * This helper function will automatically detect which renderer you should be using. + * WebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by + * the browser then this function will return a canvas renderer + * + * @method autoDetectRenderer + * @static + * @param width {Number} the width of the renderers view + * @param height {Number} the height of the renderers view + * @param view {Canvas} the canvas to use as a view, optional + * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) + * + * antialias + */ +PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) +{ + if(!width)width = 800; + if(!height)height = 600; + + // BORROWED from Mr Doob (mrdoob.com) + var webgl = ( function () { try { var canvas = document.createElement( 'canvas' ); return !! window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ); } catch( e ) { return false; } } )(); + + if(webgl) + { + var ie = (navigator.userAgent.toLowerCase().indexOf('msie') != -1); + webgl = !ie; + } + + //console.log(webgl); + if( webgl ) + { + return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); + } + + return new PIXI.CanvasRenderer(width, height, view, transparent); +}; + + + +/* + PolyK library + url: http://polyk.ivank.net + Released under MIT licence. + + Copyright (c) 2012 Ivan Kuckir + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + This is an amazing lib! + + slightly modified by mat groves (matgroves.com); +*/ + +PIXI.PolyK = {}; + +/** + * Triangulates shapes for webGL graphic fills + * + * @method Triangulate + * @namespace PolyK + * @constructor + */ +PIXI.PolyK.Triangulate = function(p) +{ + var sign = true; + + var n = p.length>>1; + if(n<3) return []; + var tgs = []; + var avl = []; + for(var i=0; i 3) + { + var i0 = avl[(i+0)%al]; + var i1 = avl[(i+1)%al]; + var i2 = avl[(i+2)%al]; + + var ax = p[2*i0], ay = p[2*i0+1]; + var bx = p[2*i1], by = p[2*i1+1]; + var cx = p[2*i2], cy = p[2*i2+1]; + + var earFound = false; + if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) + { + earFound = true; + for(var j=0; j 3*al) + { + // need to flip flip reverse it! + // reset! + if(sign) + { + var tgs = []; + avl = []; + for(var i=0; i= 0) && (v >= 0) && (u + v < 1); +} + +/** + * Checks if a shape is convex + * + * @class _convex + * @namespace PolyK + * @private + */ +PIXI.PolyK._convex = function(ax, ay, bx, by, cx, cy, sign) +{ + return ((ay-by)*(cx-bx) + (bx-ax)*(cy-by) >= 0) == sign; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/* + * the default suoer fast shader! + */ + +PIXI.shaderFragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", + "gl_FragColor = gl_FragColor * vColor;", + "}" +]; + +PIXI.shaderVertexSrc = [ + "attribute vec2 aVertexPosition;", + "attribute vec2 aTextureCoord;", + "attribute float aColor;", + + "uniform vec2 projectionVector;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "void main(void) {", + "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", + "vTextureCoord = aTextureCoord;", + "vColor = aColor;", + "}" +]; + +/* + * the triangle strip shader.. + */ + +PIXI.stripShaderFragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float alpha;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", + "gl_FragColor = gl_FragColor * alpha;", + "}" +]; + + +PIXI.stripShaderVertexSrc = [ + "attribute vec2 aVertexPosition;", + "attribute vec2 aTextureCoord;", + "attribute float aColor;", + "uniform mat3 translationMatrix;", + "uniform vec2 projectionVector;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "void main(void) {", + "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", + "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", + "vTextureCoord = aTextureCoord;", + "vColor = aColor;", + "}" +]; + +/* + * primitive shader.. + */ + +PIXI.primitiveShaderFragmentSrc = [ + "precision mediump float;", + "varying vec4 vColor;", + "void main(void) {", + "gl_FragColor = vColor;", + "}" +]; + +PIXI.primitiveShaderVertexSrc = [ + "attribute vec2 aVertexPosition;", + "attribute vec4 aColor;", + "uniform mat3 translationMatrix;", + "uniform vec2 projectionVector;", + "uniform float alpha;", + "varying vec4 vColor;", + "void main(void) {", + "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", + "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", + "vColor = aColor * alpha;", + "}" +]; + +PIXI.shaderStack = []; + +PIXI.initPrimitiveShader = function() +{ + var gl = PIXI.gl; + + var shaderProgram = PIXI.compileProgram(PIXI.primitiveShaderVertexSrc, PIXI.primitiveShaderFragmentSrc) + + gl.useProgram(shaderProgram); + + shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); + shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); + + shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); + shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); + + + //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + //gl.enableVertexAttribArray(shaderProgram.colorAttribute); +//gl.enableVertexAttribArray(program.textureCoordAttribute); + + shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); + + PIXI.primitiveProgram = shaderProgram; + + +} + +PIXI.initDefaultShader = function() +{ + PIXI.defaultShader = new PIXI.PixiShader(); + PIXI.defaultShader.init(); + PIXI.pushShader(PIXI.defaultShader); + /* + PIXI.shaderStack.push(PIXI.defaultShader); + PIXI.current*/ +} + +PIXI.initDefaultStripShader = function() +{ + var gl = this.gl; + var shaderProgram = PIXI.compileProgram(PIXI.stripShaderVertexSrc, PIXI.stripShaderFragmentSrc) + + gl.useProgram(shaderProgram); + + shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); + shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); + shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); + shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); + shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); + + shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); + shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); + shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); + + PIXI.stripShaderProgram = shaderProgram; +} + +PIXI.CompileVertexShader = function(gl, shaderSrc) +{ + return PIXI._CompileShader(gl, shaderSrc, gl.VERTEX_SHADER); +} + +PIXI.CompileFragmentShader = function(gl, shaderSrc) +{ + return PIXI._CompileShader(gl, shaderSrc, gl.FRAGMENT_SHADER); +} + +PIXI._CompileShader = function(gl, shaderSrc, shaderType) +{ + var src = shaderSrc.join("\n"); + var shader = gl.createShader(shaderType); + gl.shaderSource(shader, src); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + alert(gl.getShaderInfoLog(shader)); + return null; + } + + return shader; +} + + +PIXI.compileProgram = function(vertexSrc, fragmentSrc) +{ + var gl = PIXI.gl; + var fragmentShader = PIXI.CompileFragmentShader(gl, fragmentSrc); + var vertexShader = PIXI.CompileVertexShader(gl, vertexSrc); + + var shaderProgram = gl.createProgram(); + + gl.attachShader(shaderProgram, vertexShader); + gl.attachShader(shaderProgram, fragmentShader); + gl.linkProgram(shaderProgram); + + if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { + alert("Could not initialise shaders"); + } + + return shaderProgram; +} + +PIXI.pushShader = function(shader) +{ + PIXI.shaderStack.push(shader); + + var gl = PIXI.gl; + + var shaderProgram = shader.program; + + + // map uniforms.. + gl.useProgram(shaderProgram); + + gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); + gl.enableVertexAttribArray(shaderProgram.colorAttribute); + gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); + + shader.syncUniforms(); + + PIXI.currentShader = shaderProgram; +} + + +PIXI.popShader = function() +{ + var gl = PIXI.gl; + var lastProgram = PIXI.shaderStack.pop(); + + var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; + + gl.useProgram(shaderProgram); + + PIXI.currentShader = shaderProgram; +} + +PIXI.activatePrimitiveShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.primitiveProgram); + gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); +} + +PIXI.deactivatePrimitiveShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.currentShader); + gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); +} +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.PixiShader = function() +{ + // the webGL program.. + this.program; + + this.fragmentSrc = [ + "precision lowp float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", + "}" + ]; + +} + +PIXI.PixiShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get the default shader bits! + program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); + program.colorAttribute = gl.getAttribLocation(program, "aColor"); + program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); + + program.projectionVector = gl.getUniformLocation(program, "projectionVector"); + program.samplerUniform = gl.getUniformLocation(program, "uSampler"); + + // add those custom shaders! + for (var key in this.uniforms) + { + // get the uniform locations.. + program[key] = gl.getUniformLocation(program, key); + } + + this.program = program; +} + +PIXI.PixiShader.prototype.syncUniforms = function() +{ + var gl = PIXI.gl; + + for (var key in this.uniforms) + { + //var + var type = this.uniforms[key].type; + + // need to grow this! + if(type == "f") + { + gl.uniform1f(this.program[key], this.uniforms[key].value); + } + if(type == "f2") + { + gl.uniform2f(this.program[key], this.uniforms[key].value.x, this.uniforms[key].value.y); + } + else if(type == "mat4") + { + gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); + } + else if(type == "sampler2D") + { + // first texture... + var texture = this.uniforms[key].value; + + gl.activeTexture(gl.TEXTURE1); + gl.bindTexture(gl.TEXTURE_2D, texture.baseTexture._glTexture); + + gl.uniform1i(this.program[key], 1); + + + // activate texture.. + // gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); + // gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); + } + } + +} + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * A set of functions used by the webGL renderer to draw the primitive graphics data + * + * @class CanvasGraphics + */ +PIXI.WebGLGraphics = function() +{ + +} + +/** + * Renders the graphics object + * + * @static + * @private + * @method renderGraphics + * @param graphics {Graphics} + * @param projection {Object} + */ +PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) +{ + var gl = PIXI.gl; + + if(!graphics._webGL)graphics._webGL = {points:[], indices:[], lastIndex:0, + buffer:gl.createBuffer(), + indexBuffer:gl.createBuffer()}; + + if(graphics.dirty) + { + graphics.dirty = false; + + if(graphics.clearDirty) + { + graphics.clearDirty = false; + + graphics._webGL.lastIndex = 0; + graphics._webGL.points = []; + graphics._webGL.indices = []; + + } + + PIXI.WebGLGraphics.updateGraphics(graphics); + } + + + PIXI.activatePrimitiveShader(); + + // This could be speeded up fo sure! + var m = PIXI.mat3.clone(graphics.worldTransform); + + PIXI.mat3.transpose(m); + + // set the matrix transform for the + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + + gl.uniformMatrix3fv(PIXI.primitiveProgram.translationMatrix, false, m); + + gl.uniform2f(PIXI.primitiveProgram.projectionVector, projection.x, projection.y); + + gl.uniform1f(PIXI.primitiveProgram.alpha, graphics.worldAlpha); + + gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); + + // WHY DOES THIS LINE NEED TO BE THERE??? + //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + // its not even used.. but need to be set or it breaks? + // only on pc though.. + + gl.vertexAttribPointer(PIXI.primitiveProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 4 * 6, 0); + gl.vertexAttribPointer(PIXI.primitiveProgram.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4); + + // set the index buffer! + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); + + gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); + + PIXI.deactivatePrimitiveShader(); + + // return to default shader... +// PIXI.activateShader(PIXI.defaultShader); +} + +/** + * Updates the graphics object + * + * @static + * @private + * @method updateGraphics + * @param graphics {Graphics} + */ +PIXI.WebGLGraphics.updateGraphics = function(graphics) +{ + for (var i=graphics._webGL.lastIndex; i < graphics.graphicsData.length; i++) + { + var data = graphics.graphicsData[i]; + + if(data.type == PIXI.Graphics.POLY) + { + if(data.fill) + { + if(data.points.length>3) + PIXI.WebGLGraphics.buildPoly(data, graphics._webGL); + } + + if(data.lineWidth > 0) + { + PIXI.WebGLGraphics.buildLine(data, graphics._webGL); + } + } + else if(data.type == PIXI.Graphics.RECT) + { + PIXI.WebGLGraphics.buildRectangle(data, graphics._webGL); + } + else if(data.type == PIXI.Graphics.CIRC || data.type == PIXI.Graphics.ELIP) + { + PIXI.WebGLGraphics.buildCircle(data, graphics._webGL); + } + }; + + graphics._webGL.lastIndex = graphics.graphicsData.length; + + var gl = PIXI.gl; + + graphics._webGL.glPoints = new Float32Array(graphics._webGL.points); + + gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); + gl.bufferData(gl.ARRAY_BUFFER, graphics._webGL.glPoints, gl.STATIC_DRAW); + + graphics._webGL.glIndicies = new Uint16Array(graphics._webGL.indices); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.glIndicies, gl.STATIC_DRAW); +} + +/** + * Builds a rectangle to draw + * + * @static + * @private + * @method buildRectangle + * @param graphics {Graphics} + * @param webGLData {Object} + */ +PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData) +{ + // --- // + // need to convert points to a nice regular data + // + var rectData = graphicsData.points; + var x = rectData[0]; + var y = rectData[1]; + var width = rectData[2]; + var height = rectData[3]; + + + if(graphicsData.fill) + { + var color = HEXtoRGB(graphicsData.fillColor); + var alpha = graphicsData.fillAlpha; + + var r = color[0] * alpha; + var g = color[1] * alpha; + var b = color[2] * alpha; + + var verts = webGLData.points; + var indices = webGLData.indices; + + var vertPos = verts.length/6; + + // start + verts.push(x, y); + verts.push(r, g, b, alpha); + + verts.push(x + width, y); + verts.push(r, g, b, alpha); + + verts.push(x , y + height); + verts.push(r, g, b, alpha); + + verts.push(x + width, y + height); + verts.push(r, g, b, alpha); + + // insert 2 dead triangles.. + indices.push(vertPos, vertPos, vertPos+1, vertPos+2, vertPos+3, vertPos+3) + } + + if(graphicsData.lineWidth) + { + graphicsData.points = [x, y, + x + width, y, + x + width, y + height, + x, y + height, + x, y]; + + PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); + } + +} + +/** + * Builds a circle to draw + * + * @static + * @private + * @method buildCircle + * @param graphics {Graphics} + * @param webGLData {Object} + */ +PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData) +{ + // --- // + // need to convert points to a nice regular data + // + var rectData = graphicsData.points; + var x = rectData[0]; + var y = rectData[1]; + var width = rectData[2]; + var height = rectData[3]; + + var totalSegs = 40; + var seg = (Math.PI * 2) / totalSegs ; + + if(graphicsData.fill) + { + var color = HEXtoRGB(graphicsData.fillColor); + var alpha = graphicsData.fillAlpha; + + var r = color[0] * alpha; + var g = color[1] * alpha; + var b = color[2] * alpha; + + var verts = webGLData.points; + var indices = webGLData.indices; + + var vecPos = verts.length/6; + + indices.push(vecPos); + + for (var i=0; i < totalSegs + 1 ; i++) + { + verts.push(x,y, r, g, b, alpha); + + verts.push(x + Math.sin(seg * i) * width, + y + Math.cos(seg * i) * height, + r, g, b, alpha); + + indices.push(vecPos++, vecPos++); + }; + + indices.push(vecPos-1); + } + + if(graphicsData.lineWidth) + { + graphicsData.points = []; + + for (var i=0; i < totalSegs + 1; i++) + { + graphicsData.points.push(x + Math.sin(seg * i) * width, + y + Math.cos(seg * i) * height) + }; + + PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); + } + +} + +/** + * Builds a line to draw + * + * @static + * @private + * @method buildLine + * @param graphics {Graphics} + * @param webGLData {Object} + */ +PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) +{ + // TODO OPTIMISE! + + var wrap = true; + var points = graphicsData.points; + if(points.length == 0)return; + + // get first and last point.. figure out the middle! + var firstPoint = new PIXI.Point( points[0], points[1] ); + var lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); + + // if the first point is the last point - goona have issues :) + if(firstPoint.x == lastPoint.x && firstPoint.y == lastPoint.y) + { + points.pop(); + points.pop(); + + lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); + + var midPointX = lastPoint.x + (firstPoint.x - lastPoint.x) *0.5; + var midPointY = lastPoint.y + (firstPoint.y - lastPoint.y) *0.5; + + points.unshift(midPointX, midPointY); + points.push(midPointX, midPointY) + } + + var verts = webGLData.points; + var indices = webGLData.indices; + var length = points.length / 2; + var indexCount = points.length; + var indexStart = verts.length/6; + + // DRAW the Line + var width = graphicsData.lineWidth / 2; + + // sort color + var color = HEXtoRGB(graphicsData.lineColor); + var alpha = graphicsData.lineAlpha; + var r = color[0] * alpha; + var g = color[1] * alpha; + var b = color[2] * alpha; + + var p1x, p1y, p2x, p2y, p3x, p3y; + var perpx, perpy, perp2x, perp2y, perp3x, perp3y; + var ipx, ipy; + var a1, b1, c1, a2, b2, c2; + var denom, pdist, dist; + + p1x = points[0]; + p1y = points[1]; + + p2x = points[2]; + p2y = points[3]; + + perpx = -(p1y - p2y); + perpy = p1x - p2x; + + dist = Math.sqrt(perpx*perpx + perpy*perpy); + + perpx /= dist; + perpy /= dist; + perpx *= width; + perpy *= width; + + // start + verts.push(p1x - perpx , p1y - perpy, + r, g, b, alpha); + + verts.push(p1x + perpx , p1y + perpy, + r, g, b, alpha); + + for (var i = 1; i < length-1; i++) + { + p1x = points[(i-1)*2]; + p1y = points[(i-1)*2 + 1]; + + p2x = points[(i)*2] + p2y = points[(i)*2 + 1] + + p3x = points[(i+1)*2]; + p3y = points[(i+1)*2 + 1]; + + perpx = -(p1y - p2y); + perpy = p1x - p2x; + + dist = Math.sqrt(perpx*perpx + perpy*perpy); + perpx /= dist; + perpy /= dist; + perpx *= width; + perpy *= width; + + perp2x = -(p2y - p3y); + perp2y = p2x - p3x; + + dist = Math.sqrt(perp2x*perp2x + perp2y*perp2y); + perp2x /= dist; + perp2y /= dist; + perp2x *= width; + perp2y *= width; + + a1 = (-perpy + p1y) - (-perpy + p2y); + b1 = (-perpx + p2x) - (-perpx + p1x); + c1 = (-perpx + p1x) * (-perpy + p2y) - (-perpx + p2x) * (-perpy + p1y); + a2 = (-perp2y + p3y) - (-perp2y + p2y); + b2 = (-perp2x + p2x) - (-perp2x + p3x); + c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y); + + denom = a1*b2 - a2*b1; + + if (denom == 0) { + denom+=1; + } + + px = (b1*c2 - b2*c1)/denom; + py = (a2*c1 - a1*c2)/denom; + + pdist = (px -p2x) * (px -p2x) + (py -p2y) + (py -p2y); + + if(pdist > 140 * 140) + { + perp3x = perpx - perp2x; + perp3y = perpy - perp2y; + + dist = Math.sqrt(perp3x*perp3x + perp3y*perp3y); + perp3x /= dist; + perp3y /= dist; + perp3x *= width; + perp3y *= width; + + verts.push(p2x - perp3x, p2y -perp3y); + verts.push(r, g, b, alpha); + + verts.push(p2x + perp3x, p2y +perp3y); + verts.push(r, g, b, alpha); + + verts.push(p2x - perp3x, p2y -perp3y); + verts.push(r, g, b, alpha); + + indexCount++; + } + else + { + verts.push(px , py); + verts.push(r, g, b, alpha); + + verts.push(p2x - (px-p2x), p2y - (py - p2y)); + verts.push(r, g, b, alpha); + } + } + + p1x = points[(length-2)*2] + p1y = points[(length-2)*2 + 1] + + p2x = points[(length-1)*2] + p2y = points[(length-1)*2 + 1] + + perpx = -(p1y - p2y) + perpy = p1x - p2x; + + dist = Math.sqrt(perpx*perpx + perpy*perpy); + perpx /= dist; + perpy /= dist; + perpx *= width; + perpy *= width; + + verts.push(p2x - perpx , p2y - perpy) + verts.push(r, g, b, alpha); + + verts.push(p2x + perpx , p2y + perpy) + verts.push(r, g, b, alpha); + + indices.push(indexStart); + + for (var i=0; i < indexCount; i++) + { + indices.push(indexStart++); + }; + + indices.push(indexStart-1); +} + +/** + * Builds a polygon to draw + * + * @static + * @private + * @method buildPoly + * @param graphics {Graphics} + * @param webGLData {Object} + */ +PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData) +{ + var points = graphicsData.points; + if(points.length < 6)return; + + // get first and last point.. figure out the middle! + var verts = webGLData.points; + var indices = webGLData.indices; + + var length = points.length / 2; + + // sort color + var color = HEXtoRGB(graphicsData.fillColor); + var alpha = graphicsData.fillAlpha; + var r = color[0] * alpha; + var g = color[1] * alpha; + var b = color[2] * alpha; + + var triangles = PIXI.PolyK.Triangulate(points); + + var vertPos = verts.length / 6; + + for (var i=0; i < triangles.length; i+=3) + { + indices.push(triangles[i] + vertPos); + indices.push(triangles[i] + vertPos); + indices.push(triangles[i+1] + vertPos); + indices.push(triangles[i+2] +vertPos); + indices.push(triangles[i+2] + vertPos); + }; + + for (var i = 0; i < length; i++) + { + verts.push(points[i * 2], points[i * 2 + 1], + r, g, b, alpha); + }; +} + +function HEXtoRGB(hex) { + return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; +} + + + + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI._defaultFrame = new PIXI.Rectangle(0,0,1,1); + +// an instance of the gl context.. +// only one at the moment :/ +PIXI.gl; + +/** + * the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer + * should be used for browsers support webGL. This Render works by automatically managing webGLBatchs. + * So no need for Sprite Batch's or Sprite Cloud's + * Dont forget to add the view to your DOM or you will not see anything :) + * + * @class WebGLRenderer + * @constructor + * @param width=0 {Number} the width of the canvas view + * @param height=0 {Number} the height of the canvas view + * @param view {Canvas} the canvas to use as a view, optional + * @param transparent=false {Boolean} the transparency of the render view, default false + * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) + * + */ +PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) +{ + // do a catch.. only 1 webGL renderer.. + + this.transparent = !!transparent; + + this.width = width || 800; + this.height = height || 600; + + this.view = view || document.createElement( 'canvas' ); + this.view.width = this.width; + this.view.height = this.height; + + // deal with losing context.. + var scope = this; + this.view.addEventListener('webglcontextlost', function(event) { scope.handleContextLost(event); }, false) + this.view.addEventListener('webglcontextrestored', function(event) { scope.handleContextRestored(event); }, false) + + this.batchs = []; + + var options = { + alpha: this.transparent, + antialias:!!antialias, // SPEED UP?? + premultipliedAlpha:false, + stencil:true + } + + //try 'experimental-webgl' + try { + PIXI.gl = this.gl = this.view.getContext("experimental-webgl", options); + } catch (e) { + //try 'webgl' + try { + PIXI.gl = this.gl = this.view.getContext("webgl", options); + } catch (e) { + // fail, not able to get a context + throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); + } + } + + PIXI.initDefaultShader(); + PIXI.initPrimitiveShader(); + PIXI.initDefaultStripShader(); + + +// PIXI.activateDefaultShader(); + + var gl = this.gl; + PIXI.WebGLRenderer.gl = gl; + + this.batch = new PIXI.WebGLBatch(gl); + gl.disable(gl.DEPTH_TEST); + gl.disable(gl.CULL_FACE); + + gl.enable(gl.BLEND); + gl.colorMask(true, true, true, this.transparent); + + PIXI.projection = new PIXI.Point(400, 300); + + this.resize(this.width, this.height); + this.contextLost = false; + + PIXI.pushShader(PIXI.defaultShader); + + this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); + +} + +// constructor +PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; + +/** + * Gets a new WebGLBatch from the pool + * + * @static + * @method getBatch + * @return {WebGLBatch} + * @private + */ +PIXI.WebGLRenderer.getBatch = function() +{ + if(PIXI._batchs.length == 0) + { + return new PIXI.WebGLBatch(PIXI.WebGLRenderer.gl); + } + else + { + return PIXI._batchs.pop(); + } +} + +/** + * Puts a batch back into the pool + * + * @static + * @method returnBatch + * @param batch {WebGLBatch} The batch to return + * @private + */ +PIXI.WebGLRenderer.returnBatch = function(batch) +{ + batch.clean(); + PIXI._batchs.push(batch); +} + +/** + * Renders the stage to its webGL view + * + * @method render + * @param stage {Stage} the Stage element to be rendered + */ +PIXI.WebGLRenderer.prototype.render = function(stage) +{ + if(this.contextLost)return; + + + // if rendering a new stage clear the batchs.. + if(this.__stage !== stage) + { + // TODO make this work + // dont think this is needed any more? + this.__stage = stage; + this.stageRenderGroup.setRenderable(stage); + } + + // TODO not needed now... + // update children if need be + // best to remove first! + /*for (var i=0; i < stage.__childrenRemoved.length; i++) + { + var group = stage.__childrenRemoved[i].__renderGroup + if(group)group.removeDisplayObject(stage.__childrenRemoved[i]); + }*/ + + // update any textures + PIXI.WebGLRenderer.updateTextures(); + + // update the scene graph + PIXI.visibleCount++; + stage.updateTransform(); + + var gl = this.gl; + + // -- Does this need to be set every frame? -- // + gl.colorMask(true, true, true, this.transparent); + gl.viewport(0, 0, this.width, this.height); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); + gl.clear(gl.COLOR_BUFFER_BIT); + + // HACK TO TEST + + this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; + this.stageRenderGroup.render(PIXI.projection); + + // interaction + // run interaction! + if(stage.interactive) + { + //need to add some events! + if(!stage._interactiveEventsAdded) + { + stage._interactiveEventsAdded = true; + stage.interactionManager.setTarget(this); + } + } + + // after rendering lets confirm all frames that have been uodated.. + if(PIXI.Texture.frameUpdates.length > 0) + { + for (var i=0; i < PIXI.Texture.frameUpdates.length; i++) + { + PIXI.Texture.frameUpdates[i].updateFrame = false; + }; + + PIXI.Texture.frameUpdates = []; + } +} + +/** + * Updates the textures loaded into this webgl renderer + * + * @static + * @method updateTextures + * @private + */ +PIXI.WebGLRenderer.updateTextures = function() +{ + //TODO break this out into a texture manager... + for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); + for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); + PIXI.texturesToUpdate = []; + PIXI.texturesToDestroy = []; +} + +/** + * Updates a loaded webgl texture + * + * @static + * @method updateTexture + * @param texture {Texture} The texture to update + * @private + */ +PIXI.WebGLRenderer.updateTexture = function(texture) +{ + //TODO break this out into a texture manager... + var gl = PIXI.gl; + + if(!texture._glTexture) + { + texture._glTexture = gl.createTexture(); + } + + if(texture.hasLoaded) + { + gl.bindTexture(gl.TEXTURE_2D, texture._glTexture); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); + + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + + // reguler... + + if(!texture._powerOf2) + { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + else + { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); + } + + gl.bindTexture(gl.TEXTURE_2D, null); + } +} + +/** + * Destroys a loaded webgl texture + * + * @method destroyTexture + * @param texture {Texture} The texture to update + * @private + */ +PIXI.WebGLRenderer.destroyTexture = function(texture) +{ + //TODO break this out into a texture manager... + var gl = PIXI.gl; + + if(texture._glTexture) + { + texture._glTexture = gl.createTexture(); + gl.deleteTexture(gl.TEXTURE_2D, texture._glTexture); + } +} + +/** + * resizes the webGL view to the specified width and height + * + * @method resize + * @param width {Number} the new width of the webGL view + * @param height {Number} the new height of the webGL view + */ +PIXI.WebGLRenderer.prototype.resize = function(width, height) +{ + this.width = width; + this.height = height; + + this.view.width = width; + this.view.height = height; + + this.gl.viewport(0, 0, this.width, this.height); + + //var projectionMatrix = this.projectionMatrix; + + PIXI.projection.x = this.width/2; + PIXI.projection.y = this.height/2; + +// projectionMatrix[0] = 2/this.width; +// projectionMatrix[5] = -2/this.height; +// projectionMatrix[12] = -1; +// projectionMatrix[13] = 1; +} + +/** + * Handles a lost webgl context + * + * @method handleContextLost + * @param event {Event} + * @private + */ +PIXI.WebGLRenderer.prototype.handleContextLost = function(event) +{ + event.preventDefault(); + this.contextLost = true; +} + +/** + * Handles a restored webgl context + * + * @method handleContextRestored + * @param event {Event} + * @private + */ +PIXI.WebGLRenderer.prototype.handleContextRestored = function(event) +{ + this.gl = this.view.getContext("experimental-webgl", { + alpha: true + }); + + this.initShaders(); + + for(var key in PIXI.TextureCache) + { + var texture = PIXI.TextureCache[key].baseTexture; + texture._glTexture = null; + PIXI.WebGLRenderer.updateTexture(texture); + }; + + for (var i=0; i < this.batchs.length; i++) + { + this.batchs[i].restoreLostContext(this.gl)// + this.batchs[i].dirty = true; + }; + + PIXI._restoreBatchs(this.gl); + + this.contextLost = false; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI._batchs = []; + +/** + * @private + */ +PIXI._getBatch = function(gl) +{ + if(PIXI._batchs.length == 0) + { + return new PIXI.WebGLBatch(gl); + } + else + { + return PIXI._batchs.pop(); + } +} + +/** + * @private + */ +PIXI._returnBatch = function(batch) +{ + batch.clean(); + PIXI._batchs.push(batch); +} + +/** + * @private + */ +PIXI._restoreBatchs = function(gl) +{ + for (var i=0; i < PIXI._batchs.length; i++) + { + PIXI._batchs[i].restoreLostContext(gl); + }; +} + +/** + * A WebGLBatch Enables a group of sprites to be drawn using the same settings. + * if a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch. + * All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites + * in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled + * automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster + * the webGL renderer will run. + * + * @class WebGLBatch + * @constructor + * @param gl {WebGLContext} an instance of the webGL context + */ +PIXI.WebGLBatch = function(gl) +{ + this.gl = gl; + + this.size = 0; + + this.vertexBuffer = gl.createBuffer(); + this.indexBuffer = gl.createBuffer(); + this.uvBuffer = gl.createBuffer(); + this.colorBuffer = gl.createBuffer(); + this.blendMode = PIXI.blendModes.NORMAL; + this.dynamicSize = 1; +} + +// constructor +PIXI.WebGLBatch.prototype.constructor = PIXI.WebGLBatch; + +/** + * Cleans the batch so that is can be returned to an object pool and reused + * + * @method clean + */ +PIXI.WebGLBatch.prototype.clean = function() +{ + this.verticies = []; + this.uvs = []; + this.indices = []; + this.colors = []; + this.dynamicSize = 1; + this.texture = null; + this.last = null; + this.size = 0; + this.head; + this.tail; +} + +/** + * Recreates the buffers in the event of a context loss + * + * @method restoreLostContext + * @param gl {WebGLContext} + */ +PIXI.WebGLBatch.prototype.restoreLostContext = function(gl) +{ + this.gl = gl; + this.vertexBuffer = gl.createBuffer(); + this.indexBuffer = gl.createBuffer(); + this.uvBuffer = gl.createBuffer(); + this.colorBuffer = gl.createBuffer(); +} + +/** + * inits the batch's texture and blend mode based if the supplied sprite + * + * @method init + * @param sprite {Sprite} the first sprite to be added to the batch. Only sprites with + * the same base texture and blend mode will be allowed to be added to this batch + */ +PIXI.WebGLBatch.prototype.init = function(sprite) +{ + sprite.batch = this; + this.dirty = true; + this.blendMode = sprite.blendMode; + this.texture = sprite.texture.baseTexture; + this.head = sprite; + this.tail = sprite; + this.size = 1; + + this.growBatch(); +} + +/** + * inserts a sprite before the specified sprite + * + * @method insertBefore + * @param sprite {Sprite} the sprite to be added + * @param nextSprite {nextSprite} the first sprite will be inserted before this sprite + */ +PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) +{ + this.size++; + + sprite.batch = this; + this.dirty = true; + var tempPrev = nextSprite.__prev; + nextSprite.__prev = sprite; + sprite.__next = nextSprite; + + if(tempPrev) + { + sprite.__prev = tempPrev; + tempPrev.__next = sprite; + } + else + { + this.head = sprite; + } +} + +/** + * inserts a sprite after the specified sprite + * + * @method insertAfter + * @param sprite {Sprite} the sprite to be added + * @param previousSprite {Sprite} the first sprite will be inserted after this sprite + */ +PIXI.WebGLBatch.prototype.insertAfter = function(sprite, previousSprite) +{ + this.size++; + + sprite.batch = this; + this.dirty = true; + + var tempNext = previousSprite.__next; + previousSprite.__next = sprite; + sprite.__prev = previousSprite; + + if(tempNext) + { + sprite.__next = tempNext; + tempNext.__prev = sprite; + } + else + { + this.tail = sprite + } +} + +/** + * removes a sprite from the batch + * + * @method remove + * @param sprite {Sprite} the sprite to be removed + */ +PIXI.WebGLBatch.prototype.remove = function(sprite) +{ + this.size--; + + if(this.size == 0) + { + sprite.batch = null; + sprite.__prev = null; + sprite.__next = null; + return; + } + + if(sprite.__prev) + { + sprite.__prev.__next = sprite.__next; + } + else + { + this.head = sprite.__next; + this.head.__prev = null; + } + + if(sprite.__next) + { + sprite.__next.__prev = sprite.__prev; + } + else + { + this.tail = sprite.__prev; + this.tail.__next = null + } + + sprite.batch = null; + sprite.__next = null; + sprite.__prev = null; + this.dirty = true; +} + +/** + * Splits the batch into two with the specified sprite being the start of the new batch. + * + * @method split + * @param sprite {Sprite} the sprite that indicates where the batch should be split + * @return {WebGLBatch} the new batch + */ +PIXI.WebGLBatch.prototype.split = function(sprite) +{ + this.dirty = true; + + var batch = new PIXI.WebGLBatch(this.gl); + batch.init(sprite); + batch.texture = this.texture; + batch.tail = this.tail; + + this.tail = sprite.__prev; + this.tail.__next = null; + + sprite.__prev = null; + // return a splite batch! + + // TODO this size is wrong! + // need to recalculate :/ problem with a linked list! + // unless it gets calculated in the "clean"? + + // need to loop through items as there is no way to know the length on a linked list :/ + var tempSize = 0; + while(sprite) + { + tempSize++; + sprite.batch = batch; + sprite = sprite.__next; + } + + batch.size = tempSize; + this.size -= tempSize; + + return batch; +} + +/** + * Merges two batchs together + * + * @method merge + * @param batch {WebGLBatch} the batch that will be merged + */ +PIXI.WebGLBatch.prototype.merge = function(batch) +{ + this.dirty = true; + + this.tail.__next = batch.head; + batch.head.__prev = this.tail; + + this.size += batch.size; + + this.tail = batch.tail; + + var sprite = batch.head; + while(sprite) + { + sprite.batch = this; + sprite = sprite.__next; + } +} + +/** + * Grows the size of the batch. As the elements in the batch cannot have a dynamic size this + * function is used to increase the size of the batch. It also creates a little extra room so + * that the batch does not need to be resized every time a sprite is added + * + * @method growBatch + */ +PIXI.WebGLBatch.prototype.growBatch = function() +{ + var gl = this.gl; + if( this.size == 1) + { + this.dynamicSize = 1; + } + else + { + this.dynamicSize = this.size * 1.5 + } + // grow verts + this.verticies = new Float32Array(this.dynamicSize * 8); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); + + this.uvs = new Float32Array( this.dynamicSize * 8 ); + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); + + this.dirtyUVS = true; + + this.colors = new Float32Array( this.dynamicSize * 4 ); + gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); + + this.dirtyColors = true; + + this.indices = new Uint16Array(this.dynamicSize * 6); + var length = this.indices.length/6; + + for (var i=0; i < length; i++) + { + var index2 = i * 6; + var index3 = i * 4; + this.indices[index2 + 0] = index3 + 0; + this.indices[index2 + 1] = index3 + 1; + this.indices[index2 + 2] = index3 + 2; + this.indices[index2 + 3] = index3 + 0; + this.indices[index2 + 4] = index3 + 2; + this.indices[index2 + 5] = index3 + 3; + }; + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); +} + +/** + * Refresh's all the data in the batch and sync's it with the webGL buffers + * + * @method refresh + */ +PIXI.WebGLBatch.prototype.refresh = function() +{ + var gl = this.gl; + + if (this.dynamicSize < this.size) + { + this.growBatch(); + } + + var indexRun = 0; + var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index; + var a, b, c, d, tx, ty; + + var displayObject = this.head; + + while(displayObject) + { + index = indexRun * 8; + + var texture = displayObject.texture; + + var frame = texture.frame; + var tw = texture.baseTexture.width; + var th = texture.baseTexture.height; + + this.uvs[index + 0] = frame.x / tw; + this.uvs[index +1] = frame.y / th; + + this.uvs[index +2] = (frame.x + frame.width) / tw; + this.uvs[index +3] = frame.y / th; + + this.uvs[index +4] = (frame.x + frame.width) / tw; + this.uvs[index +5] = (frame.y + frame.height) / th; + + this.uvs[index +6] = frame.x / tw; + this.uvs[index +7] = (frame.y + frame.height) / th; + + displayObject.updateFrame = false; + + colorIndex = indexRun * 4; + this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; + + displayObject = displayObject.__next; + + indexRun ++; + } + + this.dirtyUVS = true; + this.dirtyColors = true; +} + +/** + * Updates all the relevant geometry and uploads the data to the GPU + * + * @method update + */ +PIXI.WebGLBatch.prototype.update = function() +{ + var gl = this.gl; + var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index, index2, index3 + + var a, b, c, d, tx, ty; + + var indexRun = 0; + + var displayObject = this.head; + var verticies = this.verticies; + var uvs = this.uvs; + var colors = this.colors; + + while(displayObject) + { + if(displayObject.vcount === PIXI.visibleCount) + { + width = displayObject.texture.frame.width; + height = displayObject.texture.frame.height; + + // TODO trim?? + aX = displayObject.anchor.x;// - displayObject.texture.trim.x + aY = displayObject.anchor.y; //- displayObject.texture.trim.y + w0 = width * (1-aX); + w1 = width * -aX; + + h0 = height * (1-aY); + h1 = height * -aY; + + index = indexRun * 8; + + worldTransform = displayObject.worldTransform; + + a = worldTransform[0]; + b = worldTransform[3]; + c = worldTransform[1]; + d = worldTransform[4]; + tx = worldTransform[2]; + ty = worldTransform[5]; + + verticies[index + 0 ] = a * w1 + c * h1 + tx; + verticies[index + 1 ] = d * h1 + b * w1 + ty; + + verticies[index + 2 ] = a * w0 + c * h1 + tx; + verticies[index + 3 ] = d * h1 + b * w0 + ty; + + verticies[index + 4 ] = a * w0 + c * h0 + tx; + verticies[index + 5 ] = d * h0 + b * w0 + ty; + + verticies[index + 6] = a * w1 + c * h0 + tx; + verticies[index + 7] = d * h0 + b * w1 + ty; + + if(displayObject.updateFrame || displayObject.texture.updateFrame) + { + this.dirtyUVS = true; + + var texture = displayObject.texture; + + var frame = texture.frame; + var tw = texture.baseTexture.width; + var th = texture.baseTexture.height; + + uvs[index + 0] = frame.x / tw; + uvs[index +1] = frame.y / th; + + uvs[index +2] = (frame.x + frame.width) / tw; + uvs[index +3] = frame.y / th; + + uvs[index +4] = (frame.x + frame.width) / tw; + uvs[index +5] = (frame.y + frame.height) / th; + + uvs[index +6] = frame.x / tw; + uvs[index +7] = (frame.y + frame.height) / th; + + displayObject.updateFrame = false; + } + + // TODO this probably could do with some optimisation.... + if(displayObject.cacheAlpha != displayObject.worldAlpha) + { + displayObject.cacheAlpha = displayObject.worldAlpha; + + var colorIndex = indexRun * 4; + colors[colorIndex] = colors[colorIndex + 1] = colors[colorIndex + 2] = colors[colorIndex + 3] = displayObject.worldAlpha; + this.dirtyColors = true; + } + } + else + { + index = indexRun * 8; + + verticies[index + 0 ] = verticies[index + 1 ] = verticies[index + 2 ] = verticies[index + 3 ] = verticies[index + 4 ] = verticies[index + 5 ] = verticies[index + 6] = verticies[index + 7] = 0; + } + + indexRun++; + displayObject = displayObject.__next; + } +} + +/** + * Draws the batch to the frame buffer + * + * @method render + */ +PIXI.WebGLBatch.prototype.render = function(start, end) +{ + start = start || 0; + + if(end == undefined)end = this.size; + + if(this.dirty) + { + this.refresh(); + this.dirty = false; + } + + if (this.size == 0)return; + + this.update(); + var gl = this.gl; + + //TODO optimize this! + + var shaderProgram = PIXI.currentShader; + + //gl.useProgram(shaderProgram); + + // update the verts.. + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + // ok.. + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) + gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + // update the uvs + //var isDefault = (shaderProgram == PIXI.shaderProgram) + + gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); + + if(this.dirtyUVS) + { + this.dirtyUVS = false; + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvs); + } + + gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, this.texture._glTexture); + + // update color! + gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); + + if(this.dirtyColors) + { + this.dirtyColors = false; + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.colors); + } + + gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); + // dont need to upload! + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + + var len = end - start; + + // DRAW THAT this! + gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * A WebGLBatch Enables a group of sprites to be drawn using the same settings. + * if a group of sprites all have the same baseTexture and blendMode then they can be + * grouped into a batch. All the sprites in a batch can then be drawn in one go by the + * GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch + * even if the batch only contains one sprite. Batching is handled automatically by the + * webGL renderer. A good tip is: the smaller the number of batchs there are, the faster + * the webGL renderer will run. + * + * @class WebGLBatch + * @contructor + * @param gl {WebGLContext} An instance of the webGL context + */ +PIXI.WebGLRenderGroup = function(gl) +{ + this.gl = gl; + this.root; + + this.backgroundColor; + this.batchs = []; + this.toRemove = []; +} + +// constructor +PIXI.WebGLRenderGroup.prototype.constructor = PIXI.WebGLRenderGroup; + +/** + * Add a display object to the webgl renderer + * + * @method setRenderable + * @param displayObject {DisplayObject} + * @private + */ +PIXI.WebGLRenderGroup.prototype.setRenderable = function(displayObject) +{ + // has this changed?? + if(this.root)this.removeDisplayObjectAndChildren(this.root); + + displayObject.worldVisible = displayObject.visible; + + // soooooo // + // to check if any batchs exist already?? + + // TODO what if its already has an object? should remove it + this.root = displayObject; + this.addDisplayObjectAndChildren(displayObject); +} + +/** + * Renders the stage to its webgl view + * + * @method render + * @param projection {Object} + */ +PIXI.WebGLRenderGroup.prototype.render = function(projection) +{ + PIXI.WebGLRenderer.updateTextures(); + + var gl = this.gl; + + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + // will render all the elements in the group + var renderable; + for (var i=0; i < this.batchs.length; i++) + { + + renderable = this.batchs[i]; + if(renderable instanceof PIXI.WebGLBatch) + { + this.batchs[i].render(); + continue; + } + + // non sprite batch.. + var worldVisible = renderable.vcount === PIXI.visibleCount; + + if(renderable instanceof PIXI.TilingSprite) + { + if(worldVisible)this.renderTilingSprite(renderable, projection); + } + else if(renderable instanceof PIXI.Strip) + { + if(worldVisible)this.renderStrip(renderable, projection); + } + else if(renderable instanceof PIXI.Graphics) + { + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); + } + else if(renderable instanceof PIXI.FilterBlock) + { + this.handleFilterBlock(renderable, projection); + } + } + +} + +/** + * Renders a specific displayObject + * + * @method renderSpecific + * @param displayObject {DisplayObject} + * @param projection {Object} + * @private + */ +PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection) +{ + PIXI.WebGLRenderer.updateTextures(); + + var gl = this.gl; + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + + // to do! + // render part of the scene... + + var startIndex; + var startBatchIndex; + + var endIndex; + var endBatchIndex; + + /* + * LOOK FOR THE NEXT SPRITE + * This part looks for the closest next sprite that can go into a batch + * it keeps looking until it finds a sprite or gets to the end of the display + * scene graph + */ + var nextRenderable = displayObject.first; + while(nextRenderable._iNext) + { + nextRenderable = nextRenderable._iNext; + if(nextRenderable.renderable && nextRenderable.__renderGroup)break; + } + var startBatch = nextRenderable.batch; + + if(nextRenderable instanceof PIXI.Sprite) + { + startBatch = nextRenderable.batch; + + var head = startBatch.head; + var next = head; + + // ok now we have the batch.. need to find the start index! + if(head == nextRenderable) + { + startIndex = 0; + } + else + { + startIndex = 1; + + while(head.__next != nextRenderable) + { + startIndex++; + head = head.__next; + } + } + } + else + { + startBatch = nextRenderable; + } + + // Get the LAST renderable object + var lastRenderable = displayObject; + var endBatch; + var lastItem = displayObject; + while(lastItem.children.length > 0) + { + lastItem = lastItem.children[lastItem.children.length-1]; + if(lastItem.renderable)lastRenderable = lastItem.last; + } + + if(lastRenderable instanceof PIXI.Sprite) + { + endBatch = lastRenderable.batch; + + var head = endBatch.head; + + if(head == lastRenderable) + { + endIndex = 0; + } + else + { + endIndex = 1; + + while(head.__next != lastRenderable) + { + endIndex++; + head = head.__next; + } + } + } + else + { + endBatch = lastRenderable; + } + + // TODO - need to fold this up a bit! + + if(startBatch == endBatch) + { + if(startBatch instanceof PIXI.WebGLBatch) + { + startBatch.render(startIndex, endIndex+1); + } + else + { + this.renderSpecial(startBatch, projection); + } + return; + } + + // now we have first and last! + startBatchIndex = this.batchs.indexOf(startBatch); + endBatchIndex = this.batchs.indexOf(endBatch); + + // DO the first batch + if(startBatch instanceof PIXI.WebGLBatch) + { + startBatch.render(startIndex); + } + else + { + this.renderSpecial(startBatch, projection); + } + + // DO the middle batchs.. + for (var i=startBatchIndex+1; i < endBatchIndex; i++) + { + renderable = this.batchs[i]; + + if(renderable instanceof PIXI.WebGLBatch) + { + this.batchs[i].render(); + } + else + { + this.renderSpecial(renderable, projection); + } + } + + // DO the last batch.. + if(endBatch instanceof PIXI.WebGLBatch) + { + endBatch.render(0, endIndex+1); + } + else + { + this.renderSpecial(endBatch, projection); + } +} + +/** + * Renders a specific renderable + * + * @method renderSpecial + * @param renderable {DisplayObject} + * @param projection {Object} + * @private + */ +PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) +{ + var sta = PIXI.shaderStack.length; + + var worldVisible = renderable.vcount === PIXI.visibleCount + + if(renderable instanceof PIXI.TilingSprite) + { + if(worldVisible)this.renderTilingSprite(renderable, projection); + } + else if(renderable instanceof PIXI.Strip) + { + if(worldVisible)this.renderStrip(renderable, projection); + } + else if(renderable instanceof PIXI.CustomRenderable) + { + if(worldVisible) renderable.renderWebGL(this, projection); + } + else if(renderable instanceof PIXI.Graphics) + { + if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); + } + else if(renderable instanceof PIXI.FilterBlock) + { + this.handleFilterBlock(renderable, projection); + } +} + +PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) +{ + /* + * for now only masks are supported.. + */ + var gl = PIXI.gl; + + if(renderable.open) + { + if(renderable.data instanceof Array) + { + var filter = renderable.data[0]; + + if(!filter.shader) + { + var shader = new PIXI.PixiShader(); + + shader.fragmentSrc = filter.fragmentSrc; + shader.uniforms = filter.uniforms; + shader.init(); + + filter.shader = shader + } + + PIXI.pushShader(filter.shader); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } + else + { + gl.enable(gl.STENCIL_TEST); + + gl.colorMask(false, false, false, false); + gl.stencilFunc(gl.ALWAYS,1,0xff); + gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); + PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.NOTEQUAL,0,0xff); + gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); + } + } + else + { + if(renderable.data instanceof Array) + { + PIXI.popShader(); + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + } + else + { + gl.disable(gl.STENCIL_TEST); + } + } +} + +/** + * Updates a webgl texture + * + * @method updateTexture + * @param displayObject {DisplayObject} + * @private + */ +PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject) +{ + + // TODO definitely can optimse this function.. + + this.removeObject(displayObject); + + /* + * LOOK FOR THE PREVIOUS RENDERABLE + * This part looks for the closest previous sprite that can go into a batch + * It keeps going back until it finds a sprite or the stage + */ + var previousRenderable = displayObject.first; + while(previousRenderable != this.root) + { + previousRenderable = previousRenderable._iPrev; + if(previousRenderable.renderable && previousRenderable.__renderGroup)break; + } + + /* + * LOOK FOR THE NEXT SPRITE + * This part looks for the closest next sprite that can go into a batch + * it keeps looking until it finds a sprite or gets to the end of the display + * scene graph + */ + var nextRenderable = displayObject.last; + while(nextRenderable._iNext) + { + nextRenderable = nextRenderable._iNext; + if(nextRenderable.renderable && nextRenderable.__renderGroup)break; + } + + this.insertObject(displayObject, previousRenderable, nextRenderable); +} + +/** + * Adds filter blocks + * + * @method addFilterBlocks + * @param start {FilterBlock} + * @param end {FilterBlock} + * @private + */ +PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) +{ + start.__renderGroup = this; + end.__renderGroup = this; + /* + * LOOK FOR THE PREVIOUS RENDERABLE + * This part looks for the closest previous sprite that can go into a batch + * It keeps going back until it finds a sprite or the stage + */ + var previousRenderable = start; + while(previousRenderable != this.root.first) + { + previousRenderable = previousRenderable._iPrev; + if(previousRenderable.renderable && previousRenderable.__renderGroup)break; + } + this.insertAfter(start, previousRenderable); + + /* + * LOOK FOR THE NEXT SPRITE + * This part looks for the closest next sprite that can go into a batch + * it keeps looking until it finds a sprite or gets to the end of the display + * scene graph + */ + var previousRenderable2 = end; + while(previousRenderable2 != this.root.first) + { + previousRenderable2 = previousRenderable2._iPrev; + if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; + } + this.insertAfter(end, previousRenderable2); +} + +/** + * Remove filter blocks + * + * @method removeFilterBlocks + * @param start {FilterBlock} + * @param end {FilterBlock} + * @private + */ +PIXI.WebGLRenderGroup.prototype.removeFilterBlocks = function(start, end) +{ + this.removeObject(start); + this.removeObject(end); +} + +/** + * Adds a display object and children to the webgl context + * + * @method addDisplayObjectAndChildren + * @param displayObject {DisplayObject} + * @private + */ +PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayObject) +{ + if(displayObject.__renderGroup)displayObject.__renderGroup.removeDisplayObjectAndChildren(displayObject); + + /* + * LOOK FOR THE PREVIOUS RENDERABLE + * This part looks for the closest previous sprite that can go into a batch + * It keeps going back until it finds a sprite or the stage + */ + + var previousRenderable = displayObject.first; + while(previousRenderable != this.root.first) + { + previousRenderable = previousRenderable._iPrev; + if(previousRenderable.renderable && previousRenderable.__renderGroup)break; + } + + /* + * LOOK FOR THE NEXT SPRITE + * This part looks for the closest next sprite that can go into a batch + * it keeps looking until it finds a sprite or gets to the end of the display + * scene graph + */ + var nextRenderable = displayObject.last; + while(nextRenderable._iNext) + { + nextRenderable = nextRenderable._iNext; + if(nextRenderable.renderable && nextRenderable.__renderGroup)break; + } + + // one the display object hits this. we can break the loop + + var tempObject = displayObject.first; + var testObject = displayObject.last._iNext; + do + { + tempObject.__renderGroup = this; + + if(tempObject.renderable) + { + + this.insertObject(tempObject, previousRenderable, nextRenderable); + previousRenderable = tempObject; + } + + tempObject = tempObject._iNext; + } + while(tempObject != testObject) +} + +/** + * Removes a display object and children to the webgl context + * + * @method removeDisplayObjectAndChildren + * @param displayObject {DisplayObject} + * @private + */ +PIXI.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren = function(displayObject) +{ + if(displayObject.__renderGroup != this)return; + +// var displayObject = displayObject.first; + var lastObject = displayObject.last; + do + { + displayObject.__renderGroup = null; + if(displayObject.renderable)this.removeObject(displayObject); + displayObject = displayObject._iNext; + } + while(displayObject) +} + +/** + * Inserts a displayObject into the linked list + * + * @method insertObject + * @param displayObject {DisplayObject} + * @param previousObject {DisplayObject} + * @param nextObject {DisplayObject} + * @private + */ +PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousObject, nextObject) +{ + // while looping below THE OBJECT MAY NOT HAVE BEEN ADDED + var previousSprite = previousObject; + var nextSprite = nextObject; + + /* + * so now we have the next renderable and the previous renderable + * + */ + if(displayObject instanceof PIXI.Sprite) + { + var previousBatch + var nextBatch + + if(previousSprite instanceof PIXI.Sprite) + { + previousBatch = previousSprite.batch; + if(previousBatch) + { + if(previousBatch.texture == displayObject.texture.baseTexture && previousBatch.blendMode == displayObject.blendMode) + { + previousBatch.insertAfter(displayObject, previousSprite); + return; + } + } + } + else + { + // TODO reword! + previousBatch = previousSprite; + } + + if(nextSprite) + { + if(nextSprite instanceof PIXI.Sprite) + { + nextBatch = nextSprite.batch; + + //batch may not exist if item was added to the display list but not to the webGL + if(nextBatch) + { + if(nextBatch.texture == displayObject.texture.baseTexture && nextBatch.blendMode == displayObject.blendMode) + { + nextBatch.insertBefore(displayObject, nextSprite); + return; + } + else + { + if(nextBatch == previousBatch) + { + // THERE IS A SPLIT IN THIS BATCH! // + var splitBatch = previousBatch.split(nextSprite); + // COOL! + // add it back into the array + /* + * OOPS! + * seems the new sprite is in the middle of a batch + * lets split it.. + */ + var batch = PIXI.WebGLRenderer.getBatch(); + + var index = this.batchs.indexOf( previousBatch ); + batch.init(displayObject); + this.batchs.splice(index+1, 0, batch, splitBatch); + + return; + } + } + } + } + else + { + // TODO re-word! + + nextBatch = nextSprite; + } + } + + /* + * looks like it does not belong to any batch! + * but is also not intersecting one.. + * time to create anew one! + */ + + var batch = PIXI.WebGLRenderer.getBatch(); + batch.init(displayObject); + + if(previousBatch) // if this is invalid it means + { + var index = this.batchs.indexOf( previousBatch ); + this.batchs.splice(index+1, 0, batch); + } + else + { + this.batchs.push(batch); + } + + return; + } + else if(displayObject instanceof PIXI.TilingSprite) + { + + // add to a batch!! + this.initTilingSprite(displayObject); + // this.batchs.push(displayObject); + + } + else if(displayObject instanceof PIXI.Strip) + { + // add to a batch!! + this.initStrip(displayObject); + // this.batchs.push(displayObject); + } + else if(displayObject)// instanceof PIXI.Graphics) + { + //displayObject.initWebGL(this); + + // add to a batch!! + //this.initStrip(displayObject); + //this.batchs.push(displayObject); + } + + this.insertAfter(displayObject, previousSprite); + + // insert and SPLIT! + +} + +/** + * Inserts a displayObject into the linked list + * + * @method insertAfter + * @param item {DisplayObject} + * @param displayObject {DisplayObject} The object to insert + * @private + */ +PIXI.WebGLRenderGroup.prototype.insertAfter = function(item, displayObject) +{ + if(displayObject instanceof PIXI.Sprite) + { + var previousBatch = displayObject.batch; + + if(previousBatch) + { + // so this object is in a batch! + + // is it not? need to split the batch + if(previousBatch.tail == displayObject) + { + // is it tail? insert in to batchs + var index = this.batchs.indexOf( previousBatch ); + this.batchs.splice(index+1, 0, item); + } + else + { + // TODO MODIFY ADD / REMOVE CHILD TO ACCOUNT FOR FILTERS (also get prev and next) // + + // THERE IS A SPLIT IN THIS BATCH! // + var splitBatch = previousBatch.split(displayObject.__next); + + // COOL! + // add it back into the array + /* + * OOPS! + * seems the new sprite is in the middle of a batch + * lets split it.. + */ + var index = this.batchs.indexOf( previousBatch ); + this.batchs.splice(index+1, 0, item, splitBatch); + } + } + else + { + this.batchs.push(item); + } + } + else + { + var index = this.batchs.indexOf( displayObject ); + this.batchs.splice(index+1, 0, item); + } +} + +/** + * Removes a displayObject from the linked list + * + * @method removeObject + * @param displayObject {DisplayObject} The object to remove + * @private + */ +PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) +{ + // loop through children.. + // display object // + + // add a child from the render group.. + // remove it and all its children! + //displayObject.cacheVisible = false;//displayObject.visible; + + /* + * removing is a lot quicker.. + * + */ + var batchToRemove; + + if(displayObject instanceof PIXI.Sprite) + { + // should always have a batch! + var batch = displayObject.batch; + if(!batch)return; // this means the display list has been altered befre rendering + + batch.remove(displayObject); + + if(batch.size==0) + { + batchToRemove = batch; + } + } + else + { + batchToRemove = displayObject; + } + + /* + * Looks like there is somthing that needs removing! + */ + if(batchToRemove) + { + var index = this.batchs.indexOf( batchToRemove ); + if(index == -1)return;// this means it was added then removed before rendered + + // ok so.. check to see if you adjacent batchs should be joined. + // TODO may optimise? + if(index == 0 || index == this.batchs.length-1) + { + // wha - eva! just get of the empty batch! + this.batchs.splice(index, 1); + if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); + + return; + } + + if(this.batchs[index-1] instanceof PIXI.WebGLBatch && this.batchs[index+1] instanceof PIXI.WebGLBatch) + { + if(this.batchs[index-1].texture == this.batchs[index+1].texture && this.batchs[index-1].blendMode == this.batchs[index+1].blendMode) + { + //console.log("MERGE") + this.batchs[index-1].merge(this.batchs[index+1]); + + if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); + PIXI.WebGLRenderer.returnBatch(this.batchs[index+1]); + this.batchs.splice(index, 2); + return; + } + } + + this.batchs.splice(index, 1); + if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); + } +} + + +/** + * Initializes a tiling sprite + * + * @method initTilingSprite + * @param sprite {TilingSprite} The tiling sprite to initialize + * @private + */ +PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) +{ + var gl = this.gl; + + // make the texture tilable.. + + sprite.verticies = new Float32Array([0, 0, + sprite.width, 0, + sprite.width, sprite.height, + 0, sprite.height]); + + sprite.uvs = new Float32Array([0, 0, + 1, 0, + 1, 1, + 0, 1]); + + sprite.colors = new Float32Array([1,1,1,1]); + + sprite.indices = new Uint16Array([0, 1, 3,2])//, 2]); + + sprite._vertexBuffer = gl.createBuffer(); + sprite._indexBuffer = gl.createBuffer(); + sprite._uvBuffer = gl.createBuffer(); + sprite._colorBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, sprite._vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, sprite.verticies, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, sprite.uvs, gl.DYNAMIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, sprite._colorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, sprite.colors, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sprite._indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sprite.indices, gl.STATIC_DRAW); + +// return ( (x > 0) && ((x & (x - 1)) == 0) ); + + if(sprite.texture.baseTexture._glTexture) + { + gl.bindTexture(gl.TEXTURE_2D, sprite.texture.baseTexture._glTexture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); + sprite.texture.baseTexture._powerOf2 = true; + } + else + { + sprite.texture.baseTexture._powerOf2 = true; + } +} + +/** + * Renders a Strip + * + * @method renderStrip + * @param strip {Strip} The strip to render + * @param projection {Object} + * @private + */ +PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) +{ + var gl = this.gl; + var shaderProgram = PIXI.stripShaderProgram; + + + gl.useProgram(shaderProgram); + + var m = PIXI.mat3.clone(strip.worldTransform); + + PIXI.mat3.transpose(m); + + // set the matrix transform for the + gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); + gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); + gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); + +/* + if(strip.blendMode == PIXI.blendModes.NORMAL) + { + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + } + else + { + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR); + } + */ + + + if(!strip.dirty) + { + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); + gl.bufferSubData(gl.ARRAY_BUFFER, 0, strip.verticies) + gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + + // update the uvs + gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); + gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); + gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); + + // dont need to upload! + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); + } + else + { + strip.dirty = false; + gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.STATIC_DRAW) + gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + + // update the uvs + gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW) + gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW) + gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); + + // dont need to upload! + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); + + } + + gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); + + gl.useProgram(PIXI.currentProgram); +} + +/** + * Renders a TilingSprite + * + * @method renderTilingSprite + * @param sprite {TilingSprite} The tiling sprite to render + * @param projectionMatrix {Object} + * @private + */ +PIXI.WebGLRenderGroup.prototype.renderTilingSprite = function(sprite, projectionMatrix) +{ + var gl = this.gl; + var shaderProgram = PIXI.shaderProgram; + + var tilePosition = sprite.tilePosition; + var tileScale = sprite.tileScale; + + var offsetX = tilePosition.x/sprite.texture.baseTexture.width; + var offsetY = tilePosition.y/sprite.texture.baseTexture.height; + + var scaleX = (sprite.width / sprite.texture.baseTexture.width) / tileScale.x; + var scaleY = (sprite.height / sprite.texture.baseTexture.height) / tileScale.y; + + sprite.uvs[0] = 0 - offsetX; + sprite.uvs[1] = 0 - offsetY; + + sprite.uvs[2] = (1 * scaleX) -offsetX; + sprite.uvs[3] = 0 - offsetY; + + sprite.uvs[4] = (1 *scaleX) - offsetX; + sprite.uvs[5] = (1 *scaleY) - offsetY; + + sprite.uvs[6] = 0 - offsetX; + sprite.uvs[7] = (1 *scaleY) - offsetY; + + gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); + gl.bufferSubData(gl.ARRAY_BUFFER, 0, sprite.uvs) + + this.renderStrip(sprite, projectionMatrix); +} + +/** + * Initializes a strip to be rendered + * + * @method initStrip + * @param strip {Strip} The strip to initialize + * @private + */ +PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) +{ + // build the strip! + var gl = this.gl; + var shaderProgram = this.shaderProgram; + + strip._vertexBuffer = gl.createBuffer(); + strip._indexBuffer = gl.createBuffer(); + strip._uvBuffer = gl.createBuffer(); + strip._colorBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.DYNAMIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); + gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW); + + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); +} + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * the CanvasRenderer draws the stage and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. + * Dont forget to add the view to your DOM or you will not see anything :) + * + * @class CanvasRenderer + * @constructor + * @param width=0 {Number} the width of the canvas view + * @param height=0 {Number} the height of the canvas view + * @param view {Canvas} the canvas to use as a view, optional + * @param transparent=false {Boolean} the transparency of the render view, default false + */ +PIXI.CanvasRenderer = function(width, height, view, transparent) +{ + this.transparent = transparent; + + /** + * The width of the canvas view + * + * @property width + * @type Number + * @default 800 + */ + this.width = width || 800; + + /** + * The height of the canvas view + * + * @property height + * @type Number + * @default 600 + */ + this.height = height || 600; + + /** + * The canvas element that the everything is drawn to + * + * @property view + * @type Canvas + */ + this.view = view || document.createElement( 'canvas' ); + + /** + * The canvas context that the everything is drawn to + * @property context + * @type Canvas 2d Context + */ + this.context = this.view.getContext("2d"); + + this.refresh = true; + // hack to enable some hardware acceleration! + //this.view.style["transform"] = "translatez(0)"; + + this.view.width = this.width; + this.view.height = this.height; + this.count = 0; +} + +// constructor +PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; + +/** + * Renders the stage to its canvas view + * + * @method render + * @param stage {Stage} the Stage element to be rendered + */ +PIXI.CanvasRenderer.prototype.render = function(stage) +{ + + //stage.__childrenAdded = []; + //stage.__childrenRemoved = []; + + // update textures if need be + PIXI.texturesToUpdate = []; + PIXI.texturesToDestroy = []; + + PIXI.visibleCount++; + stage.updateTransform(); + + // update the background color + if(this.view.style.backgroundColor!=stage.backgroundColorString && !this.transparent)this.view.style.backgroundColor = stage.backgroundColorString; + + this.context.setTransform(1,0,0,1,0,0); + this.context.clearRect(0, 0, this.width, this.height) + this.renderDisplayObject(stage); + //as + + // run interaction! + if(stage.interactive) + { + //need to add some events! + if(!stage._interactiveEventsAdded) + { + stage._interactiveEventsAdded = true; + stage.interactionManager.setTarget(this); + } + } + + // remove frame updates.. + if(PIXI.Texture.frameUpdates.length > 0) + { + PIXI.Texture.frameUpdates = []; + } + + +} + +/** + * resizes the canvas view to the specified width and height + * + * @method resize + * @param width {Number} the new width of the canvas view + * @param height {Number} the new height of the canvas view + */ +PIXI.CanvasRenderer.prototype.resize = function(width, height) +{ + this.width = width; + this.height = height; + + this.view.width = width; + this.view.height = height; +} + +/** + * Renders a display object + * + * @method renderDisplayObject + * @param displayObject {DisplayObject} The displayObject to render + * @private + */ +PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) +{ + // no loger recurrsive! + var transform; + var context = this.context; + + context.globalCompositeOperation = 'source-over'; + + // one the display object hits this. we can break the loop + var testObject = displayObject.last._iNext; + displayObject = displayObject.first; + + do + { + transform = displayObject.worldTransform; + + if(!displayObject.visible) + { + displayObject = displayObject.last._iNext; + continue; + } + + if(!displayObject.renderable) + { + displayObject = displayObject._iNext; + continue; + } + + if(displayObject instanceof PIXI.Sprite) + { + + var frame = displayObject.texture.frame; + + if(frame && frame.width && frame.height) + { + context.globalAlpha = displayObject.worldAlpha; + + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); + + context.drawImage(displayObject.texture.baseTexture.source, + frame.x, + frame.y, + frame.width, + frame.height, + (displayObject.anchor.x) * -frame.width, + (displayObject.anchor.y) * -frame.height, + frame.width, + frame.height); + } + } + else if(displayObject instanceof PIXI.Strip) + { + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) + this.renderStrip(displayObject); + } + else if(displayObject instanceof PIXI.TilingSprite) + { + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) + this.renderTilingSprite(displayObject); + } + else if(displayObject instanceof PIXI.CustomRenderable) + { + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); + displayObject.renderCanvas(this); + } + else if(displayObject instanceof PIXI.Graphics) + { + context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) + PIXI.CanvasGraphics.renderGraphics(displayObject, context); + } + else if(displayObject instanceof PIXI.FilterBlock) + { + if(displayObject.data instanceof PIXI.Graphics) + { + var mask = displayObject.data; + + if(displayObject.open) + { + context.save(); + + var cacheAlpha = mask.alpha; + var maskTransform = mask.worldTransform; + + context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) + + mask.worldAlpha = 0.5; + + context.worldAlpha = 0; + + PIXI.CanvasGraphics.renderGraphicsMask(mask, context); + context.clip(); + + mask.worldAlpha = cacheAlpha; + } + else + { + context.restore(); + } + } + else + { + // only masks supported right now! + } + } + // count++ + displayObject = displayObject._iNext; + + + } + while(displayObject != testObject) + + +} + +/** + * Renders a flat strip + * + * @method renderStripFlat + * @param strip {Strip} The Strip to render + * @private + */ +PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip) +{ + var context = this.context; + var verticies = strip.verticies; + var uvs = strip.uvs; + + var length = verticies.length/2; + this.count++; + + context.beginPath(); + for (var i=1; i < length-2; i++) + { + + // draw some triangles! + var index = i*2; + + var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; + var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + + }; + + context.fillStyle = "#FF0000"; + context.fill(); + context.closePath(); +} + +/** + * Renders a tiling sprite + * + * @method renderTilingSprite + * @param sprite {TilingSprite} The tilingsprite to render + * @private + */ +PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) +{ + var context = this.context; + + context.globalAlpha = sprite.worldAlpha; + + if(!sprite.__tilePattern) sprite.__tilePattern = context.createPattern(sprite.texture.baseTexture.source, "repeat"); + + context.beginPath(); + + var tilePosition = sprite.tilePosition; + var tileScale = sprite.tileScale; + + // offset + context.scale(tileScale.x,tileScale.y); + context.translate(tilePosition.x, tilePosition.y); + + context.fillStyle = sprite.__tilePattern; + context.fillRect(-tilePosition.x,-tilePosition.y,sprite.width / tileScale.x, sprite.height / tileScale.y); + + context.scale(1/tileScale.x, 1/tileScale.y); + context.translate(-tilePosition.x, -tilePosition.y); + + context.closePath(); +} + +/** + * Renders a strip + * + * @method renderStrip + * @param strip {Strip} The Strip to render + * @private + */ +PIXI.CanvasRenderer.prototype.renderStrip = function(strip) +{ + var context = this.context; + + // draw triangles!! + var verticies = strip.verticies; + var uvs = strip.uvs; + + var length = verticies.length/2; + this.count++; + for (var i=1; i < length-2; i++) + { + + // draw some triangles! + var index = i*2; + + var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; + var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; + + var u0 = uvs[index] * strip.texture.width, u1 = uvs[index+2] * strip.texture.width, u2 = uvs[index+4]* strip.texture.width; + var v0 = uvs[index+1]* strip.texture.height, v1 = uvs[index+3] * strip.texture.height, v2 = uvs[index+5]* strip.texture.height; + + + 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 delta_a = x0*v1 + v0*x2 + x1*v2 - v1*x2 - v0*x1 - x0*v2; + var delta_b = u0*x1 + x0*u2 + u1*x2 - x1*u2 - x0*u1 - u0*x2; + var delta_c = u0*v1*x2 + v0*x1*u2 + x0*u1*v2 - x0*v1*u2 - v0*u1*x2 - u0*x1*v2; + var delta_d = y0*v1 + v0*y2 + y1*v2 - v1*y2 - v0*y1 - y0*v2; + var delta_e = u0*y1 + y0*u2 + u1*y2 - y1*u2 - y0*u1 - u0*y2; + var delta_f = u0*v1*y2 + v0*y1*u2 + y0*u1*v2 - y0*v1*u2 - v0*u1*y2 - u0*y1*v2; + + + + + context.transform(delta_a/delta, delta_d/delta, + delta_b/delta, delta_e/delta, + delta_c/delta, delta_f/delta); + + context.drawImage(strip.texture.baseTexture.source, 0, 0); + context.restore(); + }; + +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * A set of functions used by the canvas renderer to draw the primitive graphics data + * + * @class CanvasGraphics + */ +PIXI.CanvasGraphics = function() +{ + +} + + +/* + * Renders the graphics object + * + * @static + * @private + * @method renderGraphics + * @param graphics {Graphics} + * @param context {Context2D} + */ +PIXI.CanvasGraphics.renderGraphics = function(graphics, context) +{ + var worldAlpha = graphics.worldAlpha; + + for (var i=0; i < graphics.graphicsData.length; i++) + { + var data = graphics.graphicsData[i]; + var points = data.points; + + context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); + + context.lineWidth = data.lineWidth; + + if(data.type == PIXI.Graphics.POLY) + { + context.beginPath(); + + context.moveTo(points[0], points[1]); + + for (var j=1; j < points.length/2; j++) + { + context.lineTo(points[j * 2], points[j * 2 + 1]); + } + + // if the first and last point are the same close the path - much neater :) + if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) + { + context.closePath(); + } + + if(data.fill) + { + context.globalAlpha = data.fillAlpha * worldAlpha; + context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); + context.fill(); + } + if(data.lineWidth) + { + context.globalAlpha = data.lineAlpha * worldAlpha; + context.stroke(); + } + } + else if(data.type == PIXI.Graphics.RECT) + { + + if(data.fillColor || data.fillColor === 0) + { + context.globalAlpha = data.fillAlpha * worldAlpha; + context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); + context.fillRect(points[0], points[1], points[2], points[3]); + + } + if(data.lineWidth) + { + context.globalAlpha = data.lineAlpha * worldAlpha; + context.strokeRect(points[0], points[1], points[2], points[3]); + } + + } + else if(data.type == PIXI.Graphics.CIRC) + { + // TODO - need to be Undefined! + context.beginPath(); + context.arc(points[0], points[1], points[2],0,2*Math.PI); + context.closePath(); + + if(data.fill) + { + context.globalAlpha = data.fillAlpha * worldAlpha; + context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); + context.fill(); + } + if(data.lineWidth) + { + context.globalAlpha = data.lineAlpha * worldAlpha; + context.stroke(); + } + } + else if(data.type == PIXI.Graphics.ELIP) + { + + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas + + var elipseData = data.points; + + var w = elipseData[2] * 2; + var h = elipseData[3] * 2; + + var x = elipseData[0] - w/2; + var y = elipseData[1] - h/2; + + context.beginPath(); + + var kappa = .5522848, + ox = (w / 2) * kappa, // control point offset horizontal + oy = (h / 2) * kappa, // control point offset vertical + xe = x + w, // x-end + ye = y + h, // y-end + xm = x + w / 2, // x-middle + ym = y + h / 2; // y-middle + + context.moveTo(x, ym); + context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); + context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); + context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); + context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); + + context.closePath(); + + if(data.fill) + { + context.globalAlpha = data.fillAlpha * worldAlpha; + context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); + context.fill(); + } + if(data.lineWidth) + { + context.globalAlpha = data.lineAlpha * worldAlpha; + context.stroke(); + } + } + + }; +} + +/* + * Renders a graphics mask + * + * @static + * @private + * @method renderGraphicsMask + * @param graphics {Graphics} + * @param context {Context2D} + */ +PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) +{ + var worldAlpha = graphics.worldAlpha; + + var len = graphics.graphicsData.length; + if(len > 1) + { + len = 1; + console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") + } + + for (var i=0; i < 1; i++) + { + var data = graphics.graphicsData[i]; + var points = data.points; + + if(data.type == PIXI.Graphics.POLY) + { + context.beginPath(); + context.moveTo(points[0], points[1]); + + for (var j=1; j < points.length/2; j++) + { + context.lineTo(points[j * 2], points[j * 2 + 1]); + } + + // if the first and last point are the same close the path - much neater :) + if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) + { + context.closePath(); + } + + } + else if(data.type == PIXI.Graphics.RECT) + { + context.beginPath(); + context.rect(points[0], points[1], points[2], points[3]); + context.closePath(); + } + else if(data.type == PIXI.Graphics.CIRC) + { + // TODO - need to be Undefined! + context.beginPath(); + context.arc(points[0], points[1], points[2],0,2*Math.PI); + context.closePath(); + } + else if(data.type == PIXI.Graphics.ELIP) + { + + // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas + var elipseData = data.points; + + var w = elipseData[2] * 2; + var h = elipseData[3] * 2; + + var x = elipseData[0] - w/2; + var y = elipseData[1] - h/2; + + context.beginPath(); + + var kappa = .5522848, + ox = (w / 2) * kappa, // control point offset horizontal + oy = (h / 2) * kappa, // control point offset vertical + xe = x + w, // x-end + ye = y + h, // y-end + xm = x + w / 2, // x-middle + ym = y + h / 2; // y-middle + + context.moveTo(x, ym); + context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); + context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); + context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); + context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); + context.closePath(); + } + + + }; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. + * It is important to know that with the webGL renderer only simple polys can be filled at this stage + * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png + * + * @class Graphics + * @extends DisplayObjectContainer + * @constructor + */ +PIXI.Graphics = function() +{ + PIXI.DisplayObjectContainer.call( this ); + + this.renderable = true; + + /** + * The alpha of the fill of this graphics object + * + * @property fillAlpha + * @type Number + */ + this.fillAlpha = 1; + + /** + * The width of any lines drawn + * + * @property lineWidth + * @type Number + */ + this.lineWidth = 0; + + /** + * The color of any lines drawn + * + * @property lineColor + * @type String + */ + this.lineColor = "black"; + + /** + * Graphics data + * + * @property graphicsData + * @type Array + * @private + */ + this.graphicsData = []; + + /** + * Current path + * + * @property currentPath + * @type Object + * @private + */ + this.currentPath = {points:[]}; +} + +// constructor +PIXI.Graphics.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); +PIXI.Graphics.prototype.constructor = PIXI.Graphics; + +/** + * Specifies a line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method. + * + * @method lineStyle + * @param lineWidth {Number} width of the line to draw, will update the object's stored style + * @param color {Number} color of the line to draw, will update the object's stored style + * @param alpha {Number} alpha of the line to draw, will update the object's stored style + */ +PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) +{ + if(this.currentPath.points.length == 0)this.graphicsData.pop(); + + this.lineWidth = lineWidth || 0; + this.lineColor = color || 0; + this.lineAlpha = (alpha == undefined) ? 1 : alpha; + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; + + this.graphicsData.push(this.currentPath); +} + +/** + * Moves the current drawing position to (x, y). + * + * @method moveTo + * @param x {Number} the X coord to move to + * @param y {Number} the Y coord to move to + */ +PIXI.Graphics.prototype.moveTo = function(x, y) +{ + if(this.currentPath.points.length == 0)this.graphicsData.pop(); + + this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; + + this.currentPath.points.push(x, y); + + this.graphicsData.push(this.currentPath); +} + +/** + * Draws a line using the current line style from the current drawing position to (x, y); + * the current drawing position is then set to (x, y). + * + * @method lineTo + * @param x {Number} the X coord to draw to + * @param y {Number} the Y coord to draw to + */ +PIXI.Graphics.prototype.lineTo = function(x, y) +{ + this.currentPath.points.push(x, y); + this.dirty = true; +} + +/** + * Specifies a simple one-color fill that subsequent calls to other Graphics methods + * (such as lineTo() or drawCircle()) use when drawing. + * + * @method beginFill + * @param color {uint} the color of the fill + * @param alpha {Number} the alpha + */ +PIXI.Graphics.prototype.beginFill = function(color, alpha) +{ + this.filling = true; + this.fillColor = color || 0; + this.fillAlpha = (alpha == undefined) ? 1 : alpha; +} + +/** + * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. + * + * @method endFill + */ +PIXI.Graphics.prototype.endFill = function() +{ + this.filling = false; + this.fillColor = null; + this.fillAlpha = 1; +} + +/** + * @method drawRect + * + * @param x {Number} The X coord of the top-left of the rectangle + * @param y {Number} The Y coord of the top-left of the rectangle + * @param width {Number} The width of the rectangle + * @param height {Number} The height of the rectangle + */ +PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) +{ + if(this.currentPath.points.length == 0)this.graphicsData.pop(); + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + points:[x, y, width, height], type:PIXI.Graphics.RECT}; + + this.graphicsData.push(this.currentPath); + this.dirty = true; +} + +/** + * Draws a circle. + * + * @method drawCircle + * @param x {Number} The X coord of the center of the circle + * @param y {Number} The Y coord of the center of the circle + * @param radius {Number} The radius of the circle + */ +PIXI.Graphics.prototype.drawCircle = function( x, y, radius) +{ + if(this.currentPath.points.length == 0)this.graphicsData.pop(); + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; + + this.graphicsData.push(this.currentPath); + this.dirty = true; +} + +/** + * Draws an elipse. + * + * @method drawElipse + * @param x {Number} + * @param y {Number} + * @param width {Number} + * @param height {Number} + */ +PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) +{ + if(this.currentPath.points.length == 0)this.graphicsData.pop(); + + this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, + fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, + points:[x, y, width, height], type:PIXI.Graphics.ELIP}; + + this.graphicsData.push(this.currentPath); + this.dirty = true; +} + +/** + * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. + * + * @method clear + */ +PIXI.Graphics.prototype.clear = function() +{ + this.lineWidth = 0; + this.filling = false; + + this.dirty = true; + this.clearDirty = true; + this.graphicsData = []; +} + +// SOME TYPES: +PIXI.Graphics.POLY = 0; +PIXI.Graphics.RECT = 1; +PIXI.Graphics.CIRC = 2; +PIXI.Graphics.ELIP = 3; + +/** + * @author Mat Groves http://matgroves.com/ + */ + +PIXI.Strip = function(texture, width, height) +{ + PIXI.DisplayObjectContainer.call( this ); + this.texture = texture; + this.blendMode = PIXI.blendModes.NORMAL; + + try + { + this.uvs = new Float32Array([0, 1, + 1, 1, + 1, 0, 0,1]); + + this.verticies = new Float32Array([0, 0, + 0,0, + 0,0, 0, + 0, 0]); + + this.colors = new Float32Array([1, 1, 1, 1]); + + this.indices = new Uint16Array([0, 1, 2, 3]); + } + catch(error) + { + this.uvs = [0, 1, + 1, 1, + 1, 0, 0,1]; + + this.verticies = [0, 0, + 0,0, + 0,0, 0, + 0, 0]; + + this.colors = [1, 1, 1, 1]; + + this.indices = [0, 1, 2, 3]; + } + + + /* + this.uvs = new Float32Array() + this.verticies = new Float32Array() + this.colors = new Float32Array() + this.indices = new Uint16Array() +*/ + this.width = width; + this.height = height; + + // load the texture! + if(texture.baseTexture.hasLoaded) + { + this.width = this.texture.frame.width; + this.height = this.texture.frame.height; + this.updateFrame = true; + } + else + { + this.onTextureUpdateBind = this.onTextureUpdate.bind(this); + this.texture.addEventListener( 'update', this.onTextureUpdateBind ); + } + + this.renderable = true; +} + +// constructor +PIXI.Strip.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); +PIXI.Strip.prototype.constructor = PIXI.Strip; + +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; +} + +PIXI.Strip.prototype.onTextureUpdate = function(event) +{ + this.updateFrame = true; +} +// some helper functions.. + + +/** + * @author Mat Groves http://matgroves.com/ + */ + + +PIXI.Rope = function(texture, points) +{ + PIXI.Strip.call( this, texture ); + this.points = points; + + try + { + this.verticies = new Float32Array( points.length * 4); + this.uvs = new Float32Array( points.length * 4); + this.colors = new Float32Array( points.length * 2); + this.indices = new Uint16Array( points.length * 2); + } + catch(error) + { + this.verticies = verticies + + this.uvs = uvs + this.colors = colors + this.indices = indices + } + + this.refresh(); +} + + +// constructor +PIXI.Rope.prototype = Object.create( PIXI.Strip.prototype ); +PIXI.Rope.prototype.constructor = PIXI.Rope; + +PIXI.Rope.prototype.refresh = function() +{ + var points = this.points; + if(points.length < 1)return; + + var uvs = this.uvs + var indices = this.indices; + var colors = this.colors; + + var lastPoint = points[0]; + var nextPoint; + var perp = {x:0, y:0}; + var point = points[0]; + + this.count-=0.2; + + + uvs[0] = 0 + uvs[1] = 1 + uvs[2] = 0 + uvs[3] = 1 + + colors[0] = 1; + colors[1] = 1; + + indices[0] = 0; + indices[1] = 1; + + var total = points.length; + + for (var i = 1; i < total; i++) + { + + var point = points[i]; + var index = i * 4; + // time to do some smart drawing! + var 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; + } +} + +PIXI.Rope.prototype.updateTransform = function() +{ + + var points = this.points; + if(points.length < 1)return; + + var verticies = this.verticies + + var lastPoint = points[0]; + var nextPoint; + var perp = {x:0, y:0}; + var point = points[0]; + + this.count-=0.2; + + verticies[0] = point.x + perp.x + verticies[1] = point.y + perp.y //+ 200 + verticies[2] = point.x - perp.x + verticies[3] = point.y - perp.y//+200 + // time to do some smart drawing! + + var total = points.length; + + for (var i = 1; i < total; i++) + { + + var point = points[i]; + var 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; + + var ratio = (1 - (i / (total-1))) * 10; + if(ratio > 1)ratio = 1; + + var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); + var 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; + + verticies[index] = point.x + perp.x + verticies[index+1] = point.y + perp.y + verticies[index+2] = point.x - perp.x + verticies[index+3] = point.y - perp.y + + lastPoint = point; + } + + PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); +} + +PIXI.Rope.prototype.setTexture = function(texture) +{ + // stop current texture + this.texture = texture; + this.updateFrame = true; +} + + + + + +/** + * @author Mat Groves http://matgroves.com/ + */ + +/** + * A tiling sprite is a fast way of rendering a tiling image + * + * @class TilingSprite + * @extends DisplayObjectContainer + * @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.DisplayObjectContainer.call( this ); + + /** + * The texture that the sprite is using + * + * @property texture + * @type Texture + */ + this.texture = texture; + + /** + * The width of the tiling sprite + * + * @property width + * @type Number + */ + this.width = width; + + /** + * The height of the tiling sprite + * + * @property height + * @type Number + */ + this.height = height; + + /** + * The scaling of the image that is being tiled + * + * @property tileScale + * @type Point + */ + this.tileScale = 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); + + this.renderable = true; + + this.blendMode = PIXI.blendModes.NORMAL +} + +// constructor +PIXI.TilingSprite.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); +PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite; + +/** + * Sets the texture of the tiling sprite + * + * @method setTexture + * @param texture {Texture} The PIXI texture that is displayed by the sprite + */ +PIXI.TilingSprite.prototype.setTexture = function(texture) +{ + //TODO SET THE TEXTURES + //TODO VISIBILITY + + // stop current texture + this.texture = texture; + this.updateFrame = true; +} + +/** + * When the texture is updated, this event will fire to update the frame + * + * @method onTextureUpdate + * @param event + * @private + */ +PIXI.TilingSprite.prototype.onTextureUpdate = function(event) +{ + this.updateFrame = true; +} + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi + * + * Awesome JS run time provided by EsotericSoftware + * https://github.com/EsotericSoftware/spine-runtimes + * + */ + +/** + * 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)) { + continue; + } + var spriteName = attachment.rendererObject.name; + var sprite = this.createSprite(slot, attachment.rendererObject); + slot.currentSprite = sprite; + slot.currentSpriteName = spriteName; + slotContainer.addChild(sprite); + } +}; + +PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); +PIXI.Spine.prototype.constructor = PIXI.Spine; + +/* + * Updates the object transform for rendering + * + * @method updateTransform + * @private + */ +PIXI.Spine.prototype.updateTransform = function () { + this.lastTime = this.lastTime || Date.now(); + var timeDelta = (Date.now() - this.lastTime) * 0.001; + this.lastTime = Date.now(); + this.state.update(timeDelta); + 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 instanceof spine.RegionAttachment)) { + slotContainer.visible = false; + continue; + } + + 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.rendererObject); + slotContainer.addChild(sprite); + } + slot.currentSprite = slot.sprites[spriteName]; + slot.currentSpriteName = spriteName; + } + } + slotContainer.visible = true; + + 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 * Math.PI / 180); + } + + PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); +}; + + +PIXI.Spine.prototype.createSprite = function (slot, descriptor) { + var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; + var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); + sprite.scale = descriptor.scale; + sprite.rotation = descriptor.rotation; + sprite.anchor.x = sprite.anchor.y = 0.5; + + slot.sprites = slot.sprites || {}; + slot.sprites[descriptor.name] = sprite; + return sprite; +}; + +/* + * Awesome JS run time provided by EsotericSoftware + * + * https://github.com/EsotericSoftware/spine-runtimes + * + */ + +var spine = {}; + +spine.BoneData = function (name, parent) { + this.name = name; + this.parent = parent; +}; +spine.BoneData.prototype = { + length: 0, + x: 0, y: 0, + rotation: 0, + scaleX: 1, scaleY: 1 +}; + +spine.SlotData = function (name, boneData) { + this.name = name; + this.boneData = boneData; +}; +spine.SlotData.prototype = { + r: 1, g: 1, b: 1, a: 1, + attachmentName: null +}; + +spine.Bone = function (boneData, parent) { + this.data = boneData; + this.parent = parent; + this.setToSetupPose(); +}; +spine.Bone.yDown = false; +spine.Bone.prototype = { + x: 0, y: 0, + rotation: 0, + scaleX: 1, scaleY: 1, + m00: 0, m01: 0, worldX: 0, // a b x + m10: 0, m11: 0, worldY: 0, // c d y + worldRotation: 0, + worldScaleX: 1, worldScaleY: 1, + updateWorldTransform: function (flipX, flipY) { + var parent = this.parent; + if (parent != null) { + this.worldX = this.x * parent.m00 + this.y * parent.m01 + parent.worldX; + this.worldY = this.x * parent.m10 + this.y * parent.m11 + parent.worldY; + this.worldScaleX = parent.worldScaleX * this.scaleX; + this.worldScaleY = parent.worldScaleY * this.scaleY; + this.worldRotation = parent.worldRotation + this.rotation; + } else { + this.worldX = this.x; + this.worldY = this.y; + this.worldScaleX = this.scaleX; + this.worldScaleY = this.scaleY; + this.worldRotation = this.rotation; + } + var radians = this.worldRotation * Math.PI / 180; + var cos = Math.cos(radians); + var sin = Math.sin(radians); + this.m00 = cos * this.worldScaleX; + this.m10 = sin * this.worldScaleX; + this.m01 = -sin * this.worldScaleY; + this.m11 = cos * this.worldScaleY; + if (flipX) { + this.m00 = -this.m00; + this.m01 = -this.m01; + } + if (flipY) { + this.m10 = -this.m10; + this.m11 = -this.m11; + } + if (spine.Bone.yDown) { + this.m10 = -this.m10; + this.m11 = -this.m11; + } + }, + setToSetupPose: function () { + var data = this.data; + this.x = data.x; + this.y = data.y; + this.rotation = data.rotation; + this.scaleX = data.scaleX; + this.scaleY = data.scaleY; + } +}; + +spine.Slot = function (slotData, skeleton, bone) { + this.data = slotData; + this.skeleton = skeleton; + this.bone = bone; + this.setToSetupPose(); +}; +spine.Slot.prototype = { + r: 1, g: 1, b: 1, a: 1, + _attachmentTime: 0, + attachment: null, + setAttachment: function (attachment) { + this.attachment = attachment; + this._attachmentTime = this.skeleton.time; + }, + setAttachmentTime: function (time) { + this._attachmentTime = this.skeleton.time - time; + }, + getAttachmentTime: function () { + return this.skeleton.time - this._attachmentTime; + }, + setToSetupPose: function () { + var data = this.data; + this.r = data.r; + this.g = data.g; + this.b = data.b; + this.a = data.a; + + var slotDatas = this.skeleton.data.slots; + for (var i = 0, n = slotDatas.length; i < n; i++) { + if (slotDatas[i] == data) { + this.setAttachment(!data.attachmentName ? null : this.skeleton.getAttachmentBySlotIndex(i, data.attachmentName)); + break; + } + } + } +}; + +spine.Skin = function (name) { + this.name = name; + this.attachments = {}; +}; +spine.Skin.prototype = { + addAttachment: function (slotIndex, name, attachment) { + this.attachments[slotIndex + ":" + name] = attachment; + }, + getAttachment: function (slotIndex, name) { + return this.attachments[slotIndex + ":" + name]; + }, + _attachAll: function (skeleton, oldSkin) { + for (var key in oldSkin.attachments) { + var colon = key.indexOf(":"); + var slotIndex = parseInt(key.substring(0, colon)); + var name = key.substring(colon + 1); + var slot = skeleton.slots[slotIndex]; + if (slot.attachment && slot.attachment.name == name) { + var attachment = this.getAttachment(slotIndex, name); + if (attachment) slot.setAttachment(attachment); + } + } + } +}; + +spine.Animation = function (name, timelines, duration) { + this.name = name; + this.timelines = timelines; + this.duration = duration; +}; +spine.Animation.prototype = { + apply: function (skeleton, time, loop) { + if (loop && this.duration != 0) time %= this.duration; + var timelines = this.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, time, 1); + }, + mix: function (skeleton, time, loop, alpha) { + if (loop && this.duration != 0) time %= this.duration; + var timelines = this.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, time, alpha); + } +}; + +spine.binarySearch = function (values, target, step) { + var low = 0; + var high = Math.floor(values.length / step) - 2; + if (high == 0) return step; + var current = high >>> 1; + while (true) { + if (values[(current + 1) * step] <= target) + low = current + 1; + else + high = current; + if (low == high) return (low + 1) * step; + current = (low + high) >>> 1; + } +}; +spine.linearSearch = function (values, target, step) { + for (var i = 0, last = values.length - step; i <= last; i += step) + if (values[i] > target) return i; + return -1; +}; + +spine.Curves = function (frameCount) { + this.curves = []; // dfx, dfy, ddfx, ddfy, dddfx, dddfy, ... + this.curves.length = (frameCount - 1) * 6; +}; +spine.Curves.prototype = { + setLinear: function (frameIndex) { + this.curves[frameIndex * 6] = 0/*LINEAR*/; + }, + setStepped: function (frameIndex) { + this.curves[frameIndex * 6] = -1/*STEPPED*/; + }, + /** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next. + * cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of + * the difference between the keyframe's values. */ + setCurve: function (frameIndex, cx1, cy1, cx2, cy2) { + var subdiv_step = 1 / 10/*BEZIER_SEGMENTS*/; + var subdiv_step2 = subdiv_step * subdiv_step; + var subdiv_step3 = subdiv_step2 * subdiv_step; + var pre1 = 3 * subdiv_step; + var pre2 = 3 * subdiv_step2; + var pre4 = 6 * subdiv_step2; + var pre5 = 6 * subdiv_step3; + var tmp1x = -cx1 * 2 + cx2; + var tmp1y = -cy1 * 2 + cy2; + var tmp2x = (cx1 - cx2) * 3 + 1; + var tmp2y = (cy1 - cy2) * 3 + 1; + var i = frameIndex * 6; + var curves = this.curves; + curves[i] = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; + curves[i + 1] = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; + curves[i + 2] = tmp1x * pre4 + tmp2x * pre5; + curves[i + 3] = tmp1y * pre4 + tmp2y * pre5; + curves[i + 4] = tmp2x * pre5; + curves[i + 5] = tmp2y * pre5; + }, + getCurvePercent: function (frameIndex, percent) { + percent = percent < 0 ? 0 : (percent > 1 ? 1 : percent); + var curveIndex = frameIndex * 6; + var curves = this.curves; + var dfx = curves[curveIndex]; + if (!dfx/*LINEAR*/) return percent; + if (dfx == -1/*STEPPED*/) return 0; + var dfy = curves[curveIndex + 1]; + var ddfx = curves[curveIndex + 2]; + var ddfy = curves[curveIndex + 3]; + var dddfx = curves[curveIndex + 4]; + var dddfy = curves[curveIndex + 5]; + var x = dfx, y = dfy; + var i = 10/*BEZIER_SEGMENTS*/ - 2; + while (true) { + if (x >= percent) { + var lastX = x - dfx; + var lastY = y - dfy; + return lastY + (y - lastY) * (percent - lastX) / (x - lastX); + } + if (i == 0) break; + i--; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + x += dfx; + y += dfy; + } + return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1. + } +}; + +spine.RotateTimeline = function (frameCount) { + this.curves = new spine.Curves(frameCount); + this.frames = []; // time, angle, ... + this.frames.length = frameCount * 2; +}; +spine.RotateTimeline.prototype = { + boneIndex: 0, + getFrameCount: function () { + return this.frames.length / 2; + }, + setFrame: function (frameIndex, time, angle) { + frameIndex *= 2; + this.frames[frameIndex] = time; + this.frames[frameIndex + 1] = angle; + }, + apply: function (skeleton, time, alpha) { + var frames = this.frames; + if (time < frames[0]) return; // Time is before first frame. + + var bone = skeleton.bones[this.boneIndex]; + + if (time >= frames[frames.length - 2]) { // Time is after last frame. + var amount = bone.data.rotation + frames[frames.length - 1] - bone.rotation; + while (amount > 180) + amount -= 360; + while (amount < -180) + amount += 360; + bone.rotation += amount * alpha; + return; + } + + // Interpolate between the last frame and the current frame. + var frameIndex = spine.binarySearch(frames, time, 2); + var lastFrameValue = frames[frameIndex - 1]; + var frameTime = frames[frameIndex]; + var percent = 1 - (time - frameTime) / (frames[frameIndex - 2/*LAST_FRAME_TIME*/] - frameTime); + percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent); + + var amount = frames[frameIndex + 1/*FRAME_VALUE*/] - lastFrameValue; + while (amount > 180) + amount -= 360; + while (amount < -180) + amount += 360; + amount = bone.data.rotation + (lastFrameValue + amount * percent) - bone.rotation; + while (amount > 180) + amount -= 360; + while (amount < -180) + amount += 360; + bone.rotation += amount * alpha; + } +}; + +spine.TranslateTimeline = function (frameCount) { + this.curves = new spine.Curves(frameCount); + this.frames = []; // time, x, y, ... + this.frames.length = frameCount * 3; +}; +spine.TranslateTimeline.prototype = { + boneIndex: 0, + getFrameCount: function () { + return this.frames.length / 3; + }, + setFrame: function (frameIndex, time, x, y) { + frameIndex *= 3; + this.frames[frameIndex] = time; + this.frames[frameIndex + 1] = x; + this.frames[frameIndex + 2] = y; + }, + apply: function (skeleton, time, alpha) { + var frames = this.frames; + if (time < frames[0]) return; // Time is before first frame. + + var bone = skeleton.bones[this.boneIndex]; + + if (time >= frames[frames.length - 3]) { // Time is after last frame. + bone.x += (bone.data.x + frames[frames.length - 2] - bone.x) * alpha; + bone.y += (bone.data.y + frames[frames.length - 1] - bone.y) * alpha; + return; + } + + // Interpolate between the last frame and the current frame. + var frameIndex = spine.binarySearch(frames, time, 3); + var lastFrameX = frames[frameIndex - 2]; + var lastFrameY = frames[frameIndex - 1]; + var frameTime = frames[frameIndex]; + var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); + percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); + + bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; + bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; + } +}; + +spine.ScaleTimeline = function (frameCount) { + this.curves = new spine.Curves(frameCount); + this.frames = []; // time, x, y, ... + this.frames.length = frameCount * 3; +}; +spine.ScaleTimeline.prototype = { + boneIndex: 0, + getFrameCount: function () { + return this.frames.length / 3; + }, + setFrame: function (frameIndex, time, x, y) { + frameIndex *= 3; + this.frames[frameIndex] = time; + this.frames[frameIndex + 1] = x; + this.frames[frameIndex + 2] = y; + }, + apply: function (skeleton, time, alpha) { + var frames = this.frames; + if (time < frames[0]) return; // Time is before first frame. + + var bone = skeleton.bones[this.boneIndex]; + + if (time >= frames[frames.length - 3]) { // Time is after last frame. + bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; + return; + } + + // Interpolate between the last frame and the current frame. + var frameIndex = spine.binarySearch(frames, time, 3); + var lastFrameX = frames[frameIndex - 2]; + var lastFrameY = frames[frameIndex - 1]; + var frameTime = frames[frameIndex]; + var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); + percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); + + bone.scaleX += (bone.data.scaleX - 1 + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - 1 + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.scaleY) * alpha; + } +}; + +spine.ColorTimeline = function (frameCount) { + this.curves = new spine.Curves(frameCount); + this.frames = []; // time, r, g, b, a, ... + this.frames.length = frameCount * 5; +}; +spine.ColorTimeline.prototype = { + slotIndex: 0, + getFrameCount: function () { + return this.frames.length / 2; + }, + setFrame: function (frameIndex, time, x, y) { + frameIndex *= 5; + this.frames[frameIndex] = time; + this.frames[frameIndex + 1] = r; + this.frames[frameIndex + 2] = g; + this.frames[frameIndex + 3] = b; + this.frames[frameIndex + 4] = a; + }, + apply: function (skeleton, time, alpha) { + var frames = this.frames; + if (time < frames[0]) return; // Time is before first frame. + + var slot = skeleton.slots[this.slotIndex]; + + if (time >= frames[frames.length - 5]) { // Time is after last frame. + var i = frames.length - 1; + slot.r = frames[i - 3]; + slot.g = frames[i - 2]; + slot.b = frames[i - 1]; + slot.a = frames[i]; + return; + } + + // Interpolate between the last frame and the current frame. + var frameIndex = spine.binarySearch(frames, time, 5); + var lastFrameR = frames[frameIndex - 4]; + var lastFrameG = frames[frameIndex - 3]; + var lastFrameB = frames[frameIndex - 2]; + var lastFrameA = frames[frameIndex - 1]; + var frameTime = frames[frameIndex]; + var percent = 1 - (time - frameTime) / (frames[frameIndex - 5/*LAST_FRAME_TIME*/] - frameTime); + percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent); + + var r = lastFrameR + (frames[frameIndex + 1/*FRAME_R*/] - lastFrameR) * percent; + var g = lastFrameG + (frames[frameIndex + 2/*FRAME_G*/] - lastFrameG) * percent; + var b = lastFrameB + (frames[frameIndex + 3/*FRAME_B*/] - lastFrameB) * percent; + var a = lastFrameA + (frames[frameIndex + 4/*FRAME_A*/] - lastFrameA) * percent; + if (alpha < 1) { + slot.r += (r - slot.r) * alpha; + slot.g += (g - slot.g) * alpha; + slot.b += (b - slot.b) * alpha; + slot.a += (a - slot.a) * alpha; + } else { + slot.r = r; + slot.g = g; + slot.b = b; + slot.a = a; + } + } +}; + +spine.AttachmentTimeline = function (frameCount) { + this.curves = new spine.Curves(frameCount); + this.frames = []; // time, ... + this.frames.length = frameCount; + this.attachmentNames = []; // time, ... + this.attachmentNames.length = frameCount; +}; +spine.AttachmentTimeline.prototype = { + slotIndex: 0, + getFrameCount: function () { + return this.frames.length; + }, + setFrame: function (frameIndex, time, attachmentName) { + this.frames[frameIndex] = time; + this.attachmentNames[frameIndex] = attachmentName; + }, + apply: function (skeleton, time, alpha) { + var frames = this.frames; + if (time < frames[0]) return; // Time is before first frame. + + var frameIndex; + if (time >= frames[frames.length - 1]) // Time is after last frame. + frameIndex = frames.length - 1; + else + frameIndex = spine.binarySearch(frames, time, 1) - 1; + + var attachmentName = this.attachmentNames[frameIndex]; + skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); + } +}; + +spine.SkeletonData = function () { + this.bones = []; + this.slots = []; + this.skins = []; + this.animations = []; +}; +spine.SkeletonData.prototype = { + defaultSkin: null, + /** @return May be null. */ + findBone: function (boneName) { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].name == boneName) return bones[i]; + return null; + }, + /** @return -1 if the bone was not found. */ + findBoneIndex: function (boneName) { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].name == boneName) return i; + return -1; + }, + /** @return May be null. */ + findSlot: function (slotName) { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) { + if (slots[i].name == slotName) return slot[i]; + } + return null; + }, + /** @return -1 if the bone was not found. */ + findSlotIndex: function (slotName) { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].name == slotName) return i; + return -1; + }, + /** @return May be null. */ + findSkin: function (skinName) { + var skins = this.skins; + for (var i = 0, n = skins.length; i < n; i++) + if (skins[i].name == skinName) return skins[i]; + return null; + }, + /** @return May be null. */ + findAnimation: function (animationName) { + var animations = this.animations; + for (var i = 0, n = animations.length; i < n; i++) + if (animations[i].name == animationName) return animations[i]; + return null; + } +}; + +spine.Skeleton = function (skeletonData) { + this.data = skeletonData; + + this.bones = []; + for (var i = 0, n = skeletonData.bones.length; i < n; i++) { + var boneData = skeletonData.bones[i]; + var parent = !boneData.parent ? null : this.bones[skeletonData.bones.indexOf(boneData.parent)]; + this.bones.push(new spine.Bone(boneData, parent)); + } + + this.slots = []; + this.drawOrder = []; + for (var i = 0, n = skeletonData.slots.length; i < n; i++) { + var slotData = skeletonData.slots[i]; + var bone = this.bones[skeletonData.bones.indexOf(slotData.boneData)]; + var slot = new spine.Slot(slotData, this, bone); + this.slots.push(slot); + this.drawOrder.push(slot); + } +}; +spine.Skeleton.prototype = { + x: 0, y: 0, + skin: null, + r: 1, g: 1, b: 1, a: 1, + time: 0, + flipX: false, flipY: false, + /** Updates the world transform for each bone. */ + updateWorldTransform: function () { + var flipX = this.flipX; + var flipY = this.flipY; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + bones[i].updateWorldTransform(flipX, flipY); + }, + /** Sets the bones and slots to their setup pose values. */ + setToSetupPose: function () { + this.setBonesToSetupPose(); + this.setSlotsToSetupPose(); + }, + setBonesToSetupPose: function () { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + bones[i].setToSetupPose(); + }, + setSlotsToSetupPose: function () { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + slots[i].setToSetupPose(i); + }, + /** @return May return null. */ + getRootBone: function () { + return this.bones.length == 0 ? null : this.bones[0]; + }, + /** @return May be null. */ + findBone: function (boneName) { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].data.name == boneName) return bones[i]; + return null; + }, + /** @return -1 if the bone was not found. */ + findBoneIndex: function (boneName) { + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) + if (bones[i].data.name == boneName) return i; + return -1; + }, + /** @return May be null. */ + findSlot: function (slotName) { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].data.name == slotName) return slots[i]; + return null; + }, + /** @return -1 if the bone was not found. */ + findSlotIndex: function (slotName) { + var slots = this.slots; + for (var i = 0, n = slots.length; i < n; i++) + if (slots[i].data.name == slotName) return i; + return -1; + }, + setSkinByName: function (skinName) { + var skin = this.data.findSkin(skinName); + if (!skin) throw "Skin not found: " + skinName; + this.setSkin(skin); + }, + /** Sets the skin used to look up attachments not found in the {@link SkeletonData#getDefaultSkin() default skin}. Attachments + * from the new skin are attached if the corresponding attachment from the old skin was attached. + * @param newSkin May be null. */ + setSkin: function (newSkin) { + if (this.skin && newSkin) newSkin._attachAll(this, this.skin); + this.skin = newSkin; + }, + /** @return May be null. */ + getAttachmentBySlotName: function (slotName, attachmentName) { + return this.getAttachmentBySlotIndex(this.data.findSlotIndex(slotName), attachmentName); + }, + /** @return May be null. */ + getAttachmentBySlotIndex: function (slotIndex, attachmentName) { + if (this.skin) { + var attachment = this.skin.getAttachment(slotIndex, attachmentName); + if (attachment) return attachment; + } + if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); + return null; + }, + /** @param attachmentName May be null. */ + setAttachment: function (slotName, attachmentName) { + var slots = this.slots; + for (var i = 0, n = slots.size; i < n; i++) { + var slot = slots[i]; + if (slot.data.name == slotName) { + var attachment = null; + if (attachmentName) { + attachment = this.getAttachment(i, attachmentName); + if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; + } + slot.setAttachment(attachment); + return; + } + } + throw "Slot not found: " + slotName; + }, + update: function (delta) { + time += delta; + } +}; + +spine.AttachmentType = { + region: 0 +}; + +spine.RegionAttachment = function () { + this.offset = []; + this.offset.length = 8; + this.uvs = []; + this.uvs.length = 8; +}; +spine.RegionAttachment.prototype = { + x: 0, y: 0, + rotation: 0, + scaleX: 1, scaleY: 1, + width: 0, height: 0, + rendererObject: null, + regionOffsetX: 0, regionOffsetY: 0, + regionWidth: 0, regionHeight: 0, + regionOriginalWidth: 0, regionOriginalHeight: 0, + setUVs: function (u, v, u2, v2, rotate) { + var uvs = this.uvs; + if (rotate) { + uvs[2/*X2*/] = u; + uvs[3/*Y2*/] = v2; + uvs[4/*X3*/] = u; + uvs[5/*Y3*/] = v; + uvs[6/*X4*/] = u2; + uvs[7/*Y4*/] = v; + uvs[0/*X1*/] = u2; + uvs[1/*Y1*/] = v2; + } else { + uvs[0/*X1*/] = u; + uvs[1/*Y1*/] = v2; + uvs[2/*X2*/] = u; + uvs[3/*Y2*/] = v; + uvs[4/*X3*/] = u2; + uvs[5/*Y3*/] = v; + uvs[6/*X4*/] = u2; + uvs[7/*Y4*/] = v2; + } + }, + updateOffset: function () { + var regionScaleX = this.width / this.regionOriginalWidth * this.scaleX; + var regionScaleY = this.height / this.regionOriginalHeight * this.scaleY; + var localX = -this.width / 2 * this.scaleX + this.regionOffsetX * regionScaleX; + var localY = -this.height / 2 * this.scaleY + this.regionOffsetY * regionScaleY; + var localX2 = localX + this.regionWidth * regionScaleX; + var localY2 = localY + this.regionHeight * regionScaleY; + var radians = this.rotation * Math.PI / 180; + var cos = Math.cos(radians); + var sin = Math.sin(radians); + var localXCos = localX * cos + this.x; + var localXSin = localX * sin; + var localYCos = localY * cos + this.y; + var localYSin = localY * sin; + var localX2Cos = localX2 * cos + this.x; + var localX2Sin = localX2 * sin; + var localY2Cos = localY2 * cos + this.y; + var localY2Sin = localY2 * sin; + var offset = this.offset; + offset[0/*X1*/] = localXCos - localYSin; + offset[1/*Y1*/] = localYCos + localXSin; + offset[2/*X2*/] = localXCos - localY2Sin; + offset[3/*Y2*/] = localY2Cos + localXSin; + offset[4/*X3*/] = localX2Cos - localY2Sin; + offset[5/*Y3*/] = localY2Cos + localX2Sin; + offset[6/*X4*/] = localX2Cos - localYSin; + offset[7/*Y4*/] = localYCos + localX2Sin; + }, + computeVertices: function (x, y, bone, vertices) { + x += bone.worldX; + y += bone.worldY; + var m00 = bone.m00; + var m01 = bone.m01; + var m10 = bone.m10; + var m11 = bone.m11; + var offset = this.offset; + vertices[0/*X1*/] = offset[0/*X1*/] * m00 + offset[1/*Y1*/] * m01 + x; + vertices[1/*Y1*/] = offset[0/*X1*/] * m10 + offset[1/*Y1*/] * m11 + y; + vertices[2/*X2*/] = offset[2/*X2*/] * m00 + offset[3/*Y2*/] * m01 + x; + vertices[3/*Y2*/] = offset[2/*X2*/] * m10 + offset[3/*Y2*/] * m11 + y; + vertices[4/*X3*/] = offset[4/*X3*/] * m00 + offset[5/*X3*/] * m01 + x; + vertices[5/*X3*/] = offset[4/*X3*/] * m10 + offset[5/*X3*/] * m11 + y; + vertices[6/*X4*/] = offset[6/*X4*/] * m00 + offset[7/*Y4*/] * m01 + x; + vertices[7/*Y4*/] = offset[6/*X4*/] * m10 + offset[7/*Y4*/] * m11 + y; + } +} + +spine.AnimationStateData = function (skeletonData) { + this.skeletonData = skeletonData; + this.animationToMixTime = {}; +}; +spine.AnimationStateData.prototype = { + defaultMix: 0, + setMixByName: function (fromName, toName, duration) { + var from = this.skeletonData.findAnimation(fromName); + if (!from) throw "Animation not found: " + fromName; + var to = this.skeletonData.findAnimation(toName); + if (!to) throw "Animation not found: " + toName; + this.setMix(from, to, duration); + }, + setMix: function (from, to, duration) { + this.animationToMixTime[from.name + ":" + to.name] = duration; + }, + getMix: function (from, to) { + var time = this.animationToMixTime[from.name + ":" + to.name]; + return time ? time : this.defaultMix; + } +}; + +spine.AnimationState = function (stateData) { + this.data = stateData; + this.queue = []; +}; +spine.AnimationState.prototype = { + current: null, + previous: null, + currentTime: 0, + previousTime: 0, + currentLoop: false, + previousLoop: false, + mixTime: 0, + mixDuration: 0, + update: function (delta) { + this.currentTime += delta; + this.previousTime += delta; + this.mixTime += delta; + + if (this.queue.length > 0) { + var entry = this.queue[0]; + if (this.currentTime >= entry.delay) { + this._setAnimation(entry.animation, entry.loop); + this.queue.shift(); + } + } + }, + apply: function (skeleton) { + if (!this.current) return; + if (this.previous) { + this.previous.apply(skeleton, this.previousTime, this.previousLoop); + var alpha = this.mixTime / this.mixDuration; + if (alpha >= 1) { + alpha = 1; + this.previous = null; + } + this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); + } else + this.current.apply(skeleton, this.currentTime, this.currentLoop); + }, + clearAnimation: function () { + this.previous = null; + this.current = null; + this.queue.length = 0; + }, + _setAnimation: function (animation, loop) { + this.previous = null; + if (animation && this.current) { + this.mixDuration = this.data.getMix(this.current, animation); + if (this.mixDuration > 0) { + this.mixTime = 0; + this.previous = this.current; + this.previousTime = this.currentTime; + this.previousLoop = this.currentLoop; + } + } + this.current = animation; + this.currentLoop = loop; + this.currentTime = 0; + }, + /** @see #setAnimation(Animation, Boolean) */ + setAnimationByName: function (animationName, loop) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) throw "Animation not found: " + animationName; + this.setAnimation(animation, loop); + }, + /** Set the current animation. Any queued animations are cleared and the current animation time is set to 0. + * @param animation May be null. */ + setAnimation: function (animation, loop) { + this.queue.length = 0; + this._setAnimation(animation, loop); + }, + /** @see #addAnimation(Animation, Boolean, Number) */ + addAnimationByName: function (animationName, loop, delay) { + var animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) throw "Animation not found: " + animationName; + this.addAnimation(animation, loop, delay); + }, + /** Adds an animation to be played delay seconds after the current or last queued animation. + * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */ + addAnimation: function (animation, loop, delay) { + var entry = {}; + entry.animation = animation; + entry.loop = loop; + + if (!delay || delay <= 0) { + var previousAnimation = this.queue.length == 0 ? this.current : this.queue[this.queue.length - 1].animation; + if (previousAnimation != null) + delay = previousAnimation.duration - this.data.getMix(previousAnimation, animation) + (delay || 0); + else + delay = 0; + } + entry.delay = delay; + + this.queue.push(entry); + }, + /** Returns true if no animation is set or if the current time is greater than the animation duration, regardless of looping. */ + isComplete: function () { + return !this.current || this.currentTime >= this.current.duration; + } +}; + +spine.SkeletonJson = function (attachmentLoader) { + this.attachmentLoader = attachmentLoader; +}; +spine.SkeletonJson.prototype = { + scale: 1, + readSkeletonData: function (root) { + var skeletonData = new spine.SkeletonData(); + + // Bones. + var bones = root["bones"]; + for (var i = 0, n = bones.length; i < n; i++) { + var boneMap = bones[i]; + var parent = null; + if (boneMap["parent"]) { + parent = skeletonData.findBone(boneMap["parent"]); + if (!parent) throw "Parent bone not found: " + boneMap["parent"]; + } + var boneData = new spine.BoneData(boneMap["name"], parent); + boneData.length = (boneMap["length"] || 0) * this.scale; + boneData.x = (boneMap["x"] || 0) * this.scale; + boneData.y = (boneMap["y"] || 0) * this.scale; + boneData.rotation = (boneMap["rotation"] || 0); + boneData.scaleX = boneMap["scaleX"] || 1; + boneData.scaleY = boneMap["scaleY"] || 1; + skeletonData.bones.push(boneData); + } + + // Slots. + var slots = root["slots"]; + for (var i = 0, n = slots.length; i < n; i++) { + var slotMap = slots[i]; + var boneData = skeletonData.findBone(slotMap["bone"]); + if (!boneData) throw "Slot bone not found: " + slotMap["bone"]; + var slotData = new spine.SlotData(slotMap["name"], boneData); + + var color = slotMap["color"]; + if (color) { + slotData.r = spine.SkeletonJson.toColor(color, 0); + slotData.g = spine.SkeletonJson.toColor(color, 1); + slotData.b = spine.SkeletonJson.toColor(color, 2); + slotData.a = spine.SkeletonJson.toColor(color, 3); + } + + slotData.attachmentName = slotMap["attachment"]; + + skeletonData.slots.push(slotData); + } + + // Skins. + var skins = root["skins"]; + for (var skinName in skins) { + if (!skins.hasOwnProperty(skinName)) continue; + var skinMap = skins[skinName]; + var skin = new spine.Skin(skinName); + for (var slotName in skinMap) { + if (!skinMap.hasOwnProperty(slotName)) continue; + var slotIndex = skeletonData.findSlotIndex(slotName); + var slotEntry = skinMap[slotName]; + for (var attachmentName in slotEntry) { + if (!slotEntry.hasOwnProperty(attachmentName)) continue; + var attachment = this.readAttachment(skin, attachmentName, slotEntry[attachmentName]); + if (attachment != null) skin.addAttachment(slotIndex, attachmentName, attachment); + } + } + skeletonData.skins.push(skin); + if (skin.name == "default") skeletonData.defaultSkin = skin; + } + + // Animations. + var animations = root["animations"]; + for (var animationName in animations) { + if (!animations.hasOwnProperty(animationName)) continue; + this.readAnimation(animationName, animations[animationName], skeletonData); + } + + return skeletonData; + }, + readAttachment: function (skin, name, map) { + name = map["name"] || name; + + var type = spine.AttachmentType[map["type"] || "region"]; + + if (type == spine.AttachmentType.region) { + var attachment = new spine.RegionAttachment(); + attachment.x = (map["x"] || 0) * this.scale; + attachment.y = (map["y"] || 0) * this.scale; + attachment.scaleX = map["scaleX"] || 1; + attachment.scaleY = map["scaleY"] || 1; + attachment.rotation = map["rotation"] || 0; + attachment.width = (map["width"] || 32) * this.scale; + attachment.height = (map["height"] || 32) * this.scale; + attachment.updateOffset(); + + attachment.rendererObject = {}; + attachment.rendererObject.name = name; + attachment.rendererObject.scale = {}; + attachment.rendererObject.scale.x = attachment.scaleX; + attachment.rendererObject.scale.y = attachment.scaleY; + attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; + return attachment; + } + + throw "Unknown attachment type: " + type; + }, + + readAnimation: function (name, map, skeletonData) { + var timelines = []; + var duration = 0; + + var bones = map["bones"]; + for (var boneName in bones) { + if (!bones.hasOwnProperty(boneName)) continue; + var boneIndex = skeletonData.findBoneIndex(boneName); + if (boneIndex == -1) throw "Bone not found: " + boneName; + var boneMap = bones[boneName]; + + for (var timelineName in boneMap) { + if (!boneMap.hasOwnProperty(timelineName)) continue; + var values = boneMap[timelineName]; + if (timelineName == "rotate") { + var timeline = new spine.RotateTimeline(values.length); + timeline.boneIndex = boneIndex; + + var frameIndex = 0; + for (var i = 0, n = values.length; i < n; i++) { + var valueMap = values[i]; + timeline.setFrame(frameIndex, valueMap["time"], valueMap["angle"]); + spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 2 - 2]); + + } else if (timelineName == "translate" || timelineName == "scale") { + var timeline; + var timelineScale = 1; + if (timelineName == "scale") + timeline = new spine.ScaleTimeline(values.length); + else { + timeline = new spine.TranslateTimeline(values.length); + timelineScale = this.scale; + } + timeline.boneIndex = boneIndex; + + var frameIndex = 0; + for (var i = 0, n = values.length; i < n; i++) { + var valueMap = values[i]; + var x = (valueMap["x"] || 0) * timelineScale; + var y = (valueMap["y"] || 0) * timelineScale; + timeline.setFrame(frameIndex, valueMap["time"], x, y); + spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); + + } else + throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; + } + } + var slots = map["slots"]; + for (var slotName in slots) { + if (!slots.hasOwnProperty(slotName)) continue; + var slotMap = slots[slotName]; + var slotIndex = skeletonData.findSlotIndex(slotName); + + for (var timelineName in slotMap) { + if (!slotMap.hasOwnProperty(timelineName)) continue; + var values = slotMap[timelineName]; + if (timelineName == "color") { + var timeline = new spine.ColorTimeline(values.length); + timeline.slotIndex = slotIndex; + + var frameIndex = 0; + for (var i = 0, n = values.length; i < n; i++) { + var valueMap = values[i]; + var color = valueMap["color"]; + var r = spine.SkeletonJson.toColor(color, 0); + var g = spine.SkeletonJson.toColor(color, 1); + var b = spine.SkeletonJson.toColor(color, 2); + var a = spine.SkeletonJson.toColor(color, 3); + timeline.setFrame(frameIndex, valueMap["time"], r, g, b, a); + spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 5 - 5]); + + } else if (timelineName == "attachment") { + var timeline = new spine.AttachmentTimeline(values.length); + timeline.slotIndex = slotIndex; + + var frameIndex = 0; + for (var i = 0, n = values.length; i < n; i++) { + var valueMap = values[i]; + timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + + } else + throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; + } + } + skeletonData.animations.push(new spine.Animation(name, timelines, duration)); + } +}; +spine.SkeletonJson.readCurve = function (timeline, frameIndex, valueMap) { + var curve = valueMap["curve"]; + if (!curve) return; + if (curve == "stepped") + timeline.curves.setStepped(frameIndex); + else if (curve instanceof Array) + timeline.curves.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); +}; +spine.SkeletonJson.toColor = function (hexString, colorIndex) { + if (hexString.length != 8) throw "Color hexidecimal length must be 8, recieved: " + hexString; + return parseInt(hexString.substring(colorIndex * 2, 2), 16) / 255; +}; + +spine.Atlas = function (atlasText, textureLoader) { + this.textureLoader = textureLoader; + this.pages = []; + this.regions = []; + + var reader = new spine.AtlasReader(atlasText); + var tuple = []; + tuple.length = 4; + var page = null; + while (true) { + var line = reader.readLine(); + if (line == null) break; + line = reader.trim(line); + if (line.length == 0) + page = null; + else if (!page) { + page = new spine.AtlasPage(); + page.name = line; + + page.format = spine.Atlas.Format[reader.readValue()]; + + reader.readTuple(tuple); + page.minFilter = spine.Atlas.TextureFilter[tuple[0]]; + page.magFilter = spine.Atlas.TextureFilter[tuple[1]]; + + var direction = reader.readValue(); + page.uWrap = spine.Atlas.TextureWrap.clampToEdge; + page.vWrap = spine.Atlas.TextureWrap.clampToEdge; + if (direction == "x") + page.uWrap = spine.Atlas.TextureWrap.repeat; + else if (direction == "y") + page.vWrap = spine.Atlas.TextureWrap.repeat; + else if (direction == "xy") + page.uWrap = page.vWrap = spine.Atlas.TextureWrap.repeat; + + textureLoader.load(page, line); + + this.pages.push(page); + + } else { + var region = new spine.AtlasRegion(); + region.name = line; + region.page = page; + + region.rotate = reader.readValue() == "true"; + + reader.readTuple(tuple); + var x = parseInt(tuple[0]); + var y = parseInt(tuple[1]); + + reader.readTuple(tuple); + var width = parseInt(tuple[0]); + var height = parseInt(tuple[1]); + + region.u = x / page.width; + region.v = y / page.height; + if (region.rotate) { + region.u2 = (x + height) / page.width; + region.v2 = (y + width) / page.height; + } else { + region.u2 = (x + width) / page.width; + region.v2 = (y + height) / page.height; + } + region.x = x; + region.y = y; + region.width = Math.abs(width); + region.height = Math.abs(height); + + if (reader.readTuple(tuple) == 4) { // split is optional + region.splits = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; + + if (reader.readTuple(tuple) == 4) { // pad is optional, but only present with splits + region.pads = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; + + reader.readTuple(tuple); + } + } + + region.originalWidth = parseInt(tuple[0]); + region.originalHeight = parseInt(tuple[1]); + + reader.readTuple(tuple); + region.offsetX = parseInt(tuple[0]); + region.offsetY = parseInt(tuple[1]); + + region.index = parseInt(reader.readValue()); + + this.regions.push(region); + } + } +}; +spine.Atlas.prototype = { + findRegion: function (name) { + var regions = this.regions; + for (var i = 0, n = regions.length; i < n; i++) + if (regions[i].name == name) return regions[i]; + return null; + }, + dispose: function () { + var pages = this.pages; + for (var i = 0, n = pages.length; i < n; i++) + this.textureLoader.unload(pages[i].rendererObject); + }, + updateUVs: function (page) { + var regions = this.regions; + for (var i = 0, n = regions.length; i < n; i++) { + var region = regions[i]; + if (region.page != page) continue; + region.u = region.x / page.width; + region.v = region.y / page.height; + if (region.rotate) { + region.u2 = (region.x + region.height) / page.width; + region.v2 = (region.y + region.width) / page.height; + } else { + region.u2 = (region.x + region.width) / page.width; + region.v2 = (region.y + region.height) / page.height; + } + } + } +}; + +spine.Atlas.Format = { + alpha: 0, + intensity: 1, + luminanceAlpha: 2, + rgb565: 3, + rgba4444: 4, + rgb888: 5, + rgba8888: 6 +}; + +spine.Atlas.TextureFilter = { + nearest: 0, + linear: 1, + mipMap: 2, + mipMapNearestNearest: 3, + mipMapLinearNearest: 4, + mipMapNearestLinear: 5, + mipMapLinearLinear: 6 +}; + +spine.Atlas.TextureWrap = { + mirroredRepeat: 0, + clampToEdge: 1, + repeat: 2 +}; + +spine.AtlasPage = function () {}; +spine.AtlasPage.prototype = { + name: null, + format: null, + minFilter: null, + magFilter: null, + uWrap: null, + vWrap: null, + rendererObject: null, + width: 0, + height: 0 +}; + +spine.AtlasRegion = function () {}; +spine.AtlasRegion.prototype = { + page: null, + name: null, + x: 0, y: 0, + width: 0, height: 0, + u: 0, v: 0, u2: 0, v2: 0, + offsetX: 0, offsetY: 0, + originalWidth: 0, originalHeight: 0, + index: 0, + rotate: false, + splits: null, + pads: null, +}; + +spine.AtlasReader = function (text) { + this.lines = text.split(/\r\n|\r|\n/); +}; +spine.AtlasReader.prototype = { + index: 0, + trim: function (value) { + return value.replace(/^\s+|\s+$/g, ""); + }, + readLine: function () { + if (this.index >= this.lines.length) return null; + return this.lines[this.index++]; + }, + readValue: function () { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) throw "Invalid line: " + line; + return this.trim(line.substring(colon + 1)); + }, + /** Returns the number of tuple values read (2 or 4). */ + readTuple: function (tuple) { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) throw "Invalid line: " + line; + var i = 0, lastMatch= colon + 1; + for (; i < 3; i++) { + var comma = line.indexOf(",", lastMatch); + if (comma == -1) { + if (i == 0) throw "Invalid line: " + line; + break; + } + tuple[i] = this.trim(line.substr(lastMatch, comma - lastMatch)); + lastMatch = comma + 1; + } + tuple[i] = this.trim(line.substring(lastMatch)); + return i + 1; + } +} + +spine.AtlasAttachmentLoader = function (atlas) { + this.atlas = atlas; +} +spine.AtlasAttachmentLoader.prototype = { + newAttachment: function (skin, type, name) { + switch (type) { + case spine.AttachmentType.region: + var region = this.atlas.findRegion(name); + if (!region) throw "Region not found in atlas: " + name + " (" + type + ")"; + var attachment = new spine.RegionAttachment(name); + attachment.rendererObject = region; + attachment.setUVs(region.u, region.v, region.u2, region.v2, region.rotate); + attachment.regionOffsetX = region.offsetX; + attachment.regionOffsetY = region.offsetY; + attachment.regionWidth = region.width; + attachment.regionHeight = region.height; + attachment.regionOriginalWidth = region.originalWidth; + attachment.regionOriginalHeight = region.originalHeight; + return attachment; + } + throw "Unknown attachment type: " + type; + } +} + +PIXI.AnimCache = {}; +spine.Bone.yDown = true; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * This object is one that will allow you to specify custom rendering functions based on render type + * + * @class CustomRenderable + * @extends DisplayObject + * @constructor + */ +PIXI.CustomRenderable = function() +{ + PIXI.DisplayObject.call( this ); + + this.renderable = true; +} + +// constructor +PIXI.CustomRenderable.prototype = Object.create( PIXI.DisplayObject.prototype ); +PIXI.CustomRenderable.prototype.constructor = PIXI.CustomRenderable; + +/** + * If this object is being rendered by a CanvasRenderer it will call this callback + * + * @method renderCanvas + * @param renderer {CanvasRenderer} The renderer instance + */ +PIXI.CustomRenderable.prototype.renderCanvas = function(renderer) +{ + // override! +} + +/** + * If this object is being rendered by a WebGLRenderer it will call this callback to initialize + * + * @method initWebGL + * @param renderer {WebGLRenderer} The renderer instance + */ +PIXI.CustomRenderable.prototype.initWebGL = function(renderer) +{ + // override! +} + +/** + * If this object is being rendered by a WebGLRenderer it will call this callback + * + * @method renderWebGL + * @param renderer {WebGLRenderer} The renderer instance + */ +PIXI.CustomRenderable.prototype.renderWebGL = function(renderGroup, projectionMatrix) +{ + // not sure if both needed? but ya have for now! + // override! +} + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.BaseTextureCache = {}; +PIXI.texturesToUpdate = []; +PIXI.texturesToDestroy = []; + +/** + * A texture stores the information that represents an image. All textures have a base texture + * + * @class BaseTexture + * @uses EventTarget + * @constructor + * @param source {String} the source object (image or canvas) + */ +PIXI.BaseTexture = function(source) +{ + PIXI.EventTarget.call( this ); + + /** + * [read-only] The width of the base texture set when the image has loaded + * + * @property width + * @type Number + * @readOnly + */ + this.width = 100; + + /** + * [read-only] The height of the base texture set when the image has loaded + * + * @property height + * @type Number + * @readOnly + */ + this.height = 100; + + /** + * [read-only] Describes if the base texture has loaded or not + * + * @property hasLoaded + * @type Boolean + * @readOnly + */ + this.hasLoaded = false; + + /** + * The source that is loaded to create the texture + * + * @property source + * @type Image + */ + this.source = source; + + if(!source)return; + + if(this.source instanceof Image || this.source instanceof HTMLImageElement) + { + if(this.source.complete) + { + this.hasLoaded = true; + this.width = this.source.width; + this.height = this.source.height; + + PIXI.texturesToUpdate.push(this); + } + else + { + + var scope = this; + this.source.onload = function(){ + + scope.hasLoaded = true; + scope.width = scope.source.width; + scope.height = scope.source.height; + + // add it to somewhere... + PIXI.texturesToUpdate.push(scope); + scope.dispatchEvent( { type: 'loaded', content: scope } ); + } + // this.image.src = imageUrl; + } + } + else + { + this.hasLoaded = true; + this.width = this.source.width; + this.height = this.source.height; + + PIXI.texturesToUpdate.push(this); + } + + this._powerOf2 = false; +} + +PIXI.BaseTexture.prototype.constructor = PIXI.BaseTexture; + +/** + * Destroys this base texture + * + * @method destroy + */ +PIXI.BaseTexture.prototype.destroy = function() +{ + if(this.source instanceof Image) + { + this.source.src = null; + } + this.source = null; + PIXI.texturesToDestroy.push(this); +} + +/** + * Helper function that returns a base texture based on an image url + * If the image is not in the base texture cache it will be created and loaded + * + * @static + * @method fromImage + * @param imageUrl {String} The image url of the texture + * @return BaseTexture + */ +PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) +{ + var baseTexture = PIXI.BaseTextureCache[imageUrl]; + if(!baseTexture) + { + // new Image() breaks tex loading in some versions of Chrome. + // See https://code.google.com/p/chromium/issues/detail?id=238071 + var image = new Image();//document.createElement('img'); + if (crossorigin) + { + image.crossOrigin = ''; + } + image.src = imageUrl; + baseTexture = new PIXI.BaseTexture(image); + PIXI.BaseTextureCache[imageUrl] = baseTexture; + } + + return baseTexture; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.TextureCache = {}; +PIXI.FrameCache = {}; + +/** + * A texture stores the information that represents an image or part of an image. It cannot be added + * to the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used + * + * @class Texture + * @uses EventTarget + * @constructor + * @param baseTexture {BaseTexture} The base texture source to create the texture from + * @param frame {Rectangle} The rectangle frame of the texture to show + */ +PIXI.Texture = function(baseTexture, frame) +{ + PIXI.EventTarget.call( this ); + + if(!frame) + { + this.noFrame = true; + frame = new PIXI.Rectangle(0,0,1,1); + } + + if(baseTexture instanceof PIXI.Texture) + baseTexture = baseTexture.baseTexture; + + /** + * The base texture of this texture + * + * @property baseTexture + * @type BaseTexture + */ + this.baseTexture = baseTexture; + + /** + * The frame specifies the region of the base texture that this texture uses + * + * @property frame + * @type Rectangle + */ + this.frame = frame; + + /** + * The trim point + * + * @property trim + * @type Point + */ + this.trim = new PIXI.Point(); + + this.scope = this; + + if(baseTexture.hasLoaded) + { + if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); + //console.log(frame) + + this.setFrame(frame); + } + else + { + var scope = this; + baseTexture.addEventListener( 'loaded', function(){ scope.onBaseTextureLoaded()} ); + } +} + +PIXI.Texture.prototype.constructor = PIXI.Texture; + +/** + * Called when the base texture is loaded + * + * @method onBaseTextureLoaded + * @param event + * @private + */ +PIXI.Texture.prototype.onBaseTextureLoaded = function(event) +{ + var baseTexture = this.baseTexture; + baseTexture.removeEventListener( 'loaded', this.onLoaded ); + + if(this.noFrame)this.frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); + this.noFrame = false; + this.width = this.frame.width; + this.height = this.frame.height; + + this.scope.dispatchEvent( { type: 'update', content: this } ); +} + +/** + * Destroys this texture + * + * @method destroy + * @param destroyBase {Boolean} Whether to destroy the base texture as well + */ +PIXI.Texture.prototype.destroy = function(destroyBase) +{ + if(destroyBase)this.baseTexture.destroy(); +} + +/** + * Specifies the rectangle region of the baseTexture + * + * @method setFrame + * @param frame {Rectangle} The frame of the texture to set it to + */ +PIXI.Texture.prototype.setFrame = function(frame) +{ + this.frame = frame; + this.width = frame.width; + this.height = frame.height; + + if(frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height) + { + throw new Error("Texture Error: frame does not fit inside the base Texture dimensions " + this); + } + + this.updateFrame = true; + + PIXI.Texture.frameUpdates.push(this); + //this.dispatchEvent( { type: 'update', content: this } ); +} + +/** + * Helper function that returns a texture based on an image url + * If the image is not in the texture cache it will be created and loaded + * + * @static + * @method fromImage + * @param imageUrl {String} The image url of the texture + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin + * @return Texture + */ +PIXI.Texture.fromImage = function(imageUrl, crossorigin) +{ + var texture = PIXI.TextureCache[imageUrl]; + + if(!texture) + { + texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); + PIXI.TextureCache[imageUrl] = texture; + } + + return texture; +} + +/** + * Helper function that returns a texture based on a frame id + * If the frame id is not in the texture cache an error will be thrown + * + * @static + * @method fromFrame + * @param frameId {String} The frame id of the texture + * @return Texture + */ +PIXI.Texture.fromFrame = function(frameId) +{ + var texture = PIXI.TextureCache[frameId]; + if(!texture)throw new Error("The frameId '"+ frameId +"' does not exist in the texture cache " + this); + return texture; +} + +/** + * Helper function that returns a texture based on a canvas element + * If the canvas is not in the texture cache it will be created and loaded + * + * @static + * @method fromCanvas + * @param canvas {Canvas} The canvas element source of the texture + * @return Texture + */ +PIXI.Texture.fromCanvas = function(canvas) +{ + var baseTexture = new PIXI.BaseTexture(canvas); + return new PIXI.Texture(baseTexture); +} + + +/** + * Adds a texture to the textureCache. + * + * @static + * @method addTextureToCache + * @param texture {Texture} + * @param id {String} the id that the texture will be stored against. + */ +PIXI.Texture.addTextureToCache = function(texture, id) +{ + PIXI.TextureCache[id] = texture; +} + +/** + * Remove a texture from the textureCache. + * + * @static + * @method removeTextureFromCache + * @param id {String} the id of the texture to be removed + * @return {Texture} the texture that was removed + */ +PIXI.Texture.removeTextureFromCache = function(id) +{ + var texture = PIXI.TextureCache[id] + PIXI.TextureCache[id] = null; + return texture; +} + +// this is more for webGL.. it contains updated frames.. +PIXI.Texture.frameUpdates = []; + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + A RenderTexture is a special texture that allows any pixi displayObject to be rendered to it. + + __Hint__: All DisplayObjects (exmpl. Sprites) that renders on RenderTexture should be preloaded. + Otherwise black rectangles will be drawn instead. + + RenderTexture takes snapshot of DisplayObject passed to render method. If DisplayObject is passed to render method, position and rotation of it will be ignored. For example: + + var renderTexture = new PIXI.RenderTexture(800, 600); + var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); + sprite.position.x = 800/2; + sprite.position.y = 600/2; + sprite.anchor.x = 0.5; + sprite.anchor.y = 0.5; + renderTexture.render(sprite); + + Sprite in this case will be rendered to 0,0 position. To render this sprite at center DisplayObjectContainer should be used: + + var doc = new PIXI.DisplayObjectContainer(); + doc.addChild(sprite); + renderTexture.render(doc); // Renders to center of renderTexture + + @class RenderTexture + @extends Texture + @constructor + @param width {Number} The width of the render texture + @param height {Number} The height of the render texture + */ +PIXI.RenderTexture = function(width, height) +{ + PIXI.EventTarget.call( this ); + + this.width = width || 100; + this.height = height || 100; + + this.indetityMatrix = PIXI.mat3.create(); + + this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); + + if(PIXI.gl) + { + this.initWebGL(); + } + else + { + this.initCanvas(); + } +} + +PIXI.RenderTexture.prototype = Object.create( PIXI.Texture.prototype ); +PIXI.RenderTexture.prototype.constructor = PIXI.RenderTexture; + +/** + * Initializes the webgl data for this texture + * + * @method initWebGL + * @private + */ +PIXI.RenderTexture.prototype.initWebGL = function() +{ + var gl = PIXI.gl; + this.glFramebuffer = gl.createFramebuffer(); + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); + + this.glFramebuffer.width = this.width; + this.glFramebuffer.height = this.height; + + this.baseTexture = new PIXI.BaseTexture(); + + this.baseTexture.width = this.width; + this.baseTexture.height = this.height; + + this.baseTexture._glTexture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); + + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + + this.baseTexture.isRender = true; + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.baseTexture._glTexture, 0); + + // create a projection matrix.. + this.projection = new PIXI.Point(this.width/2 , this.height/2); + + // set the correct render function.. + this.render = this.renderWebGL; + + +} + + +PIXI.RenderTexture.prototype.resize = function(width, height) +{ + + this.width = width; + this.height = height; + + if(PIXI.gl) + { + this.projection.x = this.width/2 + this.projection.y = this.height/2; + + var gl = PIXI.gl; + gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + } + else + { + + this.frame.width = this.width + this.frame.height = this.height; + this.renderer.resize(this.width, this.height); + } +} + +/** + * Initializes the canvas data for this texture + * + * @method initCanvas + * @private + */ +PIXI.RenderTexture.prototype.initCanvas = function() +{ + this.renderer = new PIXI.CanvasRenderer(this.width, this.height, null, 0); + + this.baseTexture = new PIXI.BaseTexture(this.renderer.view); + this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); + + this.render = this.renderCanvas; +} + +/** + * This function will draw the display object to the texture. + * + * @method renderWebGL + * @param displayObject {DisplayObject} The display object to render this texture on + * @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn + * @private + */ +PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, clear) +{ + var gl = PIXI.gl; + + // enable the alpha color mask.. + gl.colorMask(true, true, true, true); + + gl.viewport(0, 0, this.width, this.height); + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); + + if(clear) + { + gl.clearColor(0,0,0, 0); + gl.clear(gl.COLOR_BUFFER_BIT); + } + + // THIS WILL MESS WITH HIT TESTING! + var children = displayObject.children; + + //TODO -? create a new one??? dont think so! + var originalWorldTransform = displayObject.worldTransform; + displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; + // modify to flip... + displayObject.worldTransform[4] = -1; + displayObject.worldTransform[5] = this.projection.y * 2; + + + if(position) + { + displayObject.worldTransform[2] = position.x; + displayObject.worldTransform[5] -= position.y; + } + + PIXI.visibleCount++; + displayObject.vcount = PIXI.visibleCount; + + for(var i=0,j=children.length; i} assetURLs an array of image/sprite sheet urls that you would like loaded + * supported. Supported image formats include "jpeg", "jpg", "png", "gif". Supported + * sprite sheet data formats only include "JSON" at this time. Supported bitmap font + * data formats include "xml" and "fnt". + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin + */ +PIXI.AssetLoader = function(assetURLs, crossorigin) +{ + PIXI.EventTarget.call(this); + + /** + * The array of asset URLs that are going to be loaded + * + * @property assetURLs + * @type Array + */ + this.assetURLs = assetURLs; + + /** + * Whether the requests should be treated as cross origin + * + * @property crossorigin + * @type Boolean + */ + this.crossorigin = crossorigin; + + /** + * Maps file extension to loader types + * + * @property loadersByType + * @type Object + */ + this.loadersByType = { + "jpg": PIXI.ImageLoader, + "jpeg": PIXI.ImageLoader, + "png": PIXI.ImageLoader, + "gif": PIXI.ImageLoader, + "json": PIXI.JsonLoader, + "anim": PIXI.SpineLoader, + "xml": PIXI.BitmapFontLoader, + "fnt": PIXI.BitmapFontLoader + }; + + +}; + +/** + * Fired when an item has loaded + * @event onProgress + */ + +/** + * Fired when all the assets have loaded + * @event onComplete + */ + +// constructor +PIXI.AssetLoader.prototype.constructor = PIXI.AssetLoader; + +/** + * Starts loading the assets sequentially + * + * @method load + */ +PIXI.AssetLoader.prototype.load = function() +{ + var scope = this; + + this.loadCount = this.assetURLs.length; + + for (var i=0; i < this.assetURLs.length; i++) + { + var fileName = this.assetURLs[i]; + var fileType = fileName.split(".").pop().toLowerCase(); + + var loaderClass = this.loadersByType[fileType]; + if(!loaderClass) + throw new Error(fileType + " is an unsupported file type"); + + var loader = new loaderClass(fileName, this.crossorigin); + + loader.addEventListener("loaded", function() + { + scope.onAssetLoaded(); + }); + loader.load(); + } +}; + +/** + * Invoked after each file is loaded + * + * @method onAssetLoaded + * @private + */ +PIXI.AssetLoader.prototype.onAssetLoaded = function() +{ + this.loadCount--; + this.dispatchEvent({type: "onProgress", content: this}); + if(this.onProgress) this.onProgress(); + + if(this.loadCount == 0) + { + this.dispatchEvent({type: "onComplete", content: this}); + if(this.onComplete) this.onComplete(); + } +}; + + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * The json file loader is used to load in JSON data and parsing it + * When loaded this class will dispatch a "loaded" event + * If load failed this class will dispatch a "error" event + * + * @class JsonLoader + * @uses EventTarget + * @constructor + * @param url {String} The url of the JSON file + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin + */ +PIXI.JsonLoader = function (url, crossorigin) { + PIXI.EventTarget.call(this); + + /** + * The url of the bitmap font data + * + * @property url + * @type String + */ + this.url = url; + + /** + * Whether the requests should be treated as cross origin + * + * @property crossorigin + * @type Boolean + */ + this.crossorigin = crossorigin; + + /** + * [read-only] The base url of the bitmap font data + * + * @property baseUrl + * @type String + * @readOnly + */ + this.baseUrl = url.replace(/[^\/]*$/, ""); + + /** + * [read-only] Whether the data has loaded yet + * + * @property loaded + * @type Boolean + * @readOnly + */ + this.loaded = false; + +}; + +// constructor +PIXI.JsonLoader.prototype.constructor = PIXI.JsonLoader; + +/** + * Loads the JSON data + * + * @method load + */ +PIXI.JsonLoader.prototype.load = function () { + this.ajaxRequest = new AjaxRequest(); + var scope = this; + this.ajaxRequest.onreadystatechange = function () { + scope.onJSONLoaded(); + }; + + this.ajaxRequest.open("GET", this.url, true); + if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/json"); + this.ajaxRequest.send(null); +}; + +/** + * Invoke when JSON file is loaded + * + * @method onJSONLoaded + * @private + */ +PIXI.JsonLoader.prototype.onJSONLoaded = function () { + if (this.ajaxRequest.readyState == 4) { + if (this.ajaxRequest.status == 200 || window.location.href.indexOf("http") == -1) { + this.json = JSON.parse(this.ajaxRequest.responseText); + + if(this.json.frames) + { + // sprite sheet + var scope = this; + var textureUrl = this.baseUrl + this.json.meta.image; + var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); + var frameData = this.json.frames; + + this.texture = image.texture.baseTexture; + image.addEventListener("loaded", function (event) { + scope.onLoaded(); + }); + + for (var i in frameData) { + var rect = frameData[i].frame; + if (rect) { + PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { + x: rect.x, + y: rect.y, + width: rect.w, + height: rect.h + }); + if (frameData[i].trimmed) { + //var realSize = frameData[i].spriteSourceSize; + PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; + PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) + // calculate the offset! + } + } + } + + image.load(); + + } + else if(this.json.bones) + { + // spine animation + var spineJsonParser = new spine.SkeletonJson(); + var skeletonData = spineJsonParser.readSkeletonData(this.json); + PIXI.AnimCache[this.url] = skeletonData; + this.onLoaded(); + } + else + { + this.onLoaded(); + } + } + else + { + this.onError(); + } + } +}; + +/** + * Invoke when json file loaded + * + * @method onLoaded + * @private + */ +PIXI.JsonLoader.prototype.onLoaded = function () { + this.loaded = true; + this.dispatchEvent({ + type: "loaded", + content: this + }); +}; + +/** + * Invoke when error occured + * + * @method onError + * @private + */ +PIXI.JsonLoader.prototype.onError = function () { + this.dispatchEvent({ + type: "error", + content: this + }); +}; +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * The sprite sheet loader is used to load in JSON sprite sheet data + * To generate the data you can use http://www.codeandweb.com/texturepacker and publish the "JSON" format + * There is a free version so thats nice, although the paid version is great value for money. + * It is highly recommended to use Sprite sheets (also know as texture atlas") as it means sprite"s can be batched and drawn together for highly increased rendering speed. + * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() + * This loader will also load the image file that the Spritesheet points to as well as the data. + * When loaded this class will dispatch a "loaded" event + * + * @class SpriteSheetLoader + * @uses EventTarget + * @constructor + * @param url {String} The url of the sprite sheet JSON file + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin + */ + +PIXI.SpriteSheetLoader = function (url, crossorigin) { + /* + * i use texture packer to load the assets.. + * http://www.codeandweb.com/texturepacker + * make sure to set the format as "JSON" + */ + PIXI.EventTarget.call(this); + + /** + * The url of the bitmap font data + * + * @property url + * @type String + */ + this.url = url; + + /** + * Whether the requests should be treated as cross origin + * + * @property crossorigin + * @type Boolean + */ + this.crossorigin = crossorigin; + + /** + * [read-only] The base url of the bitmap font data + * + * @property baseUrl + * @type String + * @readOnly + */ + this.baseUrl = url.replace(/[^\/]*$/, ""); + + /** + * The texture being loaded + * + * @property texture + * @type Texture + */ + this.texture = null; + + /** + * The frames of the sprite sheet + * + * @property frames + * @type Object + */ + this.frames = {}; +}; + +// constructor +PIXI.SpriteSheetLoader.prototype.constructor = PIXI.SpriteSheetLoader; + +/** + * This will begin loading the JSON file + * + * @method load + */ +PIXI.SpriteSheetLoader.prototype.load = function () { + var scope = this; + var jsonLoader = new PIXI.JsonLoader(this.url, this.crossorigin); + jsonLoader.addEventListener("loaded", function (event) { + scope.json = event.content.json; + scope.onJSONLoaded(); + }); + jsonLoader.load(); +}; + +/** + * Invoke when JSON file is loaded + * + * @method onJSONLoaded + * @private + */ +PIXI.SpriteSheetLoader.prototype.onJSONLoaded = function () { + var scope = this; + var textureUrl = this.baseUrl + this.json.meta.image; + var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); + var frameData = this.json.frames; + + this.texture = image.texture.baseTexture; + image.addEventListener("loaded", function (event) { + scope.onLoaded(); + }); + + for (var i in frameData) { + var rect = frameData[i].frame; + if (rect) { + PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { + x: rect.x, + y: rect.y, + width: rect.w, + height: rect.h + }); + if (frameData[i].trimmed) { + //var realSize = frameData[i].spriteSourceSize; + PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; + PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) + // calculate the offset! + } + } + } + + image.load(); +}; +/** + * Invoke when all files are loaded (json and texture) + * + * @method onLoaded + * @private + */ +PIXI.SpriteSheetLoader.prototype.onLoaded = function () { + this.dispatchEvent({ + type: "loaded", + content: this + }); +}; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * The image loader class is responsible for loading images file formats ("jpeg", "jpg", "png" and "gif") + * Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() + * When loaded this class will dispatch a 'loaded' event + * + * @class ImageLoader + * @uses EventTarget + * @constructor + * @param url {String} The url of the image + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin + */ +PIXI.ImageLoader = function(url, crossorigin) +{ + PIXI.EventTarget.call(this); + + /** + * The texture being loaded + * + * @property texture + * @type Texture + */ + this.texture = PIXI.Texture.fromImage(url, crossorigin); + + /** + * if the image is loaded with loadFramedSpriteSheet + * frames will contain the sprite sheet frames + * + */ + this.frames = []; +}; + +// constructor +PIXI.ImageLoader.prototype.constructor = PIXI.ImageLoader; + +/** + * Loads image or takes it from cache + * + * @method load + */ +PIXI.ImageLoader.prototype.load = function() +{ + if(!this.texture.baseTexture.hasLoaded) + { + var scope = this; + this.texture.baseTexture.addEventListener("loaded", function() + { + scope.onLoaded(); + }); + } + else + { + this.onLoaded(); + } +}; + +/** + * Invoked when image file is loaded or it is already cached and ready to use + * + * @method onLoaded + * @private + */ +PIXI.ImageLoader.prototype.onLoaded = function() +{ + this.dispatchEvent({type: "loaded", content: this}); +}; + +/** + * Loads image and split it to uniform sized frames + * + * + * @method loadFramedSpriteSheet + * @param frameWidth {Number} with of each frame + * @param frameHeight {Number} height of each frame + * @param textureName {String} if given, the frames will be cached in - format + */ +PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) +{ + this.frames = []; + var cols = Math.floor(this.texture.width / frameWidth); + var rows = Math.floor(this.texture.height / frameHeight); + + var i=0; + for (var y=0; y>>") + var gl = PIXI.gl; var shaderProgram = shader.program; + // map uniforms.. gl.useProgram(shaderProgram); @@ -220,7 +220,6 @@ PIXI.activateShader = function(shader) PIXI.popShader = function() { var gl = PIXI.gl; - // activate last program.. var lastProgram = PIXI.shaderStack.pop(); var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; @@ -235,13 +234,7 @@ PIXI.activatePrimitiveShader = function() var gl = PIXI.gl; gl.useProgram(PIXI.primitiveProgram); - - //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); - //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); - - //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); - //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); } PIXI.deactivatePrimitiveShader = function() @@ -249,8 +242,5 @@ PIXI.deactivatePrimitiveShader = function() var gl = PIXI.gl; gl.useProgram(PIXI.currentShader); - gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); - //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); - //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); } \ No newline at end of file From e50a6716d8bd1c78fd4d383a22451210c04fbac3 Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Sun, 20 Oct 2013 18:30:47 +0100 Subject: [PATCH 56/96] fixed bug in masking example --- examples/example 14 - Masking/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example 14 - Masking/index.html b/examples/example 14 - Masking/index.html index 3dc625f..53746b0 100644 --- a/examples/example 14 - Masking/index.html +++ b/examples/example 14 - Masking/index.html @@ -83,7 +83,7 @@ stage.click = stage.tap = function() { - if(!container.filter) + if(!container.mask) { container.mask = thing; PIXI.runList(stage); From ddb24d7fe0339df305f816832454cb1183538282 Mon Sep 17 00:00:00 2001 From: mattdesl Date: Wed, 23 Oct 2013 11:44:34 -0400 Subject: [PATCH 57/96] - using a single JS source for all examples instead of duplicating files unnecessarily. - updating Gruntfile and package.json to include grunt-concat-sourcemap and grunt-contrib-watch for easier development. - use "grunt build-debug" to build a source-mapped file to pixi.dev.js -- or use "grunt watch" during development of examples to auto build-debug any JS changes to PIXI source or the example files. --- Gruntfile.js | 67 +- examples/example 1 - Basics/index.html | 2 +- examples/example 1 - Basics/pixi.js | 10649 --------------- examples/example 10 - Text/index.html | 2 +- examples/example 10 - Text/pixi.js | 10649 --------------- .../example 11 - RenderTexture/index.html | 2 +- examples/example 11 - RenderTexture/pixi.js | 10649 --------------- examples/example 12 - Spine/index.html | 2 +- examples/example 12 - Spine/index_dragon.html | 2 +- .../example 12 - Spine/index_goblins.html | 2 +- examples/example 12 - Spine/index_pixie.html | 2 +- examples/example 12 - Spine/pixi.js | 10649 --------------- examples/example 13 - Graphics/index.html | 2 +- examples/example 13 - Graphics/pixi.js | 10649 --------------- .../example 14 - Masking/Copy of index.html | 2 +- .../index double mask.html | 2 +- examples/example 14 - Masking/index.html | 2 +- examples/example 14 - Masking/pixi.js | 10649 --------------- examples/example 15 - Filters/index.html | 2 +- examples/example 15 - Filters/pixi.js | 10649 --------------- examples/example 16 - Displacement/index.html | 2 +- examples/example 16 - Displacement/pixi.js | 10773 ---------------- examples/example 2 - SpriteSheet/index.html | 2 +- examples/example 2 - SpriteSheet/pixi.js | 10649 --------------- examples/example 3 - MovieClip/index.html | 2 +- examples/example 3 - MovieClip/pixi.js | 10649 --------------- examples/example 4 - Balls/index.html | 2 +- examples/example 4 - Balls/pixi.js | 10649 --------------- examples/example 5 - Morph/index.html | 2 +- examples/example 5 - Morph/pixi.js | 10649 --------------- examples/example 6 - Interactivity/index.html | 2 +- examples/example 6 - Interactivity/pixi.js | 10649 --------------- .../index.html | 2 +- .../pixi.js | 10649 --------------- examples/example 8 - Dragging/index.html | 2 +- examples/example 8 - Dragging/pixi.js | 10649 --------------- .../example 9 - Tiling Texture/index.html | 2 +- examples/example 9 - Tiling Texture/pixi.js | 10649 --------------- package.json | 2 + 39 files changed, 49 insertions(+), 170570 deletions(-) delete mode 100644 examples/example 1 - Basics/pixi.js delete mode 100644 examples/example 10 - Text/pixi.js delete mode 100644 examples/example 11 - RenderTexture/pixi.js delete mode 100644 examples/example 12 - Spine/pixi.js delete mode 100644 examples/example 13 - Graphics/pixi.js delete mode 100644 examples/example 14 - Masking/pixi.js delete mode 100644 examples/example 15 - Filters/pixi.js delete mode 100644 examples/example 16 - Displacement/pixi.js delete mode 100644 examples/example 2 - SpriteSheet/pixi.js delete mode 100755 examples/example 3 - MovieClip/pixi.js delete mode 100644 examples/example 4 - Balls/pixi.js delete mode 100644 examples/example 5 - Morph/pixi.js delete mode 100644 examples/example 6 - Interactivity/pixi.js delete mode 100644 examples/example 7 - Transparent Background/pixi.js delete mode 100644 examples/example 8 - Dragging/pixi.js delete mode 100644 examples/example 9 - Tiling Texture/pixi.js diff --git a/Gruntfile.js b/Gruntfile.js index 5f7fba8..7d894a0 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,10 +1,12 @@ module.exports = function(grunt) { + grunt.loadNpmTasks('grunt-concat-sourcemap'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-contrib-qunit'); grunt.loadNpmTasks('grunt-contrib-yuidoc'); + grunt.loadNpmTasks('grunt-contrib-watch'); var root = 'src/pixi/', debug = 'bin/pixi.dev.js', @@ -77,7 +79,6 @@ module.exports = function(grunt) { dirs: { build: 'bin', docs: 'docs', - examples: 'examples', src: 'src/pixi', test: 'test' }, @@ -96,6 +97,16 @@ module.exports = function(grunt) { dest: '<%= files.build %>' } }, + concat_sourcemap: { + dev: { + files: { + '<%= files.build %>': srcFiles + }, + options: { + sourceRoot: '../' + } + } + }, jshint: { beforeconcat: srcFiles, test: ['<%= files.testBlob %>'], @@ -113,26 +124,6 @@ module.exports = function(grunt) { dest: '<%= files.buildMin %>' } }, - distribute: { - examples: [ - 'examples/example 1 - Basics', - 'examples/example 2 - SpriteSheet', - 'examples/example 3 - MovieClip', - 'examples/example 4 - Balls', - 'examples/example 5 - Morph', - 'examples/example 6 - Interactivity', - 'examples/example 7 - Transparent Background', - 'examples/example 8 - Dragging', - 'examples/example 9 - Tiling Texture', - 'examples/example 10 - Text', - 'examples/example 11 - RenderTexture', - 'examples/example 12 - Spine', - 'examples/example 13 - Graphics', - 'examples/example 14 - Masking', - 'examples/example 15 - Filters', - 'examples/example 16 - Displacement' - ] - }, connect: { qunit: { options: { @@ -167,29 +158,23 @@ module.exports = function(grunt) { outdir: '<%= dirs.docs %>' } } + }, + watch: { + dev: { + files: ['Gruntfile.js', 'src/**/*.js', 'examples/**/*.html'], + tasks: ['build-debug'], + + // We would need to inject + diff --git a/examples/example 1 - Basics/pixi.js b/examples/example 1 - Basics/pixi.js deleted file mode 100644 index 6d567a2..0000000 --- a/examples/example 1 - Basics/pixi.js +++ /dev/null @@ -1,10649 +0,0 @@ -/** - * @license - * Pixi.JS - v1.3.0 - * Copyright (c) 2012, Mat Groves - * http://goodboydigital.com/ - * - * Compiled: 2013-09-30 - * - * Pixi.JS is licensed under the MIT License. - * http://www.opensource.org/licenses/mit-license.php - */ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -(function(){ - - var root = this; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * @module PIXI - */ -var PIXI = PIXI || {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The Point object represents a location in a two-dimensional coordinate system, where x represents the horizontal axis and y represents the vertical axis. - * - * @class Point - * @constructor - * @param x {Number} position of the point - * @param y {Number} position of the point - */ -PIXI.Point = function(x, y) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; -} - -/** - * Creates a clone of this point - * - * @method clone - * @return {Point} a copy of the point - */ -PIXI.Point.prototype.clone = function() -{ - return new PIXI.Point(this.x, this.y); -} - -// constructor -PIXI.Point.prototype.constructor = PIXI.Point; - - -/** - * @author Mat Groves http://matgroves.com/ - */ - -/** - * the Rectangle object is an area defined by its position, as indicated by its top-left corner point (x, y) and by its width and its height. - * - * @class Rectangle - * @constructor - * @param x {Number} The X coord of the upper-left corner of the rectangle - * @param y {Number} The Y coord of the upper-left corner of the rectangle - * @param width {Number} The overall width of this rectangle - * @param height {Number} The overall height of this rectangle - */ -PIXI.Rectangle = function(x, y, width, height) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property width - * @type Number - * @default 0 - */ - this.width = width || 0; - - /** - * @property height - * @type Number - * @default 0 - */ - this.height = height || 0; -} - -/** - * Creates a clone of this Rectangle - * - * @method clone - * @return {Rectangle} a copy of the rectangle - */ -PIXI.Rectangle.prototype.clone = function() -{ - return new PIXI.Rectangle(this.x, this.y, this.width, this.height); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this Rectangle - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this Rectangle - */ -PIXI.Rectangle.prototype.contains = function(x, y) -{ - if(this.width <= 0 || this.height <= 0) - return false; - - var x1 = this.x; - if(x >= x1 && x <= x1 + this.width) - { - var y1 = this.y; - - if(y >= y1 && y <= y1 + this.height) - { - return true; - } - } - - return false; -} - -// constructor -PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; - - -/** - * @author Adrien Brault - */ - -/** - * @class Polygon - * @constructor - * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, - * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be - * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the - * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are - * Numbers. - */ -PIXI.Polygon = function(points) -{ - //if points isn't an array, use arguments as the array - if(!(points instanceof Array)) - points = Array.prototype.slice.call(arguments); - - //if this is a flat array of numbers, convert it to points - if(typeof points[0] === 'number') { - var p = []; - for(var i = 0, il = points.length; i < il; i+=2) { - p.push( - new PIXI.Point(points[i], points[i + 1]) - ); - } - - points = p; - } - - this.points = points; -} - -/** - * Creates a clone of this polygon - * - * @method clone - * @return {Polygon} a copy of the polygon - */ -PIXI.Polygon.prototype.clone = function() -{ - var points = []; - for (var i=0; i y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); - - if(intersect) inside = !inside; - } - - return inside; -} - -// constructor -PIXI.Polygon.prototype.constructor = PIXI.Polygon; - -/** - * @author Chad Engler - */ - -/** - * The Circle object can be used to specify a hit area for displayobjects - * - * @class Circle - * @constructor - * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle - * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle - * @param radius {Number} The radius of the circle - */ -PIXI.Circle = function(x, y, radius) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property radius - * @type Number - * @default 0 - */ - this.radius = radius || 0; -} - -/** - * Creates a clone of this Circle instance - * - * @method clone - * @return {Circle} a copy of the polygon - */ -PIXI.Circle.prototype.clone = function() -{ - return new PIXI.Circle(this.x, this.y, this.radius); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this circle - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this polygon - */ -PIXI.Circle.prototype.contains = function(x, y) -{ - if(this.radius <= 0) - return false; - - var dx = (this.x - x), - dy = (this.y - y), - r2 = this.radius * this.radius; - - dx *= dx; - dy *= dy; - - return (dx + dy <= r2); -} - -// constructor -PIXI.Circle.prototype.constructor = PIXI.Circle; - - -/** - * @author Chad Engler - */ - -/** - * The Ellipse object can be used to specify a hit area for displayobjects - * - * @class Ellipse - * @constructor - * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse - * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse - * @param width {Number} The overall width of this ellipse - * @param height {Number} The overall height of this ellipse - */ -PIXI.Ellipse = function(x, y, width, height) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property width - * @type Number - * @default 0 - */ - this.width = width || 0; - - /** - * @property height - * @type Number - * @default 0 - */ - this.height = height || 0; -} - -/** - * Creates a clone of this Ellipse instance - * - * @method clone - * @return {Ellipse} a copy of the ellipse - */ -PIXI.Ellipse.prototype.clone = function() -{ - return new PIXI.Ellipse(this.x, this.y, this.width, this.height); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this ellipse - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this ellipse - */ -PIXI.Ellipse.prototype.contains = function(x, y) -{ - if(this.width <= 0 || this.height <= 0) - return false; - - //normalize the coords to an ellipse with center 0,0 - //and a radius of 0.5 - var normx = ((x - this.x) / this.width) - 0.5, - normy = ((y - this.y) / this.height) - 0.5; - - normx *= normx; - normy *= normy; - - return (normx + normy < 0.25); -} - -PIXI.Ellipse.getBounds = function() -{ - return new PIXI.Rectangle(this.x, this.y, this.width, this.height); -} - -// constructor -PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; - - - -/* - * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV - * you both rock! - */ - -function determineMatrixArrayType() { - PIXI.Matrix = (typeof Float32Array !== 'undefined') ? Float32Array : Array; - return PIXI.Matrix; -} - -determineMatrixArrayType(); - -PIXI.mat3 = {}; - -PIXI.mat3.create = function() -{ - var matrix = new PIXI.Matrix(9); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 1; - matrix[5] = 0; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 1; - - return matrix; -} - - -PIXI.mat3.identity = function(matrix) -{ - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 1; - matrix[5] = 0; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 1; - - return matrix; -} - - -PIXI.mat4 = {}; - -PIXI.mat4.create = function() -{ - var matrix = new PIXI.Matrix(16); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 0; - matrix[5] = 1; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = 1; - matrix[11] = 0; - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; - - return matrix; -} - -PIXI.mat3.multiply = function (mat, mat2, dest) -{ - if (!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[0], a01 = mat[1], a02 = mat[2], - a10 = mat[3], a11 = mat[4], a12 = mat[5], - a20 = mat[6], a21 = mat[7], a22 = mat[8], - - b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], - b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], - b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; - - dest[0] = b00 * a00 + b01 * a10 + b02 * a20; - dest[1] = b00 * a01 + b01 * a11 + b02 * a21; - dest[2] = b00 * a02 + b01 * a12 + b02 * a22; - - dest[3] = b10 * a00 + b11 * a10 + b12 * a20; - dest[4] = b10 * a01 + b11 * a11 + b12 * a21; - dest[5] = b10 * a02 + b11 * a12 + b12 * a22; - - dest[6] = b20 * a00 + b21 * a10 + b22 * a20; - dest[7] = b20 * a01 + b21 * a11 + b22 * a21; - dest[8] = b20 * a02 + b21 * a12 + b22 * a22; - - return dest; -} - -PIXI.mat3.clone = function(mat) -{ - var matrix = new PIXI.Matrix(9); - - matrix[0] = mat[0]; - matrix[1] = mat[1]; - matrix[2] = mat[2]; - matrix[3] = mat[3]; - matrix[4] = mat[4]; - matrix[5] = mat[5]; - matrix[6] = mat[6]; - matrix[7] = mat[7]; - matrix[8] = mat[8]; - - return matrix; -} - -PIXI.mat3.transpose = function (mat, dest) -{ - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) { - var a01 = mat[1], a02 = mat[2], - a12 = mat[5]; - - mat[1] = mat[3]; - mat[2] = mat[6]; - mat[3] = a01; - mat[5] = mat[7]; - mat[6] = a02; - mat[7] = a12; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[3]; - dest[2] = mat[6]; - dest[3] = mat[1]; - dest[4] = mat[4]; - dest[5] = mat[7]; - dest[6] = mat[2]; - dest[7] = mat[5]; - dest[8] = mat[8]; - return dest; -} - -PIXI.mat3.toMat4 = function (mat, dest) -{ - if (!dest) { dest = PIXI.mat4.create(); } - - dest[15] = 1; - dest[14] = 0; - dest[13] = 0; - dest[12] = 0; - - dest[11] = 0; - dest[10] = mat[8]; - dest[9] = mat[7]; - dest[8] = mat[6]; - - dest[7] = 0; - dest[6] = mat[5]; - dest[5] = mat[4]; - dest[4] = mat[3]; - - dest[3] = 0; - dest[2] = mat[2]; - dest[1] = mat[1]; - dest[0] = mat[0]; - - return dest; -} - - -///// - - -PIXI.mat4.create = function() -{ - var matrix = new PIXI.Matrix(16); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 0; - matrix[5] = 1; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = 1; - matrix[11] = 0; - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; - - return matrix; -} - -PIXI.mat4.transpose = function (mat, dest) -{ - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) - { - var a01 = mat[1], a02 = mat[2], a03 = mat[3], - a12 = mat[6], a13 = mat[7], - a23 = mat[11]; - - mat[1] = mat[4]; - mat[2] = mat[8]; - mat[3] = mat[12]; - mat[4] = a01; - mat[6] = mat[9]; - mat[7] = mat[13]; - mat[8] = a02; - mat[9] = a12; - mat[11] = mat[14]; - mat[12] = a03; - mat[13] = a13; - mat[14] = a23; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[4]; - dest[2] = mat[8]; - dest[3] = mat[12]; - dest[4] = mat[1]; - dest[5] = mat[5]; - dest[6] = mat[9]; - dest[7] = mat[13]; - dest[8] = mat[2]; - dest[9] = mat[6]; - dest[10] = mat[10]; - dest[11] = mat[14]; - dest[12] = mat[3]; - dest[13] = mat[7]; - dest[14] = mat[11]; - dest[15] = mat[15]; - return dest; -} - -PIXI.mat4.multiply = function (mat, mat2, dest) -{ - if (!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; - var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; - var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; - var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - - // Cache only the current line of the second matrix - var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; - dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[4]; - b1 = mat2[5]; - b2 = mat2[6]; - b3 = mat2[7]; - dest[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[8]; - b1 = mat2[9]; - b2 = mat2[10]; - b3 = mat2[11]; - dest[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[12]; - b1 = mat2[13]; - b2 = mat2[14]; - b3 = mat2[15]; - dest[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - return dest; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The base class for all objects that are rendered on the screen. - * - * @class DisplayObject - * @constructor - */ -PIXI.DisplayObject = function() -{ - this.last = this; - this.first = this; - /** - * The coordinate of the object relative to the local coordinates of the parent. - * - * @property position - * @type Point - */ - this.position = new PIXI.Point(); - - /** - * The scale factor of the object. - * - * @property scale - * @type Point - */ - this.scale = new PIXI.Point(1,1);//{x:1, y:1}; - - /** - * The pivot point of the displayObject that it rotates around - * - * @property pivot - * @type Point - */ - this.pivot = new PIXI.Point(0,0); - - /** - * The rotation of the object in radians. - * - * @property rotation - * @type Number - */ - this.rotation = 0; - - /** - * The opacity of the object. - * - * @property alpha - * @type Number - */ - this.alpha = 1; - - /** - * The visibility of the object. - * - * @property visible - * @type Boolean - */ - this.visible = true; - - /** - * This is the defined area that will pick up mouse / touch events. It is null by default. - * Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children) - * - * @property hitArea - * @type Rectangle|Circle|Ellipse|Polygon - */ - this.hitArea = null; - - /** - * This is used to indicate if the displayObject should display a mouse hand cursor on rollover - * - * @property buttonMode - * @type Boolean - */ - this.buttonMode = false; - - /** - * Can this object be rendered - * - * @property renderable - * @type Boolean - */ - this.renderable = false; - - /** - * [read-only] The display object container that contains this display object. - * - * @property parent - * @type DisplayObjectContainer - * @readOnly - */ - this.parent = null; - - /** - * [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage. - * - * @property stage - * @type Stage - * @readOnly - */ - this.stage = null; - - /** - * [read-only] The multiplied alpha of the displayobject - * - * @property worldAlpha - * @type Number - * @readOnly - */ - this.worldAlpha = 1; - - /** - * [read-only] Whether or not the object is interactive, do not toggle directly! use the `interactive` property - * - * @property _interactive - * @type Boolean - * @readOnly - * @private - */ - this._interactive = false; - - /** - * [read-only] Current transform of the object based on world (parent) factors - * - * @property worldTransform - * @type Mat3 - * @readOnly - * @private - */ - this.worldTransform = PIXI.mat3.create()//mat3.identity(); - - /** - * [read-only] Current transform of the object locally - * - * @property localTransform - * @type Mat3 - * @readOnly - * @private - */ - this.localTransform = PIXI.mat3.create()//mat3.identity(); - - /** - * [NYI] Unkown - * - * @property color - * @type Array<> - * @private - */ - this.color = []; - - /** - * [NYI] Holds whether or not this object is dynamic, for rendering optimization - * - * @property dynamic - * @type Boolean - * @private - */ - this.dynamic = true; - - // chach that puppy! - this._sr = 0; - this._cr = 1; - - /* - * MOUSE Callbacks - */ - - /** - * A callback that is used when the users clicks on the displayObject with their mouse - * @method click - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user clicks the mouse down over the sprite - * @method mousedown - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject - * for this callback to be fired the mouse must have been pressed down over the displayObject - * @method mouseup - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject - * for this callback to be fired, The touch must have started over the displayObject - * @method mouseupoutside - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the users mouse rolls over the displayObject - * @method mouseover - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the users mouse leaves the displayObject - * @method mouseout - * @param interactionData {InteractionData} - */ - - - /* - * TOUCH Callbacks - */ - - /** - * A callback that is used when the users taps on the sprite with their finger - * basically a touch version of click - * @method tap - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user touch's over the displayObject - * @method touchstart - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases a touch over the displayObject - * @method touchend - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the touch that was over the displayObject - * for this callback to be fired, The touch must have started over the sprite - * @method touchendoutside - * @param interactionData {InteractionData} - */ -} - -// constructor -PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; - -/** - * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default - * Instead of using this function you can now simply set the interactive property to true or false - * - * @method setInteractive - * @param interactive {Boolean} - * @deprecated Simply set the `interactive` property directly - */ -PIXI.DisplayObject.prototype.setInteractive = function(interactive) -{ - this.interactive = interactive; -} - -/** - * Indicates if the sprite will have touch and mouse interactivity. It is false by default - * - * @property interactive - * @type Boolean - * @default false - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'interactive', { - get: function() { - return this._interactive; - }, - set: function(value) { - this._interactive = value; - - // TODO more to be done here.. - // need to sort out a re-crawl! - if(this.stage)this.stage.dirty = true; - } -}); - -/** - * Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. - * In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. - * To remove a mask, set this property to null. - * - * @property mask - * @type Graphics - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { - get: function() { - return this._mask; - }, - set: function(value) { - - - if(value) - { - if(this._mask) - { - value.start = this._mask.start; - value.end = this._mask.end; - } - else - { - this.addFilter(value); - value.renderable = false; - } - } - else - { - this.removeFilter(this._mask); - this._mask.renderable = true; - } - - this._mask = value; - } -}); - -/** - * Sets the filters for the displayObject. Currently there's a few limitations. - * 1: At the moment only one filter can be applied at a time.. - * 2: They cannot be nested. - * 3: There's no padding yet. - * 4: this is a webGL only feature. - * @property filters - * @type Array - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { - get: function() { - return this._filters; - }, - set: function(value) { - - //if(value == ) - if(value) - { - if(this._filters)this.removeFilter(this._filters); - this.addFilter(value) - } - else - { - if(this._filters)this.removeFilter(this._filters); - } - - this._filters = value; - } -}); - -/* - * Adds a filter to this displayObject - * - * @method addFilter - * @param mask {Graphics} the graphics object to use as a filter - * @private - */ -PIXI.DisplayObject.prototype.addFilter = function(data) -{ - //if(this.filter)return; - //this.filter = true; - - // insert a filter block.. - // TODO Onject pool thease bad boys.. - var start = new PIXI.FilterBlock(); - var end = new PIXI.FilterBlock(); - - data.start = start; - data.end = end; - - start.data = data; - end.data = data; - - start.first = start.last = this; - end.first = end.last = this; - - start.open = true; - - /* - * insert start - */ - - var childFirst = start - var childLast = start - var nextObject; - var previousObject; - - previousObject = this.first._iPrev; - - if(previousObject) - { - nextObject = previousObject._iNext; - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - } - else - { - nextObject = this; - } - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - - // now insert the end filter block.. - - /* - * insert end filter - */ - var childFirst = end - var childLast = end - var nextObject = null; - var previousObject = null; - - previousObject = this.last; - nextObject = previousObject._iNext; - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - var updateLast = this; - - var prevLast = this.last; - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = end; - } - updateLast = updateLast.parent; - } - - this.first = start; - - // if webGL... - if(this.__renderGroup) - { - this.__renderGroup.addFilterBlocks(start, end); - } - -} - -/* - * Removes the filter to this displayObject - * - * @method removeFilter - * @private - */ -PIXI.DisplayObject.prototype.removeFilter = function(data) -{ - //if(!this.filter)return; - //this.filter = false; - console.log("YUOIO") - // modify the list.. - var startBlock = data.start; - - - var nextObject = startBlock._iNext; - var previousObject = startBlock._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - if(previousObject)previousObject._iNext = nextObject; - - this.first = startBlock._iNext; - - // remove the end filter - var lastBlock = data.end; - - var nextObject = lastBlock._iNext; - var previousObject = lastBlock._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - - // this is always true too! - var tempLast = lastBlock._iPrev; - // need to make sure the parents last is updated too - var updateLast = this; - while(updateLast.last == lastBlock) - { - updateLast.last = tempLast; - updateLast = updateLast.parent; - if(!updateLast)break; - } - - // if webGL... - if(this.__renderGroup) - { - this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); - } -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.DisplayObject.prototype.updateTransform = function() -{ - // TODO OPTIMIZE THIS!! with dirty - if(this.rotation !== this.rotationCache) - { - this.rotationCache = this.rotation; - this._sr = Math.sin(this.rotation); - this._cr = Math.cos(this.rotation); - } - - var localTransform = this.localTransform; - var parentTransform = this.parent.worldTransform; - var worldTransform = this.worldTransform; - //console.log(localTransform) - localTransform[0] = this._cr * this.scale.x; - localTransform[1] = -this._sr * this.scale.y - localTransform[3] = this._sr * this.scale.x; - localTransform[4] = this._cr * this.scale.y; - - // TODO --> do we even need a local matrix??? - - var px = this.pivot.x; - var py = this.pivot.y; - - // Cache the matrix values (makes for huge speed increases!) - var a00 = localTransform[0], a01 = localTransform[1], a02 = this.position.x - localTransform[0] * px - py * localTransform[1], - a10 = localTransform[3], a11 = localTransform[4], a12 = this.position.y - localTransform[4] * py - px * localTransform[3], - - b00 = parentTransform[0], b01 = parentTransform[1], b02 = parentTransform[2], - b10 = parentTransform[3], b11 = parentTransform[4], b12 = parentTransform[5]; - - localTransform[2] = a02 - localTransform[5] = a12 - - worldTransform[0] = b00 * a00 + b01 * a10; - worldTransform[1] = b00 * a01 + b01 * a11; - worldTransform[2] = b00 * a02 + b01 * a12 + b02; - - worldTransform[3] = b10 * a00 + b11 * a10; - worldTransform[4] = b10 * a01 + b11 * a11; - worldTransform[5] = b10 * a02 + b11 * a12 + b12; - - // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! - // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); - this.worldAlpha = this.alpha * this.parent.worldAlpha; - - this.vcount = PIXI.visibleCount; - -} - -PIXI.visibleCount = 0; -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * A DisplayObjectContainer represents a collection of display objects. - * It is the base class of all display objects that act as a container for other objects. - * - * @class DisplayObjectContainer - * @extends DisplayObject - * @constructor - */ -PIXI.DisplayObjectContainer = function() -{ - PIXI.DisplayObject.call( this ); - - /** - * [read-only] The of children of this container. - * - * @property children - * @type Array - * @readOnly - */ - this.children = []; -} - -// constructor -PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); -PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; - -/** - * Adds a child to the container. - * - * @method addChild - * @param child {DisplayObject} The DisplayObject to add to the container - */ -PIXI.DisplayObjectContainer.prototype.addChild = function(child) -{ - if(child.parent != undefined) - { - - //// COULD BE THIS??? - child.parent.removeChild(child); - // return; - } - - child.parent = this; - - this.children.push(child); - - // update the stage refference.. - - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = this.stage; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // LINKED LIST // - - // modify the list.. - var childFirst = child.first - var childLast = child.last; - var nextObject; - var previousObject; - - // this could be wrong if there is a filter?? - if(this._filters) - { - previousObject = this.last._iPrev; - } - else - { - previousObject = this.last; - } - - nextObject = previousObject._iNext; - - // always true in this case - // need to make sure the parents last is updated too - var updateLast = this; - var prevLast = previousObject; - - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = child.last; - } - updateLast = updateLast.parent; - } - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - // need to remove any render groups.. - if(this.__renderGroup) - { - // being used by a renderTexture.. if it exists then it must be from a render texture; - if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); - // add them to the new render group.. - this.__renderGroup.addDisplayObjectAndChildren(child); - } - -} - -/** - * Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown - * - * @method addChildAt - * @param child {DisplayObject} The child to add - * @param index {Number} The index to place the child in - */ -PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) -{ - if(index >= 0 && index <= this.children.length) - { - if(child.parent != undefined) - { - child.parent.removeChild(child); - } - child.parent = this; - - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = this.stage; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // modify the list.. - var childFirst = child.first; - var childLast = child.last; - var nextObject; - var previousObject; - - if(index == this.children.length) - { - previousObject = this.last; - var updateLast = this; - var prevLast = this.last; - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = child.last; - } - updateLast = updateLast.parent; - } - } - else if(index == 0) - { - previousObject = this; - } - else - { - previousObject = this.children[index-1].last; - } - - nextObject = previousObject._iNext; - - // always true in this case - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - this.children.splice(index, 0, child); - // need to remove any render groups.. - if(this.__renderGroup) - { - // being used by a renderTexture.. if it exists then it must be from a render texture; - if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); - // add them to the new render group.. - this.__renderGroup.addDisplayObjectAndChildren(child); - } - - } - else - { - throw new Error(child + " The index "+ index +" supplied is out of bounds " + this.children.length); - } -} - -/** - * [NYI] Swaps the depth of 2 displayObjects - * - * @method swapChildren - * @param child {DisplayObject} - * @param child2 {DisplayObject} - * @private - */ -PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2) -{ - /* - * this funtion needs to be recoded.. - * can be done a lot faster.. - */ - return; - - // need to fix this function :/ - /* - // TODO I already know this?? - var index = this.children.indexOf( child ); - var index2 = this.children.indexOf( child2 ); - - if ( index !== -1 && index2 !== -1 ) - { - // cool - - /* - if(this.stage) - { - // this is to satisfy the webGL batching.. - // TODO sure there is a nicer way to achieve this! - this.stage.__removeChild(child); - this.stage.__removeChild(child2); - - this.stage.__addChild(child); - this.stage.__addChild(child2); - } - - // swap the positions.. - this.children[index] = child2; - this.children[index2] = child; - - } - else - { - throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); - }*/ -} - -/** - * Returns the Child at the specified index - * - * @method getChildAt - * @param index {Number} The index to get the child from - */ -PIXI.DisplayObjectContainer.prototype.getChildAt = function(index) -{ - if(index >= 0 && index < this.children.length) - { - return this.children[index]; - } - else - { - throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); - } -} - -/** - * Removes a child from the container. - * - * @method removeChild - * @param child {DisplayObject} The DisplayObject to remove - */ -PIXI.DisplayObjectContainer.prototype.removeChild = function(child) -{ - var index = this.children.indexOf( child ); - if ( index !== -1 ) - { - // unlink // - // modify the list.. - var childFirst = child.first; - var childLast = child.last; - - var nextObject = childLast._iNext; - var previousObject = childFirst._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - - if(this.last == childLast) - { - var tempLast = childFirst._iPrev; - // need to make sure the parents last is updated too - var updateLast = this; - while(updateLast.last == childLast.last) - { - updateLast.last = tempLast; - updateLast = updateLast.parent; - if(!updateLast)break; - } - } - - childLast._iNext = null; - childFirst._iPrev = null; - - // update the stage reference.. - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = null; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // webGL trim - if(child.__renderGroup) - { - child.__renderGroup.removeDisplayObjectAndChildren(child); - } - - child.parent = undefined; - this.children.splice( index, 1 ); - } - else - { - throw new Error(child + " The supplied DisplayObject must be a child of the caller " + this); - } -} - -/* - * Updates the container's children's transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.DisplayObjectContainer.prototype.updateTransform = function() -{ - if(!this.visible)return; - - PIXI.DisplayObject.prototype.updateTransform.call( this ); - - for(var i=0,j=this.children.length; i} an array of {Texture} objects that make up the animation - */ -PIXI.MovieClip = function(textures) -{ - PIXI.Sprite.call(this, textures[0]); - - /** - * The array of textures that make up the animation - * - * @property textures - * @type Array - */ - this.textures = textures; - - /** - * The speed that the MovieClip will play at. Higher is faster, lower is slower - * - * @property animationSpeed - * @type Number - * @default 1 - */ - this.animationSpeed = 1; - - /** - * Whether or not the movie clip repeats after playing. - * - * @property loop - * @type Boolean - * @default true - */ - this.loop = true; - - /** - * Function to call when a MovieClip finishes playing - * - * @property onComplete - * @type Function - */ - this.onComplete = null; - - /** - * [read-only] The index MovieClips current frame (this may not have to be a whole number) - * - * @property currentFrame - * @type Number - * @default 0 - * @readOnly - */ - this.currentFrame = 0; - - /** - * [read-only] Indicates if the MovieClip is currently playing - * - * @property playing - * @type Boolean - * @readOnly - */ - this.playing = false; -} - -// constructor -PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); -PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; - -/** -* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures -* assigned to the MovieClip. -* -* @property totalFrames -* @type Number -* @default 0 -* @readOnly -*/ -Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { - get: function() { - - return this.textures.length; - } -}); - - -/** - * Stops the MovieClip - * - * @method stop - */ -PIXI.MovieClip.prototype.stop = function() -{ - this.playing = false; -} - -/** - * Plays the MovieClip - * - * @method play - */ -PIXI.MovieClip.prototype.play = function() -{ - this.playing = true; -} - -/** - * Stops the MovieClip and goes to a specific frame - * - * @method gotoAndStop - * @param frameNumber {Number} frame index to stop at - */ -PIXI.MovieClip.prototype.gotoAndStop = function(frameNumber) -{ - this.playing = false; - this.currentFrame = frameNumber; - var round = (this.currentFrame + 0.5) | 0; - this.setTexture(this.textures[round % this.textures.length]); -} - -/** - * Goes to a specific frame and begins playing the MovieClip - * - * @method gotoAndPlay - * @param frameNumber {Number} frame index to start at - */ -PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) -{ - this.currentFrame = frameNumber; - this.playing = true; -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.MovieClip.prototype.updateTransform = function() -{ - PIXI.Sprite.prototype.updateTransform.call(this); - - if(!this.playing)return; - - this.currentFrame += this.animationSpeed; - - var round = (this.currentFrame + 0.5) | 0; - - if(this.loop || round < this.textures.length) - { - this.setTexture(this.textures[round % this.textures.length]); - } - else if(round >= this.textures.length) - { - this.gotoAndStop(this.textures.length - 1); - if(this.onComplete) - { - this.onComplete(); - } - } -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - - -PIXI.FilterBlock = function() -{ - this.visible = true; - this.renderable = true; -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.ColorMatrixFilter = function() -{ - // set the uniforms - this.uniforms = { - matrix: {type: 'mat4', value: [1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1]}, - }; - - this.fragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform float invert;", - "uniform mat4 matrix;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", - "gl_FragColor = gl_FragColor * vColor;", - "}" - ]; - -} - - -Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { - get: function() { - return this.uniforms.matrix.value; - }, - set: function(value) { - this.uniforms.matrix.value = value; - } -}); -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Text Object will create a line(s) of text to split a line you can use "\n" - * - * @class Text - * @extends Sprite - * @constructor - * @param text {String} The copy that you would like the text to display - * @param [style] {Object} The style parameters - * @param [style.font] {String} default "bold 20pt Arial" The style and size of the font - * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - * @param [style.stroke] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" - * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) - * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used - * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap - */ -PIXI.Text = function(text, style) -{ - this.canvas = document.createElement("canvas"); - this.context = this.canvas.getContext("2d"); - PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas)); - - this.setText(text); - this.setStyle(style); - - this.updateText(); - this.dirty = false; -}; - -// constructor -PIXI.Text.prototype = Object.create(PIXI.Sprite.prototype); -PIXI.Text.prototype.constructor = PIXI.Text; - -/** - * Set the style of the text - * - * @method setStyle - * @param [style] {Object} The style parameters - * @param [style.font="bold 20pt Arial"] {String} The style and size of the font - * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - * @param [style.stroke="black"] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" - * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) - * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used - * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap - */ -PIXI.Text.prototype.setStyle = function(style) -{ - style = style || {}; - style.font = style.font || "bold 20pt Arial"; - style.fill = style.fill || "black"; - style.align = style.align || "left"; - style.stroke = style.stroke || "black"; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136 - style.strokeThickness = style.strokeThickness || 0; - style.wordWrap = style.wordWrap || false; - style.wordWrapWidth = style.wordWrapWidth || 100; - this.style = style; - this.dirty = true; -}; - -/** - * Set the copy for the text object. To split a line you can use "\n" - * - * @methos setText - * @param {String} text The copy that you would like the text to display - */ -PIXI.Text.prototype.setText = function(text) -{ - this.text = text.toString() || " "; - this.dirty = true; -}; - -/** - * Renders text - * - * @method updateText - * @private - */ -PIXI.Text.prototype.updateText = function() -{ - this.context.font = this.style.font; - - var outputText = this.text; - - // word wrap - // preserve original text - if(this.style.wordWrap)outputText = this.wordWrap(this.text); - - //split text into lines - var lines = outputText.split(/(?:\r\n|\r|\n)/); - - //calculate text width - var lineWidths = []; - var maxLineWidth = 0; - for (var i = 0; i < lines.length; i++) - { - var lineWidth = this.context.measureText(lines[i]).width; - lineWidths[i] = lineWidth; - maxLineWidth = Math.max(maxLineWidth, lineWidth); - } - this.canvas.width = maxLineWidth + this.style.strokeThickness; - - //calculate text height - var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; - this.canvas.height = lineHeight * lines.length; - - //set canvas text styles - this.context.fillStyle = this.style.fill; - this.context.font = this.style.font; - - this.context.strokeStyle = this.style.stroke; - this.context.lineWidth = this.style.strokeThickness; - - this.context.textBaseline = "top"; - - //draw lines line by line - for (i = 0; i < lines.length; i++) - { - var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); - - if(this.style.align == "right") - { - linePosition.x += maxLineWidth - lineWidths[i]; - } - else if(this.style.align == "center") - { - linePosition.x += (maxLineWidth - lineWidths[i]) / 2; - } - - if(this.style.stroke && this.style.strokeThickness) - { - this.context.strokeText(lines[i], linePosition.x, linePosition.y); - } - - if(this.style.fill) - { - this.context.fillText(lines[i], linePosition.x, linePosition.y); - } - } - - this.updateTexture(); -}; - -/** - * Updates texture size based on canvas size - * - * @method updateTexture - * @private - */ -PIXI.Text.prototype.updateTexture = function() -{ - this.texture.baseTexture.width = this.canvas.width; - this.texture.baseTexture.height = this.canvas.height; - this.texture.frame.width = this.canvas.width; - this.texture.frame.height = this.canvas.height; - - this._width = this.canvas.width; - this._height = this.canvas.height; - - PIXI.texturesToUpdate.push(this.texture.baseTexture); -}; - -/** - * Updates the transfor of this object - * - * @method updateTransform - * @private - */ -PIXI.Text.prototype.updateTransform = function() -{ - if(this.dirty) - { - this.updateText(); - this.dirty = false; - } - - PIXI.Sprite.prototype.updateTransform.call(this); -}; - -/* - * http://stackoverflow.com/users/34441/ellisbben - * great solution to the problem! - * - * @method determineFontHeight - * @param fontStyle {Object} - * @private - */ -PIXI.Text.prototype.determineFontHeight = function(fontStyle) -{ - // build a little reference dictionary so if the font style has been used return a - // cached version... - var result = PIXI.Text.heightCache[fontStyle]; - - if(!result) - { - var body = document.getElementsByTagName("body")[0]; - var dummy = document.createElement("div"); - var dummyText = document.createTextNode("M"); - dummy.appendChild(dummyText); - dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); - body.appendChild(dummy); - - result = dummy.offsetHeight; - PIXI.Text.heightCache[fontStyle] = result; - - body.removeChild(dummy); - } - - return result; -}; - -/** - * A Text Object will apply wordwrap - * - * @method wordWrap - * @param text {String} - * @private - */ -PIXI.Text.prototype.wordWrap = function(text) -{ - // search good wrap position - var searchWrapPos = function(ctx, text, start, end, wrapWidth) - { - var p = Math.floor((end-start) / 2) + start; - if(p == start) { - return 1; - } - - if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) - { - if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) - { - return p; - } - else - { - return arguments.callee(ctx, text, p, end, wrapWidth); - } - } - else - { - return arguments.callee(ctx, text, start, p, wrapWidth); - } - }; - - var lineWrap = function(ctx, text, wrapWidth) - { - if(ctx.measureText(text).width <= wrapWidth || text.length < 1) - { - return text; - } - var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); - return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); - }; - - var result = ""; - var lines = text.split("\n"); - for (var i = 0; i < lines.length; i++) - { - result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; - } - - return result; -}; - -/** - * Destroys this text object - * - * @method destroy - * @param destroyTexture {Boolean} - */ -PIXI.Text.prototype.destroy = function(destroyTexture) -{ - if(destroyTexture) - { - this.texture.destroy(); - } - -}; - -PIXI.Text.heightCache = {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" - * You can generate the fnt files using - * http://www.angelcode.com/products/bmfont/ for windows or - * http://www.bmglyph.com/ for mac. - * - * @class BitmapText - * @extends DisplayObjectContainer - * @constructor - * @param text {String} The copy that you would like the text to display - * @param style {Object} The style parameters - * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - */ -PIXI.BitmapText = function(text, style) -{ - PIXI.DisplayObjectContainer.call(this); - - this.setText(text); - this.setStyle(style); - this.updateText(); - this.dirty = false - -}; - -// constructor -PIXI.BitmapText.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); -PIXI.BitmapText.prototype.constructor = PIXI.BitmapText; - -/** - * Set the copy for the text object - * - * @method setText - * @param text {String} The copy that you would like the text to display - */ -PIXI.BitmapText.prototype.setText = function(text) -{ - this.text = text || " "; - this.dirty = true; -}; - -/** - * Set the style of the text - * - * @method setStyle - * @param style {Object} The style parameters - * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - */ -PIXI.BitmapText.prototype.setStyle = function(style) -{ - style = style || {}; - style.align = style.align || "left"; - this.style = style; - - var font = style.font.split(" "); - this.fontName = font[font.length - 1]; - this.fontSize = font.length >= 2 ? parseInt(font[font.length - 2], 10) : PIXI.BitmapText.fonts[this.fontName].size; - - this.dirty = true; -}; - -/** - * Renders text - * - * @method updateText - * @private - */ -PIXI.BitmapText.prototype.updateText = function() -{ - var data = PIXI.BitmapText.fonts[this.fontName]; - var pos = new PIXI.Point(); - var prevCharCode = null; - var chars = []; - var maxLineWidth = 0; - var lineWidths = []; - var line = 0; - var scale = this.fontSize / data.size; - for(var i = 0; i < this.text.length; i++) - { - var charCode = this.text.charCodeAt(i); - if(/(?:\r\n|\r|\n)/.test(this.text.charAt(i))) - { - lineWidths.push(pos.x); - maxLineWidth = Math.max(maxLineWidth, pos.x); - line++; - - pos.x = 0; - pos.y += data.lineHeight; - prevCharCode = null; - continue; - } - - var charData = data.chars[charCode]; - if(!charData) continue; - - if(prevCharCode && charData[prevCharCode]) - { - pos.x += charData.kerning[prevCharCode]; - } - chars.push({texture:charData.texture, line: line, charCode: charCode, position: new PIXI.Point(pos.x + charData.xOffset, pos.y + charData.yOffset)}); - pos.x += charData.xAdvance; - - prevCharCode = charCode; - } - - lineWidths.push(pos.x); - maxLineWidth = Math.max(maxLineWidth, pos.x); - - var lineAlignOffsets = []; - for(i = 0; i <= line; i++) - { - var alignOffset = 0; - if(this.style.align == "right") - { - alignOffset = maxLineWidth - lineWidths[i]; - } - else if(this.style.align == "center") - { - alignOffset = (maxLineWidth - lineWidths[i]) / 2; - } - lineAlignOffsets.push(alignOffset); - } - - for(i = 0; i < chars.length; i++) - { - var c = new PIXI.Sprite(chars[i].texture)//PIXI.Sprite.fromFrame(chars[i].charCode); - c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale; - c.position.y = chars[i].position.y * scale; - c.scale.x = c.scale.y = scale; - this.addChild(c); - } - - this.width = pos.x * scale; - this.height = (pos.y + data.lineHeight) * scale; -}; - -/** - * Updates the transfor of this object - * - * @method updateTransform - * @private - */ -PIXI.BitmapText.prototype.updateTransform = function() -{ - if(this.dirty) - { - while(this.children.length > 0) - { - this.removeChild(this.getChildAt(0)); - } - this.updateText(); - - this.dirty = false; - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -}; - -PIXI.BitmapText.fonts = {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - /** - * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive - * This manager also supports multitouch. - * - * @class InteractionManager - * @constructor - * @param stage {Stage} The stage to handle interactions - */ -PIXI.InteractionManager = function(stage) -{ - /** - * a refference to the stage - * - * @property stage - * @type Stage - */ - this.stage = stage; - - /** - * the mouse data - * - * @property mouse - * @type InteractionData - */ - this.mouse = new PIXI.InteractionData(); - - /** - * an object that stores current touches (InteractionData) by id reference - * - * @property touchs - * @type Object - */ - this.touchs = {}; - - - - // helpers - this.tempPoint = new PIXI.Point(); - //this.tempMatrix = mat3.create(); - - this.mouseoverEnabled = true; - - //tiny little interactiveData pool! - this.pool = []; - - this.interactiveItems = []; - this.interactionDOMElement = null; - - //this will make it so that you dont have to call bind all the time - this.onMouseMove = this.onMouseMove.bind( this ); - this.onMouseDown = this.onMouseDown.bind(this); - this.onMouseOut = this.onMouseOut.bind(this); - this.onMouseUp = this.onMouseUp.bind(this); - - this.onTouchStart = this.onTouchStart.bind(this); - this.onTouchEnd = this.onTouchEnd.bind(this); - this.onTouchMove = this.onTouchMove.bind(this); - - - this.last = 0; -} - -// constructor -PIXI.InteractionManager.prototype.constructor = PIXI.InteractionManager; - -/** - * Collects an interactive sprite recursively to have their interactions managed - * - * @method collectInteractiveSprite - * @param displayObject {DisplayObject} the displayObject to collect - * @param iParent {DisplayObject} - * @private - */ -PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObject, iParent) -{ - var children = displayObject.children; - var length = children.length; - - /// make an interaction tree... {item.__interactiveParent} - for (var i = length-1; i >= 0; i--) - { - var child = children[i]; - -// if(child.visible) { - // push all interactive bits - if(child.interactive) - { - iParent.interactiveChildren = true; - //child.__iParent = iParent; - this.interactiveItems.push(child); - - if(child.children.length > 0) - { - this.collectInteractiveSprite(child, child); - } - } - else - { - child.__iParent = null; - - if(child.children.length > 0) - { - this.collectInteractiveSprite(child, iParent); - } - } -// } - } -} - -/** - * Sets the target for event delegation - * - * @method setTarget - * @param target {WebGLRenderer|CanvasRenderer} the renderer to bind events to - * @private - */ -PIXI.InteractionManager.prototype.setTarget = function(target) -{ - this.target = target; - - //check if the dom element has been set. If it has don't do anything - if( this.interactionDOMElement === null ) { - - this.setTargetDomElement( target.view ); - } - - document.body.addEventListener('mouseup', this.onMouseUp, true); -} - - -/** - * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM - * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element - * to receive those events - * - * @method setTargetDomElement - * @param domElement {DOMElement} the dom element which will receive mouse and touch events - * @private - */ -PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) -{ - //remove previouse listeners - if( this.interactionDOMElement !== null ) - { - this.interactionDOMElement.style['-ms-content-zooming'] = ''; - this.interactionDOMElement.style['-ms-touch-action'] = ''; - - this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); - this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); - this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); - - // aint no multi touch just yet! - this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); - this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); - this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); - } - - - if (window.navigator.msPointerEnabled) - { - // time to remove some of that zoom in ja.. - domElement.style['-ms-content-zooming'] = 'none'; - domElement.style['-ms-touch-action'] = 'none'; - - // DO some window specific touch! - } - - this.interactionDOMElement = domElement; - - domElement.addEventListener('mousemove', this.onMouseMove, true); - domElement.addEventListener('mousedown', this.onMouseDown, true); - domElement.addEventListener('mouseout', this.onMouseOut, true); - - // aint no multi touch just yet! - domElement.addEventListener('touchstart', this.onTouchStart, true); - domElement.addEventListener('touchend', this.onTouchEnd, true); - domElement.addEventListener('touchmove', this.onTouchMove, true); -} - - -/** - * updates the state of interactive objects - * - * @method update - * @private - */ -PIXI.InteractionManager.prototype.update = function() -{ - if(!this.target)return; - - // frequency of 30fps?? - var now = Date.now(); - var diff = now - this.last; - diff = (diff * 30) / 1000; - if(diff < 1)return; - this.last = now; - // - - // ok.. so mouse events?? - // yes for now :) - // OPTIMSE - how often to check?? - if(this.dirty) - { - this.dirty = false; - - var len = this.interactiveItems.length; - - for (var i=0; i < len; i++) { - this.interactiveItems[i].interactiveChildren = false; - } - - this.interactiveItems = []; - - if(this.stage.interactive)this.interactiveItems.push(this.stage); - // go through and collect all the objects that are interactive.. - this.collectInteractiveSprite(this.stage, this.stage); - } - - // loop through interactive objects! - var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - - //if(!item.visible)continue; - - // OPTIMISATION - only calculate every time if the mousemove function exists.. - // OK so.. does the object have any other interactive functions? - // hit-test the clip! - - - if(item.mouseover || item.mouseout || item.buttonMode) - { - // ok so there are some functions so lets hit test it.. - item.__hit = this.hitTest(item, this.mouse); - this.mouse.target = item; - // ok so deal with interactions.. - // loks like there was a hit! - if(item.__hit) - { - if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; - - if(!item.__isOver) - { - - if(item.mouseover)item.mouseover(this.mouse); - item.__isOver = true; - } - } - else - { - if(item.__isOver) - { - // roll out! - if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; - } - } - } - - // ---> - } -} - -/** - * Is called when the mouse moves accross the renderer element - * - * @method onMouseMove - * @param event {Event} The DOM event of the mouse moving - * @private - */ -PIXI.InteractionManager.prototype.onMouseMove = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - // TODO optimize by not check EVERY TIME! maybe half as often? // - var rect = this.interactionDOMElement.getBoundingClientRect(); - - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); - - var length = this.interactiveItems.length; - var global = this.mouse.global; - - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mousemove) - { - //call the function! - item.mousemove(this.mouse); - } - } -} - -/** - * Is called when the mouse button is pressed down on the renderer element - * - * @method onMouseDown - * @param event {Event} The DOM event of a mouse button being pressed down - * @private - */ -PIXI.InteractionManager.prototype.onMouseDown = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - - // loop through inteaction tree... - // hit test each item! -> - // get interactive items under point?? - //stage.__i - var length = this.interactiveItems.length; - var global = this.mouse.global; - - var index = 0; - var parent = this.stage; - - // while - // hit test - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mousedown || item.click) - { - item.__mouseIsDown = true; - item.__hit = this.hitTest(item, this.mouse); - - if(item.__hit) - { - //call the function! - if(item.mousedown)item.mousedown(this.mouse); - item.__isDown = true; - - // just the one! - if(!item.interactiveChildren)break; - } - } - } -} - - -PIXI.InteractionManager.prototype.onMouseOut = function(event) -{ - var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.__isOver) - { - this.mouse.target = item; - if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; - } - } -} - -/** - * Is called when the mouse button is released on the renderer element - * - * @method onMouseUp - * @param event {Event} The DOM event of a mouse button being released - * @private - */ -PIXI.InteractionManager.prototype.onMouseUp = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - - var global = this.mouse.global; - - - var length = this.interactiveItems.length; - var up = false; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mouseup || item.mouseupoutside || item.click) - { - item.__hit = this.hitTest(item, this.mouse); - - if(item.__hit && !up) - { - //call the function! - if(item.mouseup) - { - item.mouseup(this.mouse); - } - if(item.__isDown) - { - if(item.click)item.click(this.mouse); - } - - if(!item.interactiveChildren)up = true; - } - else - { - if(item.__isDown) - { - if(item.mouseupoutside)item.mouseupoutside(this.mouse); - } - } - - item.__isDown = false; - } - } -} - -/** - * Tests if the current mouse coords hit a sprite - * - * @method hitTest - * @param item {DisplayObject} The displayObject to test for a hit - * @param interactionData {InteractionData} The interactiondata object to update in the case of a hit - * @private - */ -PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) -{ - var global = interactionData.global; - - if(item.vcount !== PIXI.visibleCount)return false; - - var isSprite = (item instanceof PIXI.Sprite), - worldTransform = item.worldTransform, - a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10), - x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, - y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - interactionData.target = item; - - //a sprite or display object with a hit area defined - if(item.hitArea && item.hitArea.contains) { - if(item.hitArea.contains(x, y)) { - //if(isSprite) - interactionData.target = item; - - return true; - } - - return false; - } - // a sprite with no hitarea defined - else if(isSprite) - { - var width = item.texture.frame.width, - height = item.texture.frame.height, - x1 = -width * item.anchor.x, - y1; - - if(x > x1 && x < x1 + width) - { - y1 = -height * item.anchor.y; - - if(y > y1 && y < y1 + height) - { - // set the target property if a hit is true! - interactionData.target = item - return true; - } - } - } - - var length = item.children.length; - - for (var i = 0; i < length; i++) - { - var tempItem = item.children[i]; - var hit = this.hitTest(tempItem, interactionData); - if(hit) - { - // hmm.. TODO SET CORRECT TARGET? - interactionData.target = item - return true; - } - } - - return false; -} - -/** - * Is called when a touch is moved accross the renderer element - * - * @method onTouchMove - * @param event {Event} The DOM event of a touch moving accross the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchMove = function(event) -{ - var rect = this.interactionDOMElement.getBoundingClientRect(); - var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - var touchData = this.touchs[touchEvent.identifier]; - touchData.originalEvent = event || window.event; - - // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - } - - var length = this.interactiveItems.length; - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - if(item.touchmove)item.touchmove(touchData); - } -} - -/** - * Is called when a touch is started on the renderer element - * - * @method onTouchStart - * @param event {Event} The DOM event of a touch starting on the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchStart = function(event) -{ - var rect = this.interactionDOMElement.getBoundingClientRect(); - - var changedTouches = event.changedTouches; - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - - var touchData = this.pool.pop(); - if(!touchData)touchData = new PIXI.InteractionData(); - - touchData.originalEvent = event || window.event; - - this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - - var length = this.interactiveItems.length; - - for (var j = 0; j < length; j++) - { - var item = this.interactiveItems[j]; - - if(item.touchstart || item.tap) - { - item.__hit = this.hitTest(item, touchData); - - if(item.__hit) - { - //call the function! - if(item.touchstart)item.touchstart(touchData); - item.__isDown = true; - item.__touchData = touchData; - - if(!item.interactiveChildren)break; - } - } - } - } -} - -/** - * Is called when a touch is ended on the renderer element - * - * @method onTouchEnd - * @param event {Event} The DOM event of a touch ending on the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchEnd = function(event) -{ - //this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.interactionDOMElement.getBoundingClientRect(); - var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - var touchData = this.touchs[touchEvent.identifier]; - var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - - var length = this.interactiveItems.length; - for (var j = 0; j < length; j++) - { - var item = this.interactiveItems[j]; - var itemTouchData = item.__touchData; // <-- Here! - item.__hit = this.hitTest(item, touchData); - - if(itemTouchData == touchData) - { - // so this one WAS down... - touchData.originalEvent = event || window.event; - // hitTest?? - - if(item.touchend || item.tap) - { - if(item.__hit && !up) - { - if(item.touchend)item.touchend(touchData); - if(item.__isDown) - { - if(item.tap)item.tap(touchData); - } - - if(!item.interactiveChildren)up = true; - } - else - { - if(item.__isDown) - { - if(item.touchendoutside)item.touchendoutside(touchData); - } - } - - item.__isDown = false; - } - - item.__touchData = null; - - } - else - { - - } - } - // remove the touch.. - this.pool.push(touchData); - this.touchs[touchEvent.identifier] = null; - } -} - -/** - * Holds all information related to an Interaction event - * - * @class InteractionData - * @constructor - */ -PIXI.InteractionData = function() -{ - /** - * This point stores the global coords of where the touch/mouse event happened - * - * @property global - * @type Point - */ - this.global = new PIXI.Point(); - - // this is here for legacy... but will remove - this.local = new PIXI.Point(); - - /** - * The target Sprite that was interacted with - * - * @property target - * @type Sprite - */ - this.target; - - /** - * When passed to an event handler, this will be the original DOM Event that was captured - * - * @property originalEvent - * @type Event - */ - this.originalEvent; -} - -/** - * This will return the local coords of the specified displayObject for this InteractionData - * - * @method getLocalPosition - * @param displayObject {DisplayObject} The DisplayObject that you would like the local coords off - * @return {Point} A point containing the coords of the InteractionData position relative to the DisplayObject - */ -PIXI.InteractionData.prototype.getLocalPosition = function(displayObject) -{ - var worldTransform = displayObject.worldTransform; - var global = this.global; - - // do a cheeky transform to get the mouse coords; - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - // set the mouse coords... - return new PIXI.Point(a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, - a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id) -} - -// constructor -PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Stage represents the root of the display tree. Everything connected to the stage is rendered - * - * @class Stage - * @extends DisplayObjectContainer - * @constructor - * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format - * like: 0xFFFFFF for white - */ -PIXI.Stage = function(backgroundColor) -{ - PIXI.DisplayObjectContainer.call( this ); - - /** - * [read-only] Current transform of the object based on world (parent) factors - * - * @property worldTransform - * @type Mat3 - * @readOnly - * @private - */ - this.worldTransform = PIXI.mat3.create(); - - /** - * Whether or not the stage is interactive - * - * @property interactive - * @type Boolean - */ - this.interactive = true; - - /** - * The interaction manage for this stage, manages all interactive activity on the stage - * - * @property interactive - * @type InteractionManager - */ - this.interactionManager = new PIXI.InteractionManager(this); - - /** - * Whether the stage is dirty and needs to have interactions updated - * - * @property dirty - * @type Boolean - * @private - */ - this.dirty = true; - - this.__childrenAdded = []; - this.__childrenRemoved = []; - - //the stage is it's own stage - this.stage = this; - - //optimize hit detection a bit - this.stage.hitArea = new PIXI.Rectangle(0,0,100000, 100000); - - this.setBackgroundColor(backgroundColor); - this.worldVisible = true; -} - -// constructor -PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Stage.prototype.constructor = PIXI.Stage; - -/** - * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. - * This is useful for when you have other DOM elements ontop of the Canvas element. - * - * @method setInteractionDelegate - * @param domElement {DOMElement} This new domElement which will receive mouse/touch events - */ -PIXI.Stage.prototype.setInteractionDelegate = function(domElement) -{ - this.interactionManager.setTargetDomElement( domElement ); -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.Stage.prototype.updateTransform = function() -{ - this.worldAlpha = 1; - this.vcount = PIXI.visibleCount; - - for(var i=0,j=this.children.length; i> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; -} - -/** - * A polyfill for Function.prototype.bind - * - * @method bind - */ -if (typeof Function.prototype.bind != 'function') { - Function.prototype.bind = (function () { - var slice = Array.prototype.slice; - return function (thisArg) { - var target = this, boundArgs = slice.call(arguments, 1); - - if (typeof target != 'function') throw new TypeError(); - - function bound() { - var args = boundArgs.concat(slice.call(arguments)); - target.apply(this instanceof bound ? this : thisArg, args); - } - - bound.prototype = (function F(proto) { - proto && (F.prototype = proto); - if (!(this instanceof F)) return new F; - })(target.prototype); - - return bound; - }; - })(); -} - -/** - * A wrapper for ajax requests to be handled cross browser - * - * @class AjaxRequest - * @constructor - */ -var AjaxRequest = PIXI.AjaxRequest = function() -{ - var activexmodes = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Microsoft.XMLHTTP"] //activeX versions to check for in IE - - if (window.ActiveXObject) - { //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken) - for (var i=0; i>>>>>>>>") - console.log("_") - var safe = 0; - var tmp = item.first; - console.log(tmp); - - while(tmp._iNext) - { - safe++; - tmp = tmp._iNext; - console.log(tmp); - // console.log(tmp); - - if(safe > 100) - { - console.log("BREAK") - break - } - } -} - - - - - - -/** - * https://github.com/mrdoob/eventtarget.js/ - * THankS mr DOob! - */ - -/** - * Adds event emitter functionality to a class - * - * @class EventTarget - * @example - * function MyEmitter() { - * PIXI.EventTarget.call(this); //mixes in event target stuff - * } - * - * var em = new MyEmitter(); - * em.emit({ type: 'eventName', data: 'some data' }); - */ -PIXI.EventTarget = function () { - - var listeners = {}; - - this.addEventListener = this.on = function ( type, listener ) { - - - if ( listeners[ type ] === undefined ) { - - listeners[ type ] = []; - - } - - if ( listeners[ type ].indexOf( listener ) === - 1 ) { - - listeners[ type ].push( listener ); - } - - }; - - this.dispatchEvent = this.emit = function ( event ) { - - if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { - - return; - - } - - for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { - - listeners[ event.type ][ i ]( event ); - - } - - }; - - this.removeEventListener = this.off = function ( type, listener ) { - - var index = listeners[ type ].indexOf( listener ); - - if ( index !== - 1 ) { - - listeners[ type ].splice( index, 1 ); - - } - - }; - -}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * This helper function will automatically detect which renderer you should be using. - * WebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by - * the browser then this function will return a canvas renderer - * - * @method autoDetectRenderer - * @static - * @param width {Number} the width of the renderers view - * @param height {Number} the height of the renderers view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) - * - * antialias - */ -PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) -{ - if(!width)width = 800; - if(!height)height = 600; - - // BORROWED from Mr Doob (mrdoob.com) - var webgl = ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(); - - //console.log(webgl); - if( webgl ) - { - return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); - } - - return new PIXI.CanvasRenderer(width, height, view, transparent); -}; - - - -/* - PolyK library - url: http://polyk.ivank.net - Released under MIT licence. - - Copyright (c) 2012 Ivan Kuckir - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - - This is an amazing lib! - - slightly modified by mat groves (matgroves.com); -*/ - -PIXI.PolyK = {}; - -/** - * Triangulates shapes for webGL graphic fills - * - * @method Triangulate - * @namespace PolyK - * @constructor - */ -PIXI.PolyK.Triangulate = function(p) -{ - var sign = true; - - var n = p.length>>1; - if(n<3) return []; - var tgs = []; - var avl = []; - for(var i=0; i 3) - { - var i0 = avl[(i+0)%al]; - var i1 = avl[(i+1)%al]; - var i2 = avl[(i+2)%al]; - - var ax = p[2*i0], ay = p[2*i0+1]; - var bx = p[2*i1], by = p[2*i1+1]; - var cx = p[2*i2], cy = p[2*i2+1]; - - var earFound = false; - if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) - { - earFound = true; - for(var j=0; j 3*al) - { - // need to flip flip reverse it! - // reset! - if(sign) - { - var tgs = []; - avl = []; - for(var i=0; i= 0) && (v >= 0) && (u + v < 1); -} - -/** - * Checks if a shape is convex - * - * @class _convex - * @namespace PolyK - * @private - */ -PIXI.PolyK._convex = function(ax, ay, bx, by, cx, cy, sign) -{ - return ((ay-by)*(cx-bx) + (bx-ax)*(cy-by) >= 0) == sign; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/* - * the default suoer fast shader! - */ - -PIXI.shaderFragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", - "gl_FragColor = gl_FragColor * vColor;", - "}" -]; - -PIXI.shaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - - "uniform vec2 projectionVector;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "void main(void) {", - "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" -]; - -/* - * the triangle strip shader.. - */ - -PIXI.stripShaderFragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform float alpha;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", - "gl_FragColor = gl_FragColor * alpha;", - "}" -]; - - -PIXI.stripShaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" -]; - -/* - * primitive shader.. - */ - -PIXI.primitiveShaderFragmentSrc = [ - "precision mediump float;", - "varying vec4 vColor;", - "void main(void) {", - "gl_FragColor = vColor;", - "}" -]; - -PIXI.primitiveShaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec4 aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "uniform float alpha;", - "varying vec4 vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vColor = aColor * alpha;", - "}" -]; - -PIXI.shaderStack = []; - -PIXI.initPrimitiveShader = function() -{ - var gl = PIXI.gl; - - var shaderProgram = PIXI.compileProgram(PIXI.primitiveShaderVertexSrc, PIXI.primitiveShaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); - - - //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - //gl.enableVertexAttribArray(shaderProgram.colorAttribute); -//gl.enableVertexAttribArray(program.textureCoordAttribute); - - shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); - - PIXI.primitiveProgram = shaderProgram; - - -} - -PIXI.initDefaultShader = function() -{ - PIXI.defaultShader = new PIXI.PixiShader(); - PIXI.defaultShader.init(); - PIXI.activateShader(PIXI.defaultShader); - /* - PIXI.shaderStack.push(PIXI.defaultShader); - PIXI.current*/ -} - -PIXI.initDefaultStripShader = function() -{ - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.stripShaderVertexSrc, PIXI.stripShaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); - shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); - - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.stripShaderProgram = shaderProgram; -} - -PIXI.CompileVertexShader = function(gl, shaderSrc) -{ - return PIXI._CompileShader(gl, shaderSrc, gl.VERTEX_SHADER); -} - -PIXI.CompileFragmentShader = function(gl, shaderSrc) -{ - return PIXI._CompileShader(gl, shaderSrc, gl.FRAGMENT_SHADER); -} - -PIXI._CompileShader = function(gl, shaderSrc, shaderType) -{ - var src = shaderSrc.join("\n"); - var shader = gl.createShader(shaderType); - gl.shaderSource(shader, src); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - alert(gl.getShaderInfoLog(shader)); - return null; - } - - return shader; -} - - -PIXI.compileProgram = function(vertexSrc, fragmentSrc) -{ - var gl = PIXI.gl; - var fragmentShader = PIXI.CompileFragmentShader(gl, fragmentSrc); - var vertexShader = PIXI.CompileVertexShader(gl, vertexSrc); - - var shaderProgram = gl.createProgram(); - - gl.attachShader(shaderProgram, vertexShader); - gl.attachShader(shaderProgram, fragmentShader); - gl.linkProgram(shaderProgram); - - if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { - alert("Could not initialise shaders"); - } - - return shaderProgram; -} - -PIXI.activateShader = function(shader) -{ - PIXI.shaderStack.push(shader); - - //console.log(">>>") - var gl = PIXI.gl; - - var shaderProgram = shader.program; - - // map uniforms.. - gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - - shader.syncUniforms(); - - PIXI.currentShader = shaderProgram; -} - - -PIXI.popShader = function() -{ - var gl = PIXI.gl; - // activate last program.. - var lastProgram = PIXI.shaderStack.pop(); - - var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; - - gl.useProgram(shaderProgram); - - PIXI.currentShader = shaderProgram; -} - -PIXI.activatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.primitiveProgram); - - //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); - //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); - gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); - - //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); - //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); -} - -PIXI.deactivatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.currentShader); - - gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); - //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); - //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -PIXI.PixiShader = function() -{ - // the webGL program.. - this.program; - - this.fragmentSrc = [ - "precision lowp float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", - "}" - ]; - -} - -PIXI.PixiShader.prototype.init = function() -{ - var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) - - var gl = PIXI.gl; - - gl.useProgram(program); - - // get the default shader bits! - program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); - program.colorAttribute = gl.getAttribLocation(program, "aColor"); - program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); - - program.projectionVector = gl.getUniformLocation(program, "projectionVector"); - program.samplerUniform = gl.getUniformLocation(program, "uSampler"); - - // add those custom shaders! - for (var key in this.uniforms) - { - // get the uniform locations.. - program[key] = gl.getUniformLocation(program, key); - } - - this.program = program; -} - -PIXI.PixiShader.prototype.syncUniforms = function() -{ - var gl = PIXI.gl; - - for (var key in this.uniforms) - { - //var - var type = this.uniforms[key].type; - - // need to grow this! - if(type == "f") - { - gl.uniform1f(this.program[key], this.uniforms[key].value); - } - else if(type == "mat4") - { - gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); - } - } - -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A set of functions used by the webGL renderer to draw the primitive graphics data - * - * @class CanvasGraphics - */ -PIXI.WebGLGraphics = function() -{ - -} - -/** - * Renders the graphics object - * - * @static - * @private - * @method renderGraphics - * @param graphics {Graphics} - * @param projection {Object} - */ -PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) -{ - var gl = PIXI.gl; - - if(!graphics._webGL)graphics._webGL = {points:[], indices:[], lastIndex:0, - buffer:gl.createBuffer(), - indexBuffer:gl.createBuffer()}; - - if(graphics.dirty) - { - graphics.dirty = false; - - if(graphics.clearDirty) - { - graphics.clearDirty = false; - - graphics._webGL.lastIndex = 0; - graphics._webGL.points = []; - graphics._webGL.indices = []; - - } - - PIXI.WebGLGraphics.updateGraphics(graphics); - } - - - PIXI.activatePrimitiveShader(); - - // This could be speeded up fo sure! - var m = PIXI.mat3.clone(graphics.worldTransform); - - PIXI.mat3.transpose(m); - - // set the matrix transform for the - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - gl.uniformMatrix3fv(PIXI.primitiveProgram.translationMatrix, false, m); - - gl.uniform2f(PIXI.primitiveProgram.projectionVector, projection.x, projection.y); - - gl.uniform1f(PIXI.primitiveProgram.alpha, graphics.worldAlpha); - - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - - // WHY DOES THIS LINE NEED TO BE THERE??? - //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - // its not even used.. but need to be set or it breaks? - // only on pc though.. - - gl.vertexAttribPointer(PIXI.primitiveProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 4 * 6, 0); - gl.vertexAttribPointer(PIXI.primitiveProgram.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4); - - // set the index buffer! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); - - gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); - - PIXI.deactivatePrimitiveShader(); - - // return to default shader... -// PIXI.activateShader(PIXI.defaultShader); -} - -/** - * Updates the graphics object - * - * @static - * @private - * @method updateGraphics - * @param graphics {Graphics} - */ -PIXI.WebGLGraphics.updateGraphics = function(graphics) -{ - for (var i=graphics._webGL.lastIndex; i < graphics.graphicsData.length; i++) - { - var data = graphics.graphicsData[i]; - - if(data.type == PIXI.Graphics.POLY) - { - if(data.fill) - { - if(data.points.length>3) - PIXI.WebGLGraphics.buildPoly(data, graphics._webGL); - } - - if(data.lineWidth > 0) - { - PIXI.WebGLGraphics.buildLine(data, graphics._webGL); - } - } - else if(data.type == PIXI.Graphics.RECT) - { - PIXI.WebGLGraphics.buildRectangle(data, graphics._webGL); - } - else if(data.type == PIXI.Graphics.CIRC || data.type == PIXI.Graphics.ELIP) - { - PIXI.WebGLGraphics.buildCircle(data, graphics._webGL); - } - }; - - graphics._webGL.lastIndex = graphics.graphicsData.length; - - var gl = PIXI.gl; - - graphics._webGL.glPoints = new Float32Array(graphics._webGL.points); - - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - gl.bufferData(gl.ARRAY_BUFFER, graphics._webGL.glPoints, gl.STATIC_DRAW); - - graphics._webGL.glIndicies = new Uint16Array(graphics._webGL.indices); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.glIndicies, gl.STATIC_DRAW); -} - -/** - * Builds a rectangle to draw - * - * @static - * @private - * @method buildRectangle - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData) -{ - // --- // - // need to convert points to a nice regular data - // - var rectData = graphicsData.points; - var x = rectData[0]; - var y = rectData[1]; - var width = rectData[2]; - var height = rectData[3]; - - - if(graphicsData.fill) - { - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var verts = webGLData.points; - var indices = webGLData.indices; - - var vertPos = verts.length/6; - - // start - verts.push(x, y); - verts.push(r, g, b, alpha); - - verts.push(x + width, y); - verts.push(r, g, b, alpha); - - verts.push(x , y + height); - verts.push(r, g, b, alpha); - - verts.push(x + width, y + height); - verts.push(r, g, b, alpha); - - // insert 2 dead triangles.. - indices.push(vertPos, vertPos, vertPos+1, vertPos+2, vertPos+3, vertPos+3) - } - - if(graphicsData.lineWidth) - { - graphicsData.points = [x, y, - x + width, y, - x + width, y + height, - x, y + height, - x, y]; - - PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); - } - -} - -/** - * Builds a circle to draw - * - * @static - * @private - * @method buildCircle - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData) -{ - // --- // - // need to convert points to a nice regular data - // - var rectData = graphicsData.points; - var x = rectData[0]; - var y = rectData[1]; - var width = rectData[2]; - var height = rectData[3]; - - var totalSegs = 40; - var seg = (Math.PI * 2) / totalSegs ; - - if(graphicsData.fill) - { - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var verts = webGLData.points; - var indices = webGLData.indices; - - var vecPos = verts.length/6; - - indices.push(vecPos); - - for (var i=0; i < totalSegs + 1 ; i++) - { - verts.push(x,y, r, g, b, alpha); - - verts.push(x + Math.sin(seg * i) * width, - y + Math.cos(seg * i) * height, - r, g, b, alpha); - - indices.push(vecPos++, vecPos++); - }; - - indices.push(vecPos-1); - } - - if(graphicsData.lineWidth) - { - graphicsData.points = []; - - for (var i=0; i < totalSegs + 1; i++) - { - graphicsData.points.push(x + Math.sin(seg * i) * width, - y + Math.cos(seg * i) * height) - }; - - PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); - } - -} - -/** - * Builds a line to draw - * - * @static - * @private - * @method buildLine - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) -{ - // TODO OPTIMISE! - - var wrap = true; - var points = graphicsData.points; - if(points.length == 0)return; - - // get first and last point.. figure out the middle! - var firstPoint = new PIXI.Point( points[0], points[1] ); - var lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - - // if the first point is the last point - goona have issues :) - if(firstPoint.x == lastPoint.x && firstPoint.y == lastPoint.y) - { - points.pop(); - points.pop(); - - lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - - var midPointX = lastPoint.x + (firstPoint.x - lastPoint.x) *0.5; - var midPointY = lastPoint.y + (firstPoint.y - lastPoint.y) *0.5; - - points.unshift(midPointX, midPointY); - points.push(midPointX, midPointY) - } - - var verts = webGLData.points; - var indices = webGLData.indices; - var length = points.length / 2; - var indexCount = points.length; - var indexStart = verts.length/6; - - // DRAW the Line - var width = graphicsData.lineWidth / 2; - - // sort color - var color = HEXtoRGB(graphicsData.lineColor); - var alpha = graphicsData.lineAlpha; - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var p1x, p1y, p2x, p2y, p3x, p3y; - var perpx, perpy, perp2x, perp2y, perp3x, perp3y; - var ipx, ipy; - var a1, b1, c1, a2, b2, c2; - var denom, pdist, dist; - - p1x = points[0]; - p1y = points[1]; - - p2x = points[2]; - p2y = points[3]; - - perpx = -(p1y - p2y); - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - // start - verts.push(p1x - perpx , p1y - perpy, - r, g, b, alpha); - - verts.push(p1x + perpx , p1y + perpy, - r, g, b, alpha); - - for (var i = 1; i < length-1; i++) - { - p1x = points[(i-1)*2]; - p1y = points[(i-1)*2 + 1]; - - p2x = points[(i)*2] - p2y = points[(i)*2 + 1] - - p3x = points[(i+1)*2]; - p3y = points[(i+1)*2 + 1]; - - perpx = -(p1y - p2y); - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - perp2x = -(p2y - p3y); - perp2y = p2x - p3x; - - dist = Math.sqrt(perp2x*perp2x + perp2y*perp2y); - perp2x /= dist; - perp2y /= dist; - perp2x *= width; - perp2y *= width; - - a1 = (-perpy + p1y) - (-perpy + p2y); - b1 = (-perpx + p2x) - (-perpx + p1x); - c1 = (-perpx + p1x) * (-perpy + p2y) - (-perpx + p2x) * (-perpy + p1y); - a2 = (-perp2y + p3y) - (-perp2y + p2y); - b2 = (-perp2x + p2x) - (-perp2x + p3x); - c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y); - - denom = a1*b2 - a2*b1; - - if (denom == 0) { - denom+=1; - } - - px = (b1*c2 - b2*c1)/denom; - py = (a2*c1 - a1*c2)/denom; - - pdist = (px -p2x) * (px -p2x) + (py -p2y) + (py -p2y); - - if(pdist > 140 * 140) - { - perp3x = perpx - perp2x; - perp3y = perpy - perp2y; - - dist = Math.sqrt(perp3x*perp3x + perp3y*perp3y); - perp3x /= dist; - perp3y /= dist; - perp3x *= width; - perp3y *= width; - - verts.push(p2x - perp3x, p2y -perp3y); - verts.push(r, g, b, alpha); - - verts.push(p2x + perp3x, p2y +perp3y); - verts.push(r, g, b, alpha); - - verts.push(p2x - perp3x, p2y -perp3y); - verts.push(r, g, b, alpha); - - indexCount++; - } - else - { - verts.push(px , py); - verts.push(r, g, b, alpha); - - verts.push(p2x - (px-p2x), p2y - (py - p2y)); - verts.push(r, g, b, alpha); - } - } - - p1x = points[(length-2)*2] - p1y = points[(length-2)*2 + 1] - - p2x = points[(length-1)*2] - p2y = points[(length-1)*2 + 1] - - perpx = -(p1y - p2y) - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - verts.push(p2x - perpx , p2y - perpy) - verts.push(r, g, b, alpha); - - verts.push(p2x + perpx , p2y + perpy) - verts.push(r, g, b, alpha); - - indices.push(indexStart); - - for (var i=0; i < indexCount; i++) - { - indices.push(indexStart++); - }; - - indices.push(indexStart-1); -} - -/** - * Builds a polygon to draw - * - * @static - * @private - * @method buildPoly - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData) -{ - var points = graphicsData.points; - if(points.length < 6)return; - - // get first and last point.. figure out the middle! - var verts = webGLData.points; - var indices = webGLData.indices; - - var length = points.length / 2; - - // sort color - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var triangles = PIXI.PolyK.Triangulate(points); - - var vertPos = verts.length / 6; - - for (var i=0; i < triangles.length; i+=3) - { - indices.push(triangles[i] + vertPos); - indices.push(triangles[i] + vertPos); - indices.push(triangles[i+1] + vertPos); - indices.push(triangles[i+2] +vertPos); - indices.push(triangles[i+2] + vertPos); - }; - - for (var i = 0; i < length; i++) - { - verts.push(points[i * 2], points[i * 2 + 1], - r, g, b, alpha); - }; -} - -function HEXtoRGB(hex) { - return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; -} - - - - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI._defaultFrame = new PIXI.Rectangle(0,0,1,1); - -// an instance of the gl context.. -// only one at the moment :/ -PIXI.gl; - -/** - * the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer - * should be used for browsers support webGL. This Render works by automatically managing webGLBatchs. - * So no need for Sprite Batch's or Sprite Cloud's - * Dont forget to add the view to your DOM or you will not see anything :) - * - * @class WebGLRenderer - * @constructor - * @param width=0 {Number} the width of the canvas view - * @param height=0 {Number} the height of the canvas view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) - * - */ -PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) -{ - // do a catch.. only 1 webGL renderer.. - - this.transparent = !!transparent; - - this.width = width || 800; - this.height = height || 600; - - this.view = view || document.createElement( 'canvas' ); - this.view.width = this.width; - this.view.height = this.height; - - // deal with losing context.. - var scope = this; - this.view.addEventListener('webglcontextlost', function(event) { scope.handleContextLost(event); }, false) - this.view.addEventListener('webglcontextrestored', function(event) { scope.handleContextRestored(event); }, false) - - this.batchs = []; - - try - { - PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { - alpha: this.transparent, - antialias:!!antialias, // SPEED UP?? - premultipliedAlpha:false, - stencil:true - }); - } - catch (e) - { - throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); - } - - PIXI.initDefaultShader(); - PIXI.initPrimitiveShader(); - PIXI.initDefaultStripShader(); - - -// PIXI.activateDefaultShader(); - - var gl = this.gl; - PIXI.WebGLRenderer.gl = gl; - - this.batch = new PIXI.WebGLBatch(gl); - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - - gl.enable(gl.BLEND); - gl.colorMask(true, true, true, this.transparent); - - PIXI.projection = new PIXI.Point(400, 300); - - this.resize(this.width, this.height); - this.contextLost = false; - - PIXI.activateShader(PIXI.defaultShader); - - this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); - -} - -// constructor -PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; - -/** - * Gets a new WebGLBatch from the pool - * - * @static - * @method getBatch - * @return {WebGLBatch} - * @private - */ -PIXI.WebGLRenderer.getBatch = function() -{ - if(PIXI._batchs.length == 0) - { - return new PIXI.WebGLBatch(PIXI.WebGLRenderer.gl); - } - else - { - return PIXI._batchs.pop(); - } -} - -/** - * Puts a batch back into the pool - * - * @static - * @method returnBatch - * @param batch {WebGLBatch} The batch to return - * @private - */ -PIXI.WebGLRenderer.returnBatch = function(batch) -{ - batch.clean(); - PIXI._batchs.push(batch); -} - -/** - * Renders the stage to its webGL view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.WebGLRenderer.prototype.render = function(stage) -{ - if(this.contextLost)return; - - - // if rendering a new stage clear the batchs.. - if(this.__stage !== stage) - { - // TODO make this work - // dont think this is needed any more? - this.__stage = stage; - this.stageRenderGroup.setRenderable(stage); - } - - // TODO not needed now... - // update children if need be - // best to remove first! - /*for (var i=0; i < stage.__childrenRemoved.length; i++) - { - var group = stage.__childrenRemoved[i].__renderGroup - if(group)group.removeDisplayObject(stage.__childrenRemoved[i]); - }*/ - - // update any textures - PIXI.WebGLRenderer.updateTextures(); - - // update the scene graph - PIXI.visibleCount++; - stage.updateTransform(); - - var gl = this.gl; - - // -- Does this need to be set every frame? -- // - gl.colorMask(true, true, true, this.transparent); - gl.viewport(0, 0, this.width, this.height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); - gl.clear(gl.COLOR_BUFFER_BIT); - - // HACK TO TEST - - this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; - this.stageRenderGroup.render(PIXI.projection); - - // interaction - // run interaction! - if(stage.interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - - // after rendering lets confirm all frames that have been uodated.. - if(PIXI.Texture.frameUpdates.length > 0) - { - for (var i=0; i < PIXI.Texture.frameUpdates.length; i++) - { - PIXI.Texture.frameUpdates[i].updateFrame = false; - }; - - PIXI.Texture.frameUpdates = []; - } -} - -/** - * Updates the textures loaded into this webgl renderer - * - * @static - * @method updateTextures - * @private - */ -PIXI.WebGLRenderer.updateTextures = function() -{ - //TODO break this out into a texture manager... - for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); - PIXI.texturesToUpdate = []; - PIXI.texturesToDestroy = []; -} - -/** - * Updates a loaded webgl texture - * - * @static - * @method updateTexture - * @param texture {Texture} The texture to update - * @private - */ -PIXI.WebGLRenderer.updateTexture = function(texture) -{ - //TODO break this out into a texture manager... - var gl = PIXI.gl; - - if(!texture._glTexture) - { - texture._glTexture = gl.createTexture(); - } - - if(texture.hasLoaded) - { - gl.bindTexture(gl.TEXTURE_2D, texture._glTexture); - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - - // reguler... - - if(!texture._powerOf2) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - } - - gl.bindTexture(gl.TEXTURE_2D, null); - } -} - -/** - * Destroys a loaded webgl texture - * - * @method destroyTexture - * @param texture {Texture} The texture to update - * @private - */ -PIXI.WebGLRenderer.destroyTexture = function(texture) -{ - //TODO break this out into a texture manager... - var gl = PIXI.gl; - - if(texture._glTexture) - { - texture._glTexture = gl.createTexture(); - gl.deleteTexture(gl.TEXTURE_2D, texture._glTexture); - } -} - -/** - * resizes the webGL view to the specified width and height - * - * @method resize - * @param width {Number} the new width of the webGL view - * @param height {Number} the new height of the webGL view - */ -PIXI.WebGLRenderer.prototype.resize = function(width, height) -{ - this.width = width; - this.height = height; - - this.view.width = width; - this.view.height = height; - - this.gl.viewport(0, 0, this.width, this.height); - - //var projectionMatrix = this.projectionMatrix; - - PIXI.projection.x = this.width/2; - PIXI.projection.y = this.height/2; - -// projectionMatrix[0] = 2/this.width; -// projectionMatrix[5] = -2/this.height; -// projectionMatrix[12] = -1; -// projectionMatrix[13] = 1; -} - -/** - * Handles a lost webgl context - * - * @method handleContextLost - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextLost = function(event) -{ - event.preventDefault(); - this.contextLost = true; -} - -/** - * Handles a restored webgl context - * - * @method handleContextRestored - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextRestored = function(event) -{ - this.gl = this.view.getContext("experimental-webgl", { - alpha: true - }); - - this.initShaders(); - - for(var key in PIXI.TextureCache) - { - var texture = PIXI.TextureCache[key].baseTexture; - texture._glTexture = null; - PIXI.WebGLRenderer.updateTexture(texture); - }; - - for (var i=0; i < this.batchs.length; i++) - { - this.batchs[i].restoreLostContext(this.gl)// - this.batchs[i].dirty = true; - }; - - PIXI._restoreBatchs(this.gl); - - this.contextLost = false; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI._batchs = []; - -/** - * @private - */ -PIXI._getBatch = function(gl) -{ - if(PIXI._batchs.length == 0) - { - return new PIXI.WebGLBatch(gl); - } - else - { - return PIXI._batchs.pop(); - } -} - -/** - * @private - */ -PIXI._returnBatch = function(batch) -{ - batch.clean(); - PIXI._batchs.push(batch); -} - -/** - * @private - */ -PIXI._restoreBatchs = function(gl) -{ - for (var i=0; i < PIXI._batchs.length; i++) - { - PIXI._batchs[i].restoreLostContext(gl); - }; -} - -/** - * A WebGLBatch Enables a group of sprites to be drawn using the same settings. - * if a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch. - * All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites - * in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled - * automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster - * the webGL renderer will run. - * - * @class WebGLBatch - * @constructor - * @param gl {WebGLContext} an instance of the webGL context - */ -PIXI.WebGLBatch = function(gl) -{ - this.gl = gl; - - this.size = 0; - - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); - this.blendMode = PIXI.blendModes.NORMAL; - this.dynamicSize = 1; -} - -// constructor -PIXI.WebGLBatch.prototype.constructor = PIXI.WebGLBatch; - -/** - * Cleans the batch so that is can be returned to an object pool and reused - * - * @method clean - */ -PIXI.WebGLBatch.prototype.clean = function() -{ - this.verticies = []; - this.uvs = []; - this.indices = []; - this.colors = []; - this.dynamicSize = 1; - this.texture = null; - this.last = null; - this.size = 0; - this.head; - this.tail; -} - -/** - * Recreates the buffers in the event of a context loss - * - * @method restoreLostContext - * @param gl {WebGLContext} - */ -PIXI.WebGLBatch.prototype.restoreLostContext = function(gl) -{ - this.gl = gl; - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); -} - -/** - * inits the batch's texture and blend mode based if the supplied sprite - * - * @method init - * @param sprite {Sprite} the first sprite to be added to the batch. Only sprites with - * the same base texture and blend mode will be allowed to be added to this batch - */ -PIXI.WebGLBatch.prototype.init = function(sprite) -{ - sprite.batch = this; - this.dirty = true; - this.blendMode = sprite.blendMode; - this.texture = sprite.texture.baseTexture; - this.head = sprite; - this.tail = sprite; - this.size = 1; - - this.growBatch(); -} - -/** - * inserts a sprite before the specified sprite - * - * @method insertBefore - * @param sprite {Sprite} the sprite to be added - * @param nextSprite {nextSprite} the first sprite will be inserted before this sprite - */ -PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) -{ - this.size++; - - sprite.batch = this; - this.dirty = true; - var tempPrev = nextSprite.__prev; - nextSprite.__prev = sprite; - sprite.__next = nextSprite; - - if(tempPrev) - { - sprite.__prev = tempPrev; - tempPrev.__next = sprite; - } - else - { - this.head = sprite; - } -} - -/** - * inserts a sprite after the specified sprite - * - * @method insertAfter - * @param sprite {Sprite} the sprite to be added - * @param previousSprite {Sprite} the first sprite will be inserted after this sprite - */ -PIXI.WebGLBatch.prototype.insertAfter = function(sprite, previousSprite) -{ - this.size++; - - sprite.batch = this; - this.dirty = true; - - var tempNext = previousSprite.__next; - previousSprite.__next = sprite; - sprite.__prev = previousSprite; - - if(tempNext) - { - sprite.__next = tempNext; - tempNext.__prev = sprite; - } - else - { - this.tail = sprite - } -} - -/** - * removes a sprite from the batch - * - * @method remove - * @param sprite {Sprite} the sprite to be removed - */ -PIXI.WebGLBatch.prototype.remove = function(sprite) -{ - this.size--; - - if(this.size == 0) - { - sprite.batch = null; - sprite.__prev = null; - sprite.__next = null; - return; - } - - if(sprite.__prev) - { - sprite.__prev.__next = sprite.__next; - } - else - { - this.head = sprite.__next; - this.head.__prev = null; - } - - if(sprite.__next) - { - sprite.__next.__prev = sprite.__prev; - } - else - { - this.tail = sprite.__prev; - this.tail.__next = null - } - - sprite.batch = null; - sprite.__next = null; - sprite.__prev = null; - this.dirty = true; -} - -/** - * Splits the batch into two with the specified sprite being the start of the new batch. - * - * @method split - * @param sprite {Sprite} the sprite that indicates where the batch should be split - * @return {WebGLBatch} the new batch - */ -PIXI.WebGLBatch.prototype.split = function(sprite) -{ - this.dirty = true; - - var batch = new PIXI.WebGLBatch(this.gl); - batch.init(sprite); - batch.texture = this.texture; - batch.tail = this.tail; - - this.tail = sprite.__prev; - this.tail.__next = null; - - sprite.__prev = null; - // return a splite batch! - - // TODO this size is wrong! - // need to recalculate :/ problem with a linked list! - // unless it gets calculated in the "clean"? - - // need to loop through items as there is no way to know the length on a linked list :/ - var tempSize = 0; - while(sprite) - { - tempSize++; - sprite.batch = batch; - sprite = sprite.__next; - } - - batch.size = tempSize; - this.size -= tempSize; - - return batch; -} - -/** - * Merges two batchs together - * - * @method merge - * @param batch {WebGLBatch} the batch that will be merged - */ -PIXI.WebGLBatch.prototype.merge = function(batch) -{ - this.dirty = true; - - this.tail.__next = batch.head; - batch.head.__prev = this.tail; - - this.size += batch.size; - - this.tail = batch.tail; - - var sprite = batch.head; - while(sprite) - { - sprite.batch = this; - sprite = sprite.__next; - } -} - -/** - * Grows the size of the batch. As the elements in the batch cannot have a dynamic size this - * function is used to increase the size of the batch. It also creates a little extra room so - * that the batch does not need to be resized every time a sprite is added - * - * @method growBatch - */ -PIXI.WebGLBatch.prototype.growBatch = function() -{ - var gl = this.gl; - if( this.size == 1) - { - this.dynamicSize = 1; - } - else - { - this.dynamicSize = this.size * 1.5 - } - // grow verts - this.verticies = new Float32Array(this.dynamicSize * 8); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); - - this.uvs = new Float32Array( this.dynamicSize * 8 ); - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); - - this.dirtyUVS = true; - - this.colors = new Float32Array( this.dynamicSize * 4 ); - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); - - this.dirtyColors = true; - - this.indices = new Uint16Array(this.dynamicSize * 6); - var length = this.indices.length/6; - - for (var i=0; i < length; i++) - { - var index2 = i * 6; - var index3 = i * 4; - this.indices[index2 + 0] = index3 + 0; - this.indices[index2 + 1] = index3 + 1; - this.indices[index2 + 2] = index3 + 2; - this.indices[index2 + 3] = index3 + 0; - this.indices[index2 + 4] = index3 + 2; - this.indices[index2 + 5] = index3 + 3; - }; - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); -} - -/** - * Refresh's all the data in the batch and sync's it with the webGL buffers - * - * @method refresh - */ -PIXI.WebGLBatch.prototype.refresh = function() -{ - var gl = this.gl; - - if (this.dynamicSize < this.size) - { - this.growBatch(); - } - - var indexRun = 0; - var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index; - var a, b, c, d, tx, ty; - - var displayObject = this.head; - - while(displayObject) - { - index = indexRun * 8; - - var texture = displayObject.texture; - - var frame = texture.frame; - var tw = texture.baseTexture.width; - var th = texture.baseTexture.height; - - this.uvs[index + 0] = frame.x / tw; - this.uvs[index +1] = frame.y / th; - - this.uvs[index +2] = (frame.x + frame.width) / tw; - this.uvs[index +3] = frame.y / th; - - this.uvs[index +4] = (frame.x + frame.width) / tw; - this.uvs[index +5] = (frame.y + frame.height) / th; - - this.uvs[index +6] = frame.x / tw; - this.uvs[index +7] = (frame.y + frame.height) / th; - - displayObject.updateFrame = false; - - colorIndex = indexRun * 4; - this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; - - displayObject = displayObject.__next; - - indexRun ++; - } - - this.dirtyUVS = true; - this.dirtyColors = true; -} - -/** - * Updates all the relevant geometry and uploads the data to the GPU - * - * @method update - */ -PIXI.WebGLBatch.prototype.update = function() -{ - var gl = this.gl; - var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index, index2, index3 - - var a, b, c, d, tx, ty; - - var indexRun = 0; - - var displayObject = this.head; - - while(displayObject) - { - if(displayObject.vcount === PIXI.visibleCount) - { - width = displayObject.texture.frame.width; - height = displayObject.texture.frame.height; - - // TODO trim?? - aX = displayObject.anchor.x;// - displayObject.texture.trim.x - aY = displayObject.anchor.y; //- displayObject.texture.trim.y - w0 = width * (1-aX); - w1 = width * -aX; - - h0 = height * (1-aY); - h1 = height * -aY; - - index = indexRun * 8; - - worldTransform = displayObject.worldTransform; - - a = worldTransform[0]; - b = worldTransform[3]; - c = worldTransform[1]; - d = worldTransform[4]; - tx = worldTransform[2]; - ty = worldTransform[5]; - - this.verticies[index + 0 ] = a * w1 + c * h1 + tx; - this.verticies[index + 1 ] = d * h1 + b * w1 + ty; - - this.verticies[index + 2 ] = a * w0 + c * h1 + tx; - this.verticies[index + 3 ] = d * h1 + b * w0 + ty; - - this.verticies[index + 4 ] = a * w0 + c * h0 + tx; - this.verticies[index + 5 ] = d * h0 + b * w0 + ty; - - this.verticies[index + 6] = a * w1 + c * h0 + tx; - this.verticies[index + 7] = d * h0 + b * w1 + ty; - - if(displayObject.updateFrame || displayObject.texture.updateFrame) - { - this.dirtyUVS = true; - - var texture = displayObject.texture; - - var frame = texture.frame; - var tw = texture.baseTexture.width; - var th = texture.baseTexture.height; - - this.uvs[index + 0] = frame.x / tw; - this.uvs[index +1] = frame.y / th; - - this.uvs[index +2] = (frame.x + frame.width) / tw; - this.uvs[index +3] = frame.y / th; - - this.uvs[index +4] = (frame.x + frame.width) / tw; - this.uvs[index +5] = (frame.y + frame.height) / th; - - this.uvs[index +6] = frame.x / tw; - this.uvs[index +7] = (frame.y + frame.height) / th; - - displayObject.updateFrame = false; - } - - // TODO this probably could do with some optimisation.... - if(displayObject.cacheAlpha != displayObject.worldAlpha) - { - displayObject.cacheAlpha = displayObject.worldAlpha; - - var colorIndex = indexRun * 4; - this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; - this.dirtyColors = true; - } - } - else - { - index = indexRun * 8; - - this.verticies[index + 0 ] = 0; - this.verticies[index + 1 ] = 0; - - this.verticies[index + 2 ] = 0; - this.verticies[index + 3 ] = 0; - - this.verticies[index + 4 ] = 0; - this.verticies[index + 5 ] = 0; - - this.verticies[index + 6] = 0; - this.verticies[index + 7] = 0; - } - - indexRun++; - displayObject = displayObject.__next; - } -} - -/** - * Draws the batch to the frame buffer - * - * @method render - */ -PIXI.WebGLBatch.prototype.render = function(start, end) -{ - start = start || 0; - - if(end == undefined)end = this.size; - - if(this.dirty) - { - this.refresh(); - this.dirty = false; - } - - if (this.size == 0)return; - - this.update(); - var gl = this.gl; - - //TODO optimize this! - - var shaderProgram = PIXI.currentShader; - - //gl.useProgram(shaderProgram); - - // update the verts.. - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - // ok.. - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - // update the uvs - var isDefault = (shaderProgram == PIXI.shaderProgram) - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - - if(this.dirtyUVS) - { - this.dirtyUVS = false; - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvs); - } - - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this.texture._glTexture); - - // update color! - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - - if(this.dirtyColors) - { - this.dirtyColors = false; - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.colors); - } - - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - var len = end - start; - - // DRAW THAT this! - gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A WebGLBatch Enables a group of sprites to be drawn using the same settings. - * if a group of sprites all have the same baseTexture and blendMode then they can be - * grouped into a batch. All the sprites in a batch can then be drawn in one go by the - * GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch - * even if the batch only contains one sprite. Batching is handled automatically by the - * webGL renderer. A good tip is: the smaller the number of batchs there are, the faster - * the webGL renderer will run. - * - * @class WebGLBatch - * @contructor - * @param gl {WebGLContext} An instance of the webGL context - */ -PIXI.WebGLRenderGroup = function(gl) -{ - this.gl = gl; - this.root; - - this.backgroundColor; - this.batchs = []; - this.toRemove = []; -} - -// constructor -PIXI.WebGLRenderGroup.prototype.constructor = PIXI.WebGLRenderGroup; - -/** - * Add a display object to the webgl renderer - * - * @method setRenderable - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.setRenderable = function(displayObject) -{ - // has this changed?? - if(this.root)this.removeDisplayObjectAndChildren(this.root); - - displayObject.worldVisible = displayObject.visible; - - // soooooo // - // to check if any batchs exist already?? - - // TODO what if its already has an object? should remove it - this.root = displayObject; - this.addDisplayObjectAndChildren(displayObject); -} - -/** - * Renders the stage to its webgl view - * - * @method render - * @param projection {Object} - */ -PIXI.WebGLRenderGroup.prototype.render = function(projection) -{ - PIXI.WebGLRenderer.updateTextures(); - - var gl = this.gl; - - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - // will render all the elements in the group - var renderable; - for (var i=0; i < this.batchs.length; i++) - { - - renderable = this.batchs[i]; - if(renderable instanceof PIXI.WebGLBatch) - { - this.batchs[i].render(); - continue; - } - - // non sprite batch.. - var worldVisible = renderable.vcount === PIXI.visibleCount; - - if(renderable instanceof PIXI.TilingSprite) - { - if(worldVisible)this.renderTilingSprite(renderable, projection); - } - else if(renderable instanceof PIXI.Strip) - { - if(worldVisible)this.renderStrip(renderable, projection); - } - else if(renderable instanceof PIXI.Graphics) - { - if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); - } - else if(renderable instanceof PIXI.FilterBlock) - { - this.handleFilterBlock(renderable, projection); - } - } - -} - -/** - * Renders a specific displayObject - * - * @method renderSpecific - * @param displayObject {DisplayObject} - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection) -{ - PIXI.WebGLRenderer.updateTextures(); - - var gl = this.gl; - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - - // to do! - // render part of the scene... - - var startIndex; - var startBatchIndex; - - var endIndex; - var endBatchIndex; - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.first; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - var startBatch = nextRenderable.batch; - - if(nextRenderable instanceof PIXI.Sprite) - { - startBatch = nextRenderable.batch; - - var head = startBatch.head; - var next = head; - - // ok now we have the batch.. need to find the start index! - if(head == nextRenderable) - { - startIndex = 0; - } - else - { - startIndex = 1; - - while(head.__next != nextRenderable) - { - startIndex++; - head = head.__next; - } - } - } - else - { - startBatch = nextRenderable; - } - - // Get the LAST renderable object - var lastRenderable = displayObject; - var endBatch; - var lastItem = displayObject; - while(lastItem.children.length > 0) - { - lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem.last; - } - - if(lastRenderable instanceof PIXI.Sprite) - { - endBatch = lastRenderable.batch; - - var head = endBatch.head; - - if(head == lastRenderable) - { - endIndex = 0; - } - else - { - endIndex = 1; - - while(head.__next != lastRenderable) - { - endIndex++; - head = head.__next; - } - } - } - else - { - endBatch = lastRenderable; - } - - // TODO - need to fold this up a bit! - - if(startBatch == endBatch) - { - if(startBatch instanceof PIXI.WebGLBatch) - { - startBatch.render(startIndex, endIndex+1); - } - else - { - this.renderSpecial(startBatch, projection); - } - return; - } - - // now we have first and last! - startBatchIndex = this.batchs.indexOf(startBatch); - endBatchIndex = this.batchs.indexOf(endBatch); - - // DO the first batch - if(startBatch instanceof PIXI.WebGLBatch) - { - startBatch.render(startIndex); - } - else - { - this.renderSpecial(startBatch, projection); - } - - // DO the middle batchs.. - for (var i=startBatchIndex+1; i < endBatchIndex; i++) - { - renderable = this.batchs[i]; - - if(renderable instanceof PIXI.WebGLBatch) - { - this.batchs[i].render(); - } - else - { - this.renderSpecial(renderable, projection); - } - } - - // DO the last batch.. - if(endBatch instanceof PIXI.WebGLBatch) - { - endBatch.render(0, endIndex+1); - } - else - { - this.renderSpecial(endBatch, projection); - } -} - -/** - * Renders a specific renderable - * - * @method renderSpecial - * @param renderable {DisplayObject} - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) -{ - var sta = PIXI.shaderStack.length; - - var worldVisible = renderable.vcount === PIXI.visibleCount - - if(renderable instanceof PIXI.TilingSprite) - { - if(worldVisible)this.renderTilingSprite(renderable, projection); - } - else if(renderable instanceof PIXI.Strip) - { - if(worldVisible)this.renderStrip(renderable, projection); - } - else if(renderable instanceof PIXI.CustomRenderable) - { - if(worldVisible) renderable.renderWebGL(this, projection); - } - else if(renderable instanceof PIXI.Graphics) - { - if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); - } - else if(renderable instanceof PIXI.FilterBlock) - { - this.handleFilterBlock(renderable, projection); - } -} - -PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) -{ - /* - * for now only masks are supported.. - */ - var gl = PIXI.gl; - - if(renderable.open) - { - if(renderable.data instanceof Array) - { - var filter = renderable.data[0]; - - if(!filter.shader) - { - var shader = new PIXI.PixiShader(); - - shader.fragmentSrc = filter.fragmentSrc; - shader.uniforms = filter.uniforms; - shader.init(); - - filter.shader = shader - } - - PIXI.activateShader(filter.shader); - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - } - else - { - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); - - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - } - else - { - if(renderable.data instanceof Array) - { - PIXI.popShader(); - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - } - else - { - gl.disable(gl.STENCIL_TEST); - } - } -} - -/** - * Updates a webgl texture - * - * @method updateTexture - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject) -{ - - // TODO definitely can optimse this function.. - - this.removeObject(displayObject); - - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - var previousRenderable = displayObject.first; - while(previousRenderable != this.root) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.last; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - - this.insertObject(displayObject, previousRenderable, nextRenderable); -} - -/** - * Adds filter blocks - * - * @method addFilterBlocks - * @param start {FilterBlock} - * @param end {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) -{ - start.__renderGroup = this; - end.__renderGroup = this; - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - var previousRenderable = start; - while(previousRenderable != this.root.first) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - this.insertAfter(start, previousRenderable); - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var previousRenderable2 = end; - while(previousRenderable2 != this.root.first) - { - previousRenderable2 = previousRenderable2._iPrev; - if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; - } - this.insertAfter(end, previousRenderable2); -} - -/** - * Remove filter blocks - * - * @method removeFilterBlocks - * @param start {FilterBlock} - * @param end {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeFilterBlocks = function(start, end) -{ - this.removeObject(start); - this.removeObject(end); -} - -/** - * Adds a display object and children to the webgl context - * - * @method addDisplayObjectAndChildren - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayObject) -{ - if(displayObject.__renderGroup)displayObject.__renderGroup.removeDisplayObjectAndChildren(displayObject); - - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - - var previousRenderable = displayObject.first; - while(previousRenderable != this.root.first) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.last; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - - // one the display object hits this. we can break the loop - - var tempObject = displayObject.first; - var testObject = displayObject.last._iNext; - do - { - tempObject.__renderGroup = this; - - if(tempObject.renderable) - { - - this.insertObject(tempObject, previousRenderable, nextRenderable); - previousRenderable = tempObject; - } - - tempObject = tempObject._iNext; - } - while(tempObject != testObject) -} - -/** - * Removes a display object and children to the webgl context - * - * @method removeDisplayObjectAndChildren - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren = function(displayObject) -{ - if(displayObject.__renderGroup != this)return; - -// var displayObject = displayObject.first; - var lastObject = displayObject.last; - do - { - displayObject.__renderGroup = null; - if(displayObject.renderable)this.removeObject(displayObject); - displayObject = displayObject._iNext; - } - while(displayObject) -} - -/** - * Inserts a displayObject into the linked list - * - * @method insertObject - * @param displayObject {DisplayObject} - * @param previousObject {DisplayObject} - * @param nextObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousObject, nextObject) -{ - // while looping below THE OBJECT MAY NOT HAVE BEEN ADDED - var previousSprite = previousObject; - var nextSprite = nextObject; - - /* - * so now we have the next renderable and the previous renderable - * - */ - if(displayObject instanceof PIXI.Sprite) - { - var previousBatch - var nextBatch - - if(previousSprite instanceof PIXI.Sprite) - { - previousBatch = previousSprite.batch; - if(previousBatch) - { - if(previousBatch.texture == displayObject.texture.baseTexture && previousBatch.blendMode == displayObject.blendMode) - { - previousBatch.insertAfter(displayObject, previousSprite); - return; - } - } - } - else - { - // TODO reword! - previousBatch = previousSprite; - } - - if(nextSprite) - { - if(nextSprite instanceof PIXI.Sprite) - { - nextBatch = nextSprite.batch; - - //batch may not exist if item was added to the display list but not to the webGL - if(nextBatch) - { - if(nextBatch.texture == displayObject.texture.baseTexture && nextBatch.blendMode == displayObject.blendMode) - { - nextBatch.insertBefore(displayObject, nextSprite); - return; - } - else - { - if(nextBatch == previousBatch) - { - // THERE IS A SPLIT IN THIS BATCH! // - var splitBatch = previousBatch.split(nextSprite); - // COOL! - // add it back into the array - /* - * OOPS! - * seems the new sprite is in the middle of a batch - * lets split it.. - */ - var batch = PIXI.WebGLRenderer.getBatch(); - - var index = this.batchs.indexOf( previousBatch ); - batch.init(displayObject); - this.batchs.splice(index+1, 0, batch, splitBatch); - - return; - } - } - } - } - else - { - // TODO re-word! - - nextBatch = nextSprite; - } - } - - /* - * looks like it does not belong to any batch! - * but is also not intersecting one.. - * time to create anew one! - */ - - var batch = PIXI.WebGLRenderer.getBatch(); - batch.init(displayObject); - - if(previousBatch) // if this is invalid it means - { - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, batch); - } - else - { - this.batchs.push(batch); - } - - return; - } - else if(displayObject instanceof PIXI.TilingSprite) - { - - // add to a batch!! - this.initTilingSprite(displayObject); - // this.batchs.push(displayObject); - - } - else if(displayObject instanceof PIXI.Strip) - { - // add to a batch!! - this.initStrip(displayObject); - // this.batchs.push(displayObject); - } - else if(displayObject)// instanceof PIXI.Graphics) - { - //displayObject.initWebGL(this); - - // add to a batch!! - //this.initStrip(displayObject); - //this.batchs.push(displayObject); - } - - this.insertAfter(displayObject, previousSprite); - - // insert and SPLIT! - -} - -/** - * Inserts a displayObject into the linked list - * - * @method insertAfter - * @param item {DisplayObject} - * @param displayObject {DisplayObject} The object to insert - * @private - */ -PIXI.WebGLRenderGroup.prototype.insertAfter = function(item, displayObject) -{ - if(displayObject instanceof PIXI.Sprite) - { - var previousBatch = displayObject.batch; - - if(previousBatch) - { - // so this object is in a batch! - - // is it not? need to split the batch - if(previousBatch.tail == displayObject) - { - // is it tail? insert in to batchs - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, item); - } - else - { - // TODO MODIFY ADD / REMOVE CHILD TO ACCOUNT FOR FILTERS (also get prev and next) // - - // THERE IS A SPLIT IN THIS BATCH! // - var splitBatch = previousBatch.split(displayObject.__next); - - // COOL! - // add it back into the array - /* - * OOPS! - * seems the new sprite is in the middle of a batch - * lets split it.. - */ - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, item, splitBatch); - } - } - else - { - this.batchs.push(item); - } - } - else - { - var index = this.batchs.indexOf( displayObject ); - this.batchs.splice(index+1, 0, item); - } -} - -/** - * Removes a displayObject from the linked list - * - * @method removeObject - * @param displayObject {DisplayObject} The object to remove - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) -{ - // loop through children.. - // display object // - - // add a child from the render group.. - // remove it and all its children! - //displayObject.cacheVisible = false;//displayObject.visible; - - /* - * removing is a lot quicker.. - * - */ - var batchToRemove; - - if(displayObject instanceof PIXI.Sprite) - { - // should always have a batch! - var batch = displayObject.batch; - if(!batch)return; // this means the display list has been altered befre rendering - - batch.remove(displayObject); - - if(batch.size==0) - { - batchToRemove = batch; - } - } - else - { - batchToRemove = displayObject; - } - - /* - * Looks like there is somthing that needs removing! - */ - if(batchToRemove) - { - var index = this.batchs.indexOf( batchToRemove ); - if(index == -1)return;// this means it was added then removed before rendered - - // ok so.. check to see if you adjacent batchs should be joined. - // TODO may optimise? - if(index == 0 || index == this.batchs.length-1) - { - // wha - eva! just get of the empty batch! - this.batchs.splice(index, 1); - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - - return; - } - - if(this.batchs[index-1] instanceof PIXI.WebGLBatch && this.batchs[index+1] instanceof PIXI.WebGLBatch) - { - if(this.batchs[index-1].texture == this.batchs[index+1].texture && this.batchs[index-1].blendMode == this.batchs[index+1].blendMode) - { - //console.log("MERGE") - this.batchs[index-1].merge(this.batchs[index+1]); - - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - PIXI.WebGLRenderer.returnBatch(this.batchs[index+1]); - this.batchs.splice(index, 2); - return; - } - } - - this.batchs.splice(index, 1); - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - } -} - - -/** - * Initializes a tiling sprite - * - * @method initTilingSprite - * @param sprite {TilingSprite} The tiling sprite to initialize - * @private - */ -PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) -{ - var gl = this.gl; - - // make the texture tilable.. - - sprite.verticies = new Float32Array([0, 0, - sprite.width, 0, - sprite.width, sprite.height, - 0, sprite.height]); - - sprite.uvs = new Float32Array([0, 0, - 1, 0, - 1, 1, - 0, 1]); - - sprite.colors = new Float32Array([1,1,1,1]); - - sprite.indices = new Uint16Array([0, 1, 3,2])//, 2]); - - sprite._vertexBuffer = gl.createBuffer(); - sprite._indexBuffer = gl.createBuffer(); - sprite._uvBuffer = gl.createBuffer(); - sprite._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.verticies, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.uvs, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.colors, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sprite._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sprite.indices, gl.STATIC_DRAW); - -// return ( (x > 0) && ((x & (x - 1)) == 0) ); - - if(sprite.texture.baseTexture._glTexture) - { - gl.bindTexture(gl.TEXTURE_2D, sprite.texture.baseTexture._glTexture); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - sprite.texture.baseTexture._powerOf2 = true; - } - else - { - sprite.texture.baseTexture._powerOf2 = true; - } -} - -/** - * Renders a Strip - * - * @method renderStrip - * @param strip {Strip} The strip to render - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) -{ - var gl = this.gl; - var shaderProgram = PIXI.stripShaderProgram; - - - gl.useProgram(shaderProgram); - - var m = PIXI.mat3.clone(strip.worldTransform); - - PIXI.mat3.transpose(m); - - // set the matrix transform for the - gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); - gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); - -/* - if(strip.blendMode == PIXI.blendModes.NORMAL) - { - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - } - else - { - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR); - } - */ - - - if(!strip.dirty) - { - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, strip.verticies) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - } - else - { - strip.dirty = false; - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); - - } - - gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - - gl.useProgram(PIXI.currentProgram); -} - -/** - * Renders a TilingSprite - * - * @method renderTilingSprite - * @param sprite {TilingSprite} The tiling sprite to render - * @param projectionMatrix {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderTilingSprite = function(sprite, projectionMatrix) -{ - var gl = this.gl; - var shaderProgram = PIXI.shaderProgram; - - var tilePosition = sprite.tilePosition; - var tileScale = sprite.tileScale; - - var offsetX = tilePosition.x/sprite.texture.baseTexture.width; - var offsetY = tilePosition.y/sprite.texture.baseTexture.height; - - var scaleX = (sprite.width / sprite.texture.baseTexture.width) / tileScale.x; - var scaleY = (sprite.height / sprite.texture.baseTexture.height) / tileScale.y; - - sprite.uvs[0] = 0 - offsetX; - sprite.uvs[1] = 0 - offsetY; - - sprite.uvs[2] = (1 * scaleX) -offsetX; - sprite.uvs[3] = 0 - offsetY; - - sprite.uvs[4] = (1 *scaleX) - offsetX; - sprite.uvs[5] = (1 *scaleY) - offsetY; - - sprite.uvs[6] = 0 - offsetX; - sprite.uvs[7] = (1 *scaleY) - offsetY; - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, sprite.uvs) - - this.renderStrip(sprite, projectionMatrix); -} - -/** - * Initializes a strip to be rendered - * - * @method initStrip - * @param strip {Strip} The strip to initialize - * @private - */ -PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) -{ - // build the strip! - var gl = this.gl; - var shaderProgram = this.shaderProgram; - - strip._vertexBuffer = gl.createBuffer(); - strip._indexBuffer = gl.createBuffer(); - strip._uvBuffer = gl.createBuffer(); - strip._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW); - - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * the CanvasRenderer draws the stage and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. - * Dont forget to add the view to your DOM or you will not see anything :) - * - * @class CanvasRenderer - * @constructor - * @param width=0 {Number} the width of the canvas view - * @param height=0 {Number} the height of the canvas view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - */ -PIXI.CanvasRenderer = function(width, height, view, transparent) -{ - this.transparent = transparent; - - /** - * The width of the canvas view - * - * @property width - * @type Number - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @property height - * @type Number - * @default 600 - */ - this.height = height || 600; - - /** - * The canvas element that the everything is drawn to - * - * @property view - * @type Canvas - */ - this.view = view || document.createElement( 'canvas' ); - - /** - * The canvas context that the everything is drawn to - * @property context - * @type Canvas 2d Context - */ - this.context = this.view.getContext("2d"); - - this.refresh = true; - // hack to enable some hardware acceleration! - //this.view.style["transform"] = "translatez(0)"; - - this.view.width = this.width; - this.view.height = this.height; - this.count = 0; -} - -// constructor -PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; - -/** - * Renders the stage to its canvas view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.CanvasRenderer.prototype.render = function(stage) -{ - - //stage.__childrenAdded = []; - //stage.__childrenRemoved = []; - - // update textures if need be - PIXI.texturesToUpdate = []; - PIXI.texturesToDestroy = []; - - PIXI.visibleCount++; - stage.updateTransform(); - - // update the background color - if(this.view.style.backgroundColor!=stage.backgroundColorString && !this.transparent)this.view.style.backgroundColor = stage.backgroundColorString; - - this.context.setTransform(1,0,0,1,0,0); - this.context.clearRect(0, 0, this.width, this.height) - this.renderDisplayObject(stage); - //as - - // run interaction! - if(stage.interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - - // remove frame updates.. - if(PIXI.Texture.frameUpdates.length > 0) - { - PIXI.Texture.frameUpdates = []; - } - - -} - -/** - * resizes the canvas view to the specified width and height - * - * @method resize - * @param width {Number} the new width of the canvas view - * @param height {Number} the new height of the canvas view - */ -PIXI.CanvasRenderer.prototype.resize = function(width, height) -{ - this.width = width; - this.height = height; - - this.view.width = width; - this.view.height = height; -} - -/** - * Renders a display object - * - * @method renderDisplayObject - * @param displayObject {DisplayObject} The displayObject to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) -{ - // no loger recurrsive! - var transform; - var context = this.context; - - context.globalCompositeOperation = 'source-over'; - - // one the display object hits this. we can break the loop - var testObject = displayObject.last._iNext; - displayObject = displayObject.first; - - do - { - transform = displayObject.worldTransform; - - if(!displayObject.visible) - { - displayObject = displayObject.last._iNext; - continue; - } - - if(!displayObject.renderable) - { - displayObject = displayObject._iNext; - continue; - } - - if(displayObject instanceof PIXI.Sprite) - { - - var frame = displayObject.texture.frame; - - if(frame && frame.width && frame.height) - { - context.globalAlpha = displayObject.worldAlpha; - - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); - - context.drawImage(displayObject.texture.baseTexture.source, - frame.x, - frame.y, - frame.width, - frame.height, - (displayObject.anchor.x) * -frame.width, - (displayObject.anchor.y) * -frame.height, - frame.width, - frame.height); - } - } - else if(displayObject instanceof PIXI.Strip) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - this.renderStrip(displayObject); - } - else if(displayObject instanceof PIXI.TilingSprite) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - this.renderTilingSprite(displayObject); - } - else if(displayObject instanceof PIXI.CustomRenderable) - { - displayObject.renderCanvas(this); - } - else if(displayObject instanceof PIXI.Graphics) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - PIXI.CanvasGraphics.renderGraphics(displayObject, context); - } - else if(displayObject instanceof PIXI.FilterBlock) - { - if(PIXI.FilterBlock.data instanceof PIXI.Graphics) - { - if(displayObject.open) - { - context.save(); - - var cacheAlpha = displayObject.mask.alpha; - var maskTransform = displayObject.mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - displayObject.mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); - context.clip(); - - displayObject.mask.worldAlpha = cacheAlpha; - } - else - { - context.restore(); - } - } - else - { - // only masks supported right now! - } - } - // count++ - displayObject = displayObject._iNext; - - - } - while(displayObject != testObject) - - -} - -/** - * Renders a flat strip - * - * @method renderStripFlat - * @param strip {Strip} The Strip to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip) -{ - var context = this.context; - var verticies = strip.verticies; - var uvs = strip.uvs; - - var length = verticies.length/2; - this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - - // draw some triangles! - var index = i*2; - - var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; - var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - }; - - context.fillStyle = "#FF0000"; - context.fill(); - context.closePath(); -} - -/** - * Renders a tiling sprite - * - * @method renderTilingSprite - * @param sprite {TilingSprite} The tilingsprite to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) -{ - var context = this.context; - - context.globalAlpha = sprite.worldAlpha; - - if(!sprite.__tilePattern) sprite.__tilePattern = context.createPattern(sprite.texture.baseTexture.source, "repeat"); - - context.beginPath(); - - var tilePosition = sprite.tilePosition; - var tileScale = sprite.tileScale; - - // offset - context.scale(tileScale.x,tileScale.y); - context.translate(tilePosition.x, tilePosition.y); - - context.fillStyle = sprite.__tilePattern; - context.fillRect(-tilePosition.x,-tilePosition.y,sprite.width / tileScale.x, sprite.height / tileScale.y); - - context.scale(1/tileScale.x, 1/tileScale.y); - context.translate(-tilePosition.x, -tilePosition.y); - - context.closePath(); -} - -/** - * Renders a strip - * - * @method renderStrip - * @param strip {Strip} The Strip to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderStrip = function(strip) -{ - var context = this.context; - - // draw triangles!! - var verticies = strip.verticies; - var uvs = strip.uvs; - - var length = verticies.length/2; - this.count++; - for (var i=1; i < length-2; i++) - { - - // draw some triangles! - var index = i*2; - - var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; - var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - - var u0 = uvs[index] * strip.texture.width, u1 = uvs[index+2] * strip.texture.width, u2 = uvs[index+4]* strip.texture.width; - var v0 = uvs[index+1]* strip.texture.height, v1 = uvs[index+3] * strip.texture.height, v2 = uvs[index+5]* strip.texture.height; - - - 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 delta_a = x0*v1 + v0*x2 + x1*v2 - v1*x2 - v0*x1 - x0*v2; - var delta_b = u0*x1 + x0*u2 + u1*x2 - x1*u2 - x0*u1 - u0*x2; - var delta_c = u0*v1*x2 + v0*x1*u2 + x0*u1*v2 - x0*v1*u2 - v0*u1*x2 - u0*x1*v2; - var delta_d = y0*v1 + v0*y2 + y1*v2 - v1*y2 - v0*y1 - y0*v2; - var delta_e = u0*y1 + y0*u2 + u1*y2 - y1*u2 - y0*u1 - u0*y2; - var delta_f = u0*v1*y2 + v0*y1*u2 + y0*u1*v2 - y0*v1*u2 - v0*u1*y2 - u0*y1*v2; - - - - - context.transform(delta_a/delta, delta_d/delta, - delta_b/delta, delta_e/delta, - delta_c/delta, delta_f/delta); - - context.drawImage(strip.texture.baseTexture.source, 0, 0); - context.restore(); - }; - -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * A set of functions used by the canvas renderer to draw the primitive graphics data - * - * @class CanvasGraphics - */ -PIXI.CanvasGraphics = function() -{ - -} - - -/* - * Renders the graphics object - * - * @static - * @private - * @method renderGraphics - * @param graphics {Graphics} - * @param context {Context2D} - */ -PIXI.CanvasGraphics.renderGraphics = function(graphics, context) -{ - var worldAlpha = graphics.worldAlpha; - - for (var i=0; i < graphics.graphicsData.length; i++) - { - var data = graphics.graphicsData[i]; - var points = data.points; - - context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); - - context.lineWidth = data.lineWidth; - - if(data.type == PIXI.Graphics.POLY) - { - context.beginPath(); - - context.moveTo(points[0], points[1]); - - for (var j=1; j < points.length/2; j++) - { - context.lineTo(points[j * 2], points[j * 2 + 1]); - } - - // if the first and last point are the same close the path - much neater :) - if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) - { - context.closePath(); - } - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - else if(data.type == PIXI.Graphics.RECT) - { - - if(data.fillColor || data.fillColor === 0) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fillRect(points[0], points[1], points[2], points[3]); - - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.strokeRect(points[0], points[1], points[2], points[3]); - } - - } - else if(data.type == PIXI.Graphics.CIRC) - { - // TODO - need to be Undefined! - context.beginPath(); - context.arc(points[0], points[1], points[2],0,2*Math.PI); - context.closePath(); - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - else if(data.type == PIXI.Graphics.ELIP) - { - - // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - - var elipseData = data.points; - - var w = elipseData[2] * 2; - var h = elipseData[3] * 2; - - var x = elipseData[0] - w/2; - var y = elipseData[1] - h/2; - - context.beginPath(); - - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - - context.moveTo(x, ym); - context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - - context.closePath(); - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - - }; -} - -/* - * Renders a graphics mask - * - * @static - * @private - * @method renderGraphicsMask - * @param graphics {Graphics} - * @param context {Context2D} - */ -PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) -{ - var worldAlpha = graphics.worldAlpha; - - var len = graphics.graphicsData.length; - if(len > 1) - { - len = 1; - console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") - } - - for (var i=0; i < 1; i++) - { - var data = graphics.graphicsData[i]; - var points = data.points; - - if(data.type == PIXI.Graphics.POLY) - { - context.beginPath(); - context.moveTo(points[0], points[1]); - - for (var j=1; j < points.length/2; j++) - { - context.lineTo(points[j * 2], points[j * 2 + 1]); - } - - // if the first and last point are the same close the path - much neater :) - if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) - { - context.closePath(); - } - - } - else if(data.type == PIXI.Graphics.RECT) - { - context.beginPath(); - context.rect(points[0], points[1], points[2], points[3]); - context.closePath(); - } - else if(data.type == PIXI.Graphics.CIRC) - { - // TODO - need to be Undefined! - context.beginPath(); - context.arc(points[0], points[1], points[2],0,2*Math.PI); - context.closePath(); - } - else if(data.type == PIXI.Graphics.ELIP) - { - - // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - var elipseData = data.points; - - var w = elipseData[2] * 2; - var h = elipseData[3] * 2; - - var x = elipseData[0] - w/2; - var y = elipseData[1] - h/2; - - context.beginPath(); - - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - - context.moveTo(x, ym); - context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - context.closePath(); - } - - - }; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. - * It is important to know that with the webGL renderer only simple polys can be filled at this stage - * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png - * - * @class Graphics - * @extends DisplayObjectContainer - * @constructor - */ -PIXI.Graphics = function() -{ - PIXI.DisplayObjectContainer.call( this ); - - this.renderable = true; - - /** - * The alpha of the fill of this graphics object - * - * @property fillAlpha - * @type Number - */ - this.fillAlpha = 1; - - /** - * The width of any lines drawn - * - * @property lineWidth - * @type Number - */ - this.lineWidth = 0; - - /** - * The color of any lines drawn - * - * @property lineColor - * @type String - */ - this.lineColor = "black"; - - /** - * Graphics data - * - * @property graphicsData - * @type Array - * @private - */ - this.graphicsData = []; - - /** - * Current path - * - * @property currentPath - * @type Object - * @private - */ - this.currentPath = {points:[]}; -} - -// constructor -PIXI.Graphics.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Graphics.prototype.constructor = PIXI.Graphics; - -/** - * Specifies a line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method. - * - * @method lineStyle - * @param lineWidth {Number} width of the line to draw, will update the object's stored style - * @param color {Number} color of the line to draw, will update the object's stored style - * @param alpha {Number} alpha of the line to draw, will update the object's stored style - */ -PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.lineWidth = lineWidth || 0; - this.lineColor = color || 0; - this.lineAlpha = (alpha == undefined) ? 1 : alpha; - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - - this.graphicsData.push(this.currentPath); -} - -/** - * Moves the current drawing position to (x, y). - * - * @method moveTo - * @param x {Number} the X coord to move to - * @param y {Number} the Y coord to move to - */ -PIXI.Graphics.prototype.moveTo = function(x, y) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - - this.currentPath.points.push(x, y); - - this.graphicsData.push(this.currentPath); -} - -/** - * Draws a line using the current line style from the current drawing position to (x, y); - * the current drawing position is then set to (x, y). - * - * @method lineTo - * @param x {Number} the X coord to draw to - * @param y {Number} the Y coord to draw to - */ -PIXI.Graphics.prototype.lineTo = function(x, y) -{ - this.currentPath.points.push(x, y); - this.dirty = true; -} - -/** - * Specifies a simple one-color fill that subsequent calls to other Graphics methods - * (such as lineTo() or drawCircle()) use when drawing. - * - * @method beginFill - * @param color {uint} the color of the fill - * @param alpha {Number} the alpha - */ -PIXI.Graphics.prototype.beginFill = function(color, alpha) -{ - this.filling = true; - this.fillColor = color || 0; - this.fillAlpha = (alpha == undefined) ? 1 : alpha; -} - -/** - * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. - * - * @method endFill - */ -PIXI.Graphics.prototype.endFill = function() -{ - this.filling = false; - this.fillColor = null; - this.fillAlpha = 1; -} - -/** - * @method drawRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - */ -PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, width, height], type:PIXI.Graphics.RECT}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Draws a circle. - * - * @method drawCircle - * @param x {Number} The X coord of the center of the circle - * @param y {Number} The Y coord of the center of the circle - * @param radius {Number} The radius of the circle - */ -PIXI.Graphics.prototype.drawCircle = function( x, y, radius) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Draws an elipse. - * - * @method drawElipse - * @param x {Number} - * @param y {Number} - * @param width {Number} - * @param height {Number} - */ -PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, width, height], type:PIXI.Graphics.ELIP}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @method clear - */ -PIXI.Graphics.prototype.clear = function() -{ - this.lineWidth = 0; - this.filling = false; - - this.dirty = true; - this.clearDirty = true; - this.graphicsData = []; -} - -// SOME TYPES: -PIXI.Graphics.POLY = 0; -PIXI.Graphics.RECT = 1; -PIXI.Graphics.CIRC = 2; -PIXI.Graphics.ELIP = 3; - -/** - * @author Mat Groves http://matgroves.com/ - */ - -PIXI.Strip = function(texture, width, height) -{ - PIXI.DisplayObjectContainer.call( this ); - this.texture = texture; - this.blendMode = PIXI.blendModes.NORMAL; - - try - { - this.uvs = new Float32Array([0, 1, - 1, 1, - 1, 0, 0,1]); - - this.verticies = new Float32Array([0, 0, - 0,0, - 0,0, 0, - 0, 0]); - - this.colors = new Float32Array([1, 1, 1, 1]); - - this.indices = new Uint16Array([0, 1, 2, 3]); - } - catch(error) - { - this.uvs = [0, 1, - 1, 1, - 1, 0, 0,1]; - - this.verticies = [0, 0, - 0,0, - 0,0, 0, - 0, 0]; - - this.colors = [1, 1, 1, 1]; - - this.indices = [0, 1, 2, 3]; - } - - - /* - this.uvs = new Float32Array() - this.verticies = new Float32Array() - this.colors = new Float32Array() - this.indices = new Uint16Array() -*/ - this.width = width; - this.height = height; - - // load the texture! - if(texture.baseTexture.hasLoaded) - { - this.width = this.texture.frame.width; - this.height = this.texture.frame.height; - this.updateFrame = true; - } - else - { - this.onTextureUpdateBind = this.onTextureUpdate.bind(this); - this.texture.addEventListener( 'update', this.onTextureUpdateBind ); - } - - this.renderable = true; -} - -// constructor -PIXI.Strip.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Strip.prototype.constructor = PIXI.Strip; - -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; -} - -PIXI.Strip.prototype.onTextureUpdate = function(event) -{ - this.updateFrame = true; -} -// some helper functions.. - - -/** - * @author Mat Groves http://matgroves.com/ - */ - - -PIXI.Rope = function(texture, points) -{ - PIXI.Strip.call( this, texture ); - this.points = points; - - try - { - this.verticies = new Float32Array( points.length * 4); - this.uvs = new Float32Array( points.length * 4); - this.colors = new Float32Array( points.length * 2); - this.indices = new Uint16Array( points.length * 2); - } - catch(error) - { - this.verticies = verticies - - this.uvs = uvs - this.colors = colors - this.indices = indices - } - - this.refresh(); -} - - -// constructor -PIXI.Rope.prototype = Object.create( PIXI.Strip.prototype ); -PIXI.Rope.prototype.constructor = PIXI.Rope; - -PIXI.Rope.prototype.refresh = function() -{ - var points = this.points; - if(points.length < 1)return; - - var uvs = this.uvs - var indices = this.indices; - var colors = this.colors; - - var lastPoint = points[0]; - var nextPoint; - var perp = {x:0, y:0}; - var point = points[0]; - - this.count-=0.2; - - - uvs[0] = 0 - uvs[1] = 1 - uvs[2] = 0 - uvs[3] = 1 - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length; - - for (var i = 1; i < total; i++) - { - - var point = points[i]; - var index = i * 4; - // time to do some smart drawing! - var 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; - } -} - -PIXI.Rope.prototype.updateTransform = function() -{ - - var points = this.points; - if(points.length < 1)return; - - var verticies = this.verticies - - var lastPoint = points[0]; - var nextPoint; - var perp = {x:0, y:0}; - var point = points[0]; - - this.count-=0.2; - - verticies[0] = point.x + perp.x - verticies[1] = point.y + perp.y //+ 200 - verticies[2] = point.x - perp.x - verticies[3] = point.y - perp.y//+200 - // time to do some smart drawing! - - var total = points.length; - - for (var i = 1; i < total; i++) - { - - var point = points[i]; - var 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; - - var ratio = (1 - (i / (total-1))) * 10; - if(ratio > 1)ratio = 1; - - var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); - var 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; - - verticies[index] = point.x + perp.x - verticies[index+1] = point.y + perp.y - verticies[index+2] = point.x - perp.x - verticies[index+3] = point.y - perp.y - - lastPoint = point; - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); -} - -PIXI.Rope.prototype.setTexture = function(texture) -{ - // stop current texture - this.texture = texture; - this.updateFrame = true; -} - - - - - -/** - * @author Mat Groves http://matgroves.com/ - */ - -/** - * A tiling sprite is a fast way of rendering a tiling image - * - * @class TilingSprite - * @extends DisplayObjectContainer - * @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.DisplayObjectContainer.call( this ); - - /** - * The texture that the sprite is using - * - * @property texture - * @type Texture - */ - this.texture = texture; - - /** - * The width of the tiling sprite - * - * @property width - * @type Number - */ - this.width = width; - - /** - * The height of the tiling sprite - * - * @property height - * @type Number - */ - this.height = height; - - /** - * The scaling of the image that is being tiled - * - * @property tileScale - * @type Point - */ - this.tileScale = 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); - - this.renderable = true; - - this.blendMode = PIXI.blendModes.NORMAL -} - -// constructor -PIXI.TilingSprite.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite; - -/** - * Sets the texture of the tiling sprite - * - * @method setTexture - * @param texture {Texture} The PIXI texture that is displayed by the sprite - */ -PIXI.TilingSprite.prototype.setTexture = function(texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - - // stop current texture - this.texture = texture; - this.updateFrame = true; -} - -/** - * When the texture is updated, this event will fire to update the frame - * - * @method onTextureUpdate - * @param event - * @private - */ -PIXI.TilingSprite.prototype.onTextureUpdate = function(event) -{ - this.updateFrame = true; -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * - * Awesome JS run time provided by EsotericSoftware - * https://github.com/EsotericSoftware/spine-runtimes - * - */ - -/** - * 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)) { - continue; - } - var spriteName = attachment.rendererObject.name; - var sprite = this.createSprite(slot, attachment.rendererObject); - slot.currentSprite = sprite; - slot.currentSpriteName = spriteName; - slotContainer.addChild(sprite); - } -}; - -PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); -PIXI.Spine.prototype.constructor = PIXI.Spine; - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.Spine.prototype.updateTransform = function () { - this.lastTime = this.lastTime || Date.now(); - var timeDelta = (Date.now() - this.lastTime) * 0.001; - this.lastTime = Date.now(); - this.state.update(timeDelta); - 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 instanceof spine.RegionAttachment)) { - slotContainer.visible = false; - continue; - } - - 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.rendererObject); - slotContainer.addChild(sprite); - } - slot.currentSprite = slot.sprites[spriteName]; - slot.currentSpriteName = spriteName; - } - } - slotContainer.visible = true; - - 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 * Math.PI / 180); - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -}; - - -PIXI.Spine.prototype.createSprite = function (slot, descriptor) { - var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); - sprite.scale = descriptor.scale; - sprite.rotation = descriptor.rotation; - sprite.anchor.x = sprite.anchor.y = 0.5; - - slot.sprites = slot.sprites || {}; - slot.sprites[descriptor.name] = sprite; - return sprite; -}; - -/* - * Awesome JS run time provided by EsotericSoftware - * - * https://github.com/EsotericSoftware/spine-runtimes - * - */ - -var spine = {}; - -spine.BoneData = function (name, parent) { - this.name = name; - this.parent = parent; -}; -spine.BoneData.prototype = { - length: 0, - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1 -}; - -spine.SlotData = function (name, boneData) { - this.name = name; - this.boneData = boneData; -}; -spine.SlotData.prototype = { - r: 1, g: 1, b: 1, a: 1, - attachmentName: null -}; - -spine.Bone = function (boneData, parent) { - this.data = boneData; - this.parent = parent; - this.setToSetupPose(); -}; -spine.Bone.yDown = false; -spine.Bone.prototype = { - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1, - m00: 0, m01: 0, worldX: 0, // a b x - m10: 0, m11: 0, worldY: 0, // c d y - worldRotation: 0, - worldScaleX: 1, worldScaleY: 1, - updateWorldTransform: function (flipX, flipY) { - var parent = this.parent; - if (parent != null) { - this.worldX = this.x * parent.m00 + this.y * parent.m01 + parent.worldX; - this.worldY = this.x * parent.m10 + this.y * parent.m11 + parent.worldY; - this.worldScaleX = parent.worldScaleX * this.scaleX; - this.worldScaleY = parent.worldScaleY * this.scaleY; - this.worldRotation = parent.worldRotation + this.rotation; - } else { - this.worldX = this.x; - this.worldY = this.y; - this.worldScaleX = this.scaleX; - this.worldScaleY = this.scaleY; - this.worldRotation = this.rotation; - } - var radians = this.worldRotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - this.m00 = cos * this.worldScaleX; - this.m10 = sin * this.worldScaleX; - this.m01 = -sin * this.worldScaleY; - this.m11 = cos * this.worldScaleY; - if (flipX) { - this.m00 = -this.m00; - this.m01 = -this.m01; - } - if (flipY) { - this.m10 = -this.m10; - this.m11 = -this.m11; - } - if (spine.Bone.yDown) { - this.m10 = -this.m10; - this.m11 = -this.m11; - } - }, - setToSetupPose: function () { - var data = this.data; - this.x = data.x; - this.y = data.y; - this.rotation = data.rotation; - this.scaleX = data.scaleX; - this.scaleY = data.scaleY; - } -}; - -spine.Slot = function (slotData, skeleton, bone) { - this.data = slotData; - this.skeleton = skeleton; - this.bone = bone; - this.setToSetupPose(); -}; -spine.Slot.prototype = { - r: 1, g: 1, b: 1, a: 1, - _attachmentTime: 0, - attachment: null, - setAttachment: function (attachment) { - this.attachment = attachment; - this._attachmentTime = this.skeleton.time; - }, - setAttachmentTime: function (time) { - this._attachmentTime = this.skeleton.time - time; - }, - getAttachmentTime: function () { - return this.skeleton.time - this._attachmentTime; - }, - setToSetupPose: function () { - var data = this.data; - this.r = data.r; - this.g = data.g; - this.b = data.b; - this.a = data.a; - - var slotDatas = this.skeleton.data.slots; - for (var i = 0, n = slotDatas.length; i < n; i++) { - if (slotDatas[i] == data) { - this.setAttachment(!data.attachmentName ? null : this.skeleton.getAttachmentBySlotIndex(i, data.attachmentName)); - break; - } - } - } -}; - -spine.Skin = function (name) { - this.name = name; - this.attachments = {}; -}; -spine.Skin.prototype = { - addAttachment: function (slotIndex, name, attachment) { - this.attachments[slotIndex + ":" + name] = attachment; - }, - getAttachment: function (slotIndex, name) { - return this.attachments[slotIndex + ":" + name]; - }, - _attachAll: function (skeleton, oldSkin) { - for (var key in oldSkin.attachments) { - var colon = key.indexOf(":"); - var slotIndex = parseInt(key.substring(0, colon)); - var name = key.substring(colon + 1); - var slot = skeleton.slots[slotIndex]; - if (slot.attachment && slot.attachment.name == name) { - var attachment = this.getAttachment(slotIndex, name); - if (attachment) slot.setAttachment(attachment); - } - } - } -}; - -spine.Animation = function (name, timelines, duration) { - this.name = name; - this.timelines = timelines; - this.duration = duration; -}; -spine.Animation.prototype = { - apply: function (skeleton, time, loop) { - if (loop && this.duration != 0) time %= this.duration; - var timelines = this.timelines; - for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, time, 1); - }, - mix: function (skeleton, time, loop, alpha) { - if (loop && this.duration != 0) time %= this.duration; - var timelines = this.timelines; - for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, time, alpha); - } -}; - -spine.binarySearch = function (values, target, step) { - var low = 0; - var high = Math.floor(values.length / step) - 2; - if (high == 0) return step; - var current = high >>> 1; - while (true) { - if (values[(current + 1) * step] <= target) - low = current + 1; - else - high = current; - if (low == high) return (low + 1) * step; - current = (low + high) >>> 1; - } -}; -spine.linearSearch = function (values, target, step) { - for (var i = 0, last = values.length - step; i <= last; i += step) - if (values[i] > target) return i; - return -1; -}; - -spine.Curves = function (frameCount) { - this.curves = []; // dfx, dfy, ddfx, ddfy, dddfx, dddfy, ... - this.curves.length = (frameCount - 1) * 6; -}; -spine.Curves.prototype = { - setLinear: function (frameIndex) { - this.curves[frameIndex * 6] = 0/*LINEAR*/; - }, - setStepped: function (frameIndex) { - this.curves[frameIndex * 6] = -1/*STEPPED*/; - }, - /** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next. - * cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of - * the difference between the keyframe's values. */ - setCurve: function (frameIndex, cx1, cy1, cx2, cy2) { - var subdiv_step = 1 / 10/*BEZIER_SEGMENTS*/; - var subdiv_step2 = subdiv_step * subdiv_step; - var subdiv_step3 = subdiv_step2 * subdiv_step; - var pre1 = 3 * subdiv_step; - var pre2 = 3 * subdiv_step2; - var pre4 = 6 * subdiv_step2; - var pre5 = 6 * subdiv_step3; - var tmp1x = -cx1 * 2 + cx2; - var tmp1y = -cy1 * 2 + cy2; - var tmp2x = (cx1 - cx2) * 3 + 1; - var tmp2y = (cy1 - cy2) * 3 + 1; - var i = frameIndex * 6; - var curves = this.curves; - curves[i] = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; - curves[i + 1] = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; - curves[i + 2] = tmp1x * pre4 + tmp2x * pre5; - curves[i + 3] = tmp1y * pre4 + tmp2y * pre5; - curves[i + 4] = tmp2x * pre5; - curves[i + 5] = tmp2y * pre5; - }, - getCurvePercent: function (frameIndex, percent) { - percent = percent < 0 ? 0 : (percent > 1 ? 1 : percent); - var curveIndex = frameIndex * 6; - var curves = this.curves; - var dfx = curves[curveIndex]; - if (!dfx/*LINEAR*/) return percent; - if (dfx == -1/*STEPPED*/) return 0; - var dfy = curves[curveIndex + 1]; - var ddfx = curves[curveIndex + 2]; - var ddfy = curves[curveIndex + 3]; - var dddfx = curves[curveIndex + 4]; - var dddfy = curves[curveIndex + 5]; - var x = dfx, y = dfy; - var i = 10/*BEZIER_SEGMENTS*/ - 2; - while (true) { - if (x >= percent) { - var lastX = x - dfx; - var lastY = y - dfy; - return lastY + (y - lastY) * (percent - lastX) / (x - lastX); - } - if (i == 0) break; - i--; - dfx += ddfx; - dfy += ddfy; - ddfx += dddfx; - ddfy += dddfy; - x += dfx; - y += dfy; - } - return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1. - } -}; - -spine.RotateTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, angle, ... - this.frames.length = frameCount * 2; -}; -spine.RotateTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 2; - }, - setFrame: function (frameIndex, time, angle) { - frameIndex *= 2; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = angle; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 2]) { // Time is after last frame. - var amount = bone.data.rotation + frames[frames.length - 1] - bone.rotation; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - bone.rotation += amount * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 2); - var lastFrameValue = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex - 2/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent); - - var amount = frames[frameIndex + 1/*FRAME_VALUE*/] - lastFrameValue; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - amount = bone.data.rotation + (lastFrameValue + amount * percent) - bone.rotation; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - bone.rotation += amount * alpha; - } -}; - -spine.TranslateTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, x, y, ... - this.frames.length = frameCount * 3; -}; -spine.TranslateTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 3; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 3; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = x; - this.frames[frameIndex + 2] = y; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 3]) { // Time is after last frame. - bone.x += (bone.data.x + frames[frames.length - 2] - bone.x) * alpha; - bone.y += (bone.data.y + frames[frames.length - 1] - bone.y) * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 3); - var lastFrameX = frames[frameIndex - 2]; - var lastFrameY = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); - - bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; - bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; - } -}; - -spine.ScaleTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, x, y, ... - this.frames.length = frameCount * 3; -}; -spine.ScaleTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 3; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 3; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = x; - this.frames[frameIndex + 2] = y; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 3]) { // Time is after last frame. - bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 3); - var lastFrameX = frames[frameIndex - 2]; - var lastFrameY = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); - - bone.scaleX += (bone.data.scaleX - 1 + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - 1 + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.scaleY) * alpha; - } -}; - -spine.ColorTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, r, g, b, a, ... - this.frames.length = frameCount * 5; -}; -spine.ColorTimeline.prototype = { - slotIndex: 0, - getFrameCount: function () { - return this.frames.length / 2; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 5; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = r; - this.frames[frameIndex + 2] = g; - this.frames[frameIndex + 3] = b; - this.frames[frameIndex + 4] = a; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var slot = skeleton.slots[this.slotIndex]; - - if (time >= frames[frames.length - 5]) { // Time is after last frame. - var i = frames.length - 1; - slot.r = frames[i - 3]; - slot.g = frames[i - 2]; - slot.b = frames[i - 1]; - slot.a = frames[i]; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 5); - var lastFrameR = frames[frameIndex - 4]; - var lastFrameG = frames[frameIndex - 3]; - var lastFrameB = frames[frameIndex - 2]; - var lastFrameA = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex - 5/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent); - - var r = lastFrameR + (frames[frameIndex + 1/*FRAME_R*/] - lastFrameR) * percent; - var g = lastFrameG + (frames[frameIndex + 2/*FRAME_G*/] - lastFrameG) * percent; - var b = lastFrameB + (frames[frameIndex + 3/*FRAME_B*/] - lastFrameB) * percent; - var a = lastFrameA + (frames[frameIndex + 4/*FRAME_A*/] - lastFrameA) * percent; - if (alpha < 1) { - slot.r += (r - slot.r) * alpha; - slot.g += (g - slot.g) * alpha; - slot.b += (b - slot.b) * alpha; - slot.a += (a - slot.a) * alpha; - } else { - slot.r = r; - slot.g = g; - slot.b = b; - slot.a = a; - } - } -}; - -spine.AttachmentTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, ... - this.frames.length = frameCount; - this.attachmentNames = []; // time, ... - this.attachmentNames.length = frameCount; -}; -spine.AttachmentTimeline.prototype = { - slotIndex: 0, - getFrameCount: function () { - return this.frames.length; - }, - setFrame: function (frameIndex, time, attachmentName) { - this.frames[frameIndex] = time; - this.attachmentNames[frameIndex] = attachmentName; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var frameIndex; - if (time >= frames[frames.length - 1]) // Time is after last frame. - frameIndex = frames.length - 1; - else - frameIndex = spine.binarySearch(frames, time, 1) - 1; - - var attachmentName = this.attachmentNames[frameIndex]; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); - } -}; - -spine.SkeletonData = function () { - this.bones = []; - this.slots = []; - this.skins = []; - this.animations = []; -}; -spine.SkeletonData.prototype = { - defaultSkin: null, - /** @return May be null. */ - findBone: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].name == boneName) return bones[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findBoneIndex: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].name == boneName) return i; - return -1; - }, - /** @return May be null. */ - findSlot: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) { - if (slots[i].name == slotName) return slot[i]; - } - return null; - }, - /** @return -1 if the bone was not found. */ - findSlotIndex: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].name == slotName) return i; - return -1; - }, - /** @return May be null. */ - findSkin: function (skinName) { - var skins = this.skins; - for (var i = 0, n = skins.length; i < n; i++) - if (skins[i].name == skinName) return skins[i]; - return null; - }, - /** @return May be null. */ - findAnimation: function (animationName) { - var animations = this.animations; - for (var i = 0, n = animations.length; i < n; i++) - if (animations[i].name == animationName) return animations[i]; - return null; - } -}; - -spine.Skeleton = function (skeletonData) { - this.data = skeletonData; - - this.bones = []; - for (var i = 0, n = skeletonData.bones.length; i < n; i++) { - var boneData = skeletonData.bones[i]; - var parent = !boneData.parent ? null : this.bones[skeletonData.bones.indexOf(boneData.parent)]; - this.bones.push(new spine.Bone(boneData, parent)); - } - - this.slots = []; - this.drawOrder = []; - for (var i = 0, n = skeletonData.slots.length; i < n; i++) { - var slotData = skeletonData.slots[i]; - var bone = this.bones[skeletonData.bones.indexOf(slotData.boneData)]; - var slot = new spine.Slot(slotData, this, bone); - this.slots.push(slot); - this.drawOrder.push(slot); - } -}; -spine.Skeleton.prototype = { - x: 0, y: 0, - skin: null, - r: 1, g: 1, b: 1, a: 1, - time: 0, - flipX: false, flipY: false, - /** Updates the world transform for each bone. */ - updateWorldTransform: function () { - var flipX = this.flipX; - var flipY = this.flipY; - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - bones[i].updateWorldTransform(flipX, flipY); - }, - /** Sets the bones and slots to their setup pose values. */ - setToSetupPose: function () { - this.setBonesToSetupPose(); - this.setSlotsToSetupPose(); - }, - setBonesToSetupPose: function () { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - bones[i].setToSetupPose(); - }, - setSlotsToSetupPose: function () { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - slots[i].setToSetupPose(i); - }, - /** @return May return null. */ - getRootBone: function () { - return this.bones.length == 0 ? null : this.bones[0]; - }, - /** @return May be null. */ - findBone: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].data.name == boneName) return bones[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findBoneIndex: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].data.name == boneName) return i; - return -1; - }, - /** @return May be null. */ - findSlot: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].data.name == slotName) return slots[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findSlotIndex: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].data.name == slotName) return i; - return -1; - }, - setSkinByName: function (skinName) { - var skin = this.data.findSkin(skinName); - if (!skin) throw "Skin not found: " + skinName; - this.setSkin(skin); - }, - /** Sets the skin used to look up attachments not found in the {@link SkeletonData#getDefaultSkin() default skin}. Attachments - * from the new skin are attached if the corresponding attachment from the old skin was attached. - * @param newSkin May be null. */ - setSkin: function (newSkin) { - if (this.skin && newSkin) newSkin._attachAll(this, this.skin); - this.skin = newSkin; - }, - /** @return May be null. */ - getAttachmentBySlotName: function (slotName, attachmentName) { - return this.getAttachmentBySlotIndex(this.data.findSlotIndex(slotName), attachmentName); - }, - /** @return May be null. */ - getAttachmentBySlotIndex: function (slotIndex, attachmentName) { - if (this.skin) { - var attachment = this.skin.getAttachment(slotIndex, attachmentName); - if (attachment) return attachment; - } - if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); - return null; - }, - /** @param attachmentName May be null. */ - setAttachment: function (slotName, attachmentName) { - var slots = this.slots; - for (var i = 0, n = slots.size; i < n; i++) { - var slot = slots[i]; - if (slot.data.name == slotName) { - var attachment = null; - if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); - if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; - } - slot.setAttachment(attachment); - return; - } - } - throw "Slot not found: " + slotName; - }, - update: function (delta) { - time += delta; - } -}; - -spine.AttachmentType = { - region: 0 -}; - -spine.RegionAttachment = function () { - this.offset = []; - this.offset.length = 8; - this.uvs = []; - this.uvs.length = 8; -}; -spine.RegionAttachment.prototype = { - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1, - width: 0, height: 0, - rendererObject: null, - regionOffsetX: 0, regionOffsetY: 0, - regionWidth: 0, regionHeight: 0, - regionOriginalWidth: 0, regionOriginalHeight: 0, - setUVs: function (u, v, u2, v2, rotate) { - var uvs = this.uvs; - if (rotate) { - uvs[2/*X2*/] = u; - uvs[3/*Y2*/] = v2; - uvs[4/*X3*/] = u; - uvs[5/*Y3*/] = v; - uvs[6/*X4*/] = u2; - uvs[7/*Y4*/] = v; - uvs[0/*X1*/] = u2; - uvs[1/*Y1*/] = v2; - } else { - uvs[0/*X1*/] = u; - uvs[1/*Y1*/] = v2; - uvs[2/*X2*/] = u; - uvs[3/*Y2*/] = v; - uvs[4/*X3*/] = u2; - uvs[5/*Y3*/] = v; - uvs[6/*X4*/] = u2; - uvs[7/*Y4*/] = v2; - } - }, - updateOffset: function () { - var regionScaleX = this.width / this.regionOriginalWidth * this.scaleX; - var regionScaleY = this.height / this.regionOriginalHeight * this.scaleY; - var localX = -this.width / 2 * this.scaleX + this.regionOffsetX * regionScaleX; - var localY = -this.height / 2 * this.scaleY + this.regionOffsetY * regionScaleY; - var localX2 = localX + this.regionWidth * regionScaleX; - var localY2 = localY + this.regionHeight * regionScaleY; - var radians = this.rotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - var localXCos = localX * cos + this.x; - var localXSin = localX * sin; - var localYCos = localY * cos + this.y; - var localYSin = localY * sin; - var localX2Cos = localX2 * cos + this.x; - var localX2Sin = localX2 * sin; - var localY2Cos = localY2 * cos + this.y; - var localY2Sin = localY2 * sin; - var offset = this.offset; - offset[0/*X1*/] = localXCos - localYSin; - offset[1/*Y1*/] = localYCos + localXSin; - offset[2/*X2*/] = localXCos - localY2Sin; - offset[3/*Y2*/] = localY2Cos + localXSin; - offset[4/*X3*/] = localX2Cos - localY2Sin; - offset[5/*Y3*/] = localY2Cos + localX2Sin; - offset[6/*X4*/] = localX2Cos - localYSin; - offset[7/*Y4*/] = localYCos + localX2Sin; - }, - computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; - y += bone.worldY; - var m00 = bone.m00; - var m01 = bone.m01; - var m10 = bone.m10; - var m11 = bone.m11; - var offset = this.offset; - vertices[0/*X1*/] = offset[0/*X1*/] * m00 + offset[1/*Y1*/] * m01 + x; - vertices[1/*Y1*/] = offset[0/*X1*/] * m10 + offset[1/*Y1*/] * m11 + y; - vertices[2/*X2*/] = offset[2/*X2*/] * m00 + offset[3/*Y2*/] * m01 + x; - vertices[3/*Y2*/] = offset[2/*X2*/] * m10 + offset[3/*Y2*/] * m11 + y; - vertices[4/*X3*/] = offset[4/*X3*/] * m00 + offset[5/*X3*/] * m01 + x; - vertices[5/*X3*/] = offset[4/*X3*/] * m10 + offset[5/*X3*/] * m11 + y; - vertices[6/*X4*/] = offset[6/*X4*/] * m00 + offset[7/*Y4*/] * m01 + x; - vertices[7/*Y4*/] = offset[6/*X4*/] * m10 + offset[7/*Y4*/] * m11 + y; - } -} - -spine.AnimationStateData = function (skeletonData) { - this.skeletonData = skeletonData; - this.animationToMixTime = {}; -}; -spine.AnimationStateData.prototype = { - defaultMix: 0, - setMixByName: function (fromName, toName, duration) { - var from = this.skeletonData.findAnimation(fromName); - if (!from) throw "Animation not found: " + fromName; - var to = this.skeletonData.findAnimation(toName); - if (!to) throw "Animation not found: " + toName; - this.setMix(from, to, duration); - }, - setMix: function (from, to, duration) { - this.animationToMixTime[from.name + ":" + to.name] = duration; - }, - getMix: function (from, to) { - var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : this.defaultMix; - } -}; - -spine.AnimationState = function (stateData) { - this.data = stateData; - this.queue = []; -}; -spine.AnimationState.prototype = { - current: null, - previous: null, - currentTime: 0, - previousTime: 0, - currentLoop: false, - previousLoop: false, - mixTime: 0, - mixDuration: 0, - update: function (delta) { - this.currentTime += delta; - this.previousTime += delta; - this.mixTime += delta; - - if (this.queue.length > 0) { - var entry = this.queue[0]; - if (this.currentTime >= entry.delay) { - this._setAnimation(entry.animation, entry.loop); - this.queue.shift(); - } - } - }, - apply: function (skeleton) { - if (!this.current) return; - if (this.previous) { - this.previous.apply(skeleton, this.previousTime, this.previousLoop); - var alpha = this.mixTime / this.mixDuration; - if (alpha >= 1) { - alpha = 1; - this.previous = null; - } - this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else - this.current.apply(skeleton, this.currentTime, this.currentLoop); - }, - clearAnimation: function () { - this.previous = null; - this.current = null; - this.queue.length = 0; - }, - _setAnimation: function (animation, loop) { - this.previous = null; - if (animation && this.current) { - this.mixDuration = this.data.getMix(this.current, animation); - if (this.mixDuration > 0) { - this.mixTime = 0; - this.previous = this.current; - this.previousTime = this.currentTime; - this.previousLoop = this.currentLoop; - } - } - this.current = animation; - this.currentLoop = loop; - this.currentTime = 0; - }, - /** @see #setAnimation(Animation, Boolean) */ - setAnimationByName: function (animationName, loop) { - var animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw "Animation not found: " + animationName; - this.setAnimation(animation, loop); - }, - /** Set the current animation. Any queued animations are cleared and the current animation time is set to 0. - * @param animation May be null. */ - setAnimation: function (animation, loop) { - this.queue.length = 0; - this._setAnimation(animation, loop); - }, - /** @see #addAnimation(Animation, Boolean, Number) */ - addAnimationByName: function (animationName, loop, delay) { - var animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw "Animation not found: " + animationName; - this.addAnimation(animation, loop, delay); - }, - /** Adds an animation to be played delay seconds after the current or last queued animation. - * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */ - addAnimation: function (animation, loop, delay) { - var entry = {}; - entry.animation = animation; - entry.loop = loop; - - if (!delay || delay <= 0) { - var previousAnimation = this.queue.length == 0 ? this.current : this.queue[this.queue.length - 1].animation; - if (previousAnimation != null) - delay = previousAnimation.duration - this.data.getMix(previousAnimation, animation) + (delay || 0); - else - delay = 0; - } - entry.delay = delay; - - this.queue.push(entry); - }, - /** Returns true if no animation is set or if the current time is greater than the animation duration, regardless of looping. */ - isComplete: function () { - return !this.current || this.currentTime >= this.current.duration; - } -}; - -spine.SkeletonJson = function (attachmentLoader) { - this.attachmentLoader = attachmentLoader; -}; -spine.SkeletonJson.prototype = { - scale: 1, - readSkeletonData: function (root) { - var skeletonData = new spine.SkeletonData(); - - // Bones. - var bones = root["bones"]; - for (var i = 0, n = bones.length; i < n; i++) { - var boneMap = bones[i]; - var parent = null; - if (boneMap["parent"]) { - parent = skeletonData.findBone(boneMap["parent"]); - if (!parent) throw "Parent bone not found: " + boneMap["parent"]; - } - var boneData = new spine.BoneData(boneMap["name"], parent); - boneData.length = (boneMap["length"] || 0) * this.scale; - boneData.x = (boneMap["x"] || 0) * this.scale; - boneData.y = (boneMap["y"] || 0) * this.scale; - boneData.rotation = (boneMap["rotation"] || 0); - boneData.scaleX = boneMap["scaleX"] || 1; - boneData.scaleY = boneMap["scaleY"] || 1; - skeletonData.bones.push(boneData); - } - - // Slots. - var slots = root["slots"]; - for (var i = 0, n = slots.length; i < n; i++) { - var slotMap = slots[i]; - var boneData = skeletonData.findBone(slotMap["bone"]); - if (!boneData) throw "Slot bone not found: " + slotMap["bone"]; - var slotData = new spine.SlotData(slotMap["name"], boneData); - - var color = slotMap["color"]; - if (color) { - slotData.r = spine.SkeletonJson.toColor(color, 0); - slotData.g = spine.SkeletonJson.toColor(color, 1); - slotData.b = spine.SkeletonJson.toColor(color, 2); - slotData.a = spine.SkeletonJson.toColor(color, 3); - } - - slotData.attachmentName = slotMap["attachment"]; - - skeletonData.slots.push(slotData); - } - - // Skins. - var skins = root["skins"]; - for (var skinName in skins) { - if (!skins.hasOwnProperty(skinName)) continue; - var skinMap = skins[skinName]; - var skin = new spine.Skin(skinName); - for (var slotName in skinMap) { - if (!skinMap.hasOwnProperty(slotName)) continue; - var slotIndex = skeletonData.findSlotIndex(slotName); - var slotEntry = skinMap[slotName]; - for (var attachmentName in slotEntry) { - if (!slotEntry.hasOwnProperty(attachmentName)) continue; - var attachment = this.readAttachment(skin, attachmentName, slotEntry[attachmentName]); - if (attachment != null) skin.addAttachment(slotIndex, attachmentName, attachment); - } - } - skeletonData.skins.push(skin); - if (skin.name == "default") skeletonData.defaultSkin = skin; - } - - // Animations. - var animations = root["animations"]; - for (var animationName in animations) { - if (!animations.hasOwnProperty(animationName)) continue; - this.readAnimation(animationName, animations[animationName], skeletonData); - } - - return skeletonData; - }, - readAttachment: function (skin, name, map) { - name = map["name"] || name; - - var type = spine.AttachmentType[map["type"] || "region"]; - - if (type == spine.AttachmentType.region) { - var attachment = new spine.RegionAttachment(); - attachment.x = (map["x"] || 0) * this.scale; - attachment.y = (map["y"] || 0) * this.scale; - attachment.scaleX = map["scaleX"] || 1; - attachment.scaleY = map["scaleY"] || 1; - attachment.rotation = map["rotation"] || 0; - attachment.width = (map["width"] || 32) * this.scale; - attachment.height = (map["height"] || 32) * this.scale; - attachment.updateOffset(); - - attachment.rendererObject = {}; - attachment.rendererObject.name = name; - attachment.rendererObject.scale = {}; - attachment.rendererObject.scale.x = attachment.scaleX; - attachment.rendererObject.scale.y = attachment.scaleY; - attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; - return attachment; - } - - throw "Unknown attachment type: " + type; - }, - - readAnimation: function (name, map, skeletonData) { - var timelines = []; - var duration = 0; - - var bones = map["bones"]; - for (var boneName in bones) { - if (!bones.hasOwnProperty(boneName)) continue; - var boneIndex = skeletonData.findBoneIndex(boneName); - if (boneIndex == -1) throw "Bone not found: " + boneName; - var boneMap = bones[boneName]; - - for (var timelineName in boneMap) { - if (!boneMap.hasOwnProperty(timelineName)) continue; - var values = boneMap[timelineName]; - if (timelineName == "rotate") { - var timeline = new spine.RotateTimeline(values.length); - timeline.boneIndex = boneIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - timeline.setFrame(frameIndex, valueMap["time"], valueMap["angle"]); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 2 - 2]); - - } else if (timelineName == "translate" || timelineName == "scale") { - var timeline; - var timelineScale = 1; - if (timelineName == "scale") - timeline = new spine.ScaleTimeline(values.length); - else { - timeline = new spine.TranslateTimeline(values.length); - timelineScale = this.scale; - } - timeline.boneIndex = boneIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - var x = (valueMap["x"] || 0) * timelineScale; - var y = (valueMap["y"] || 0) * timelineScale; - timeline.setFrame(frameIndex, valueMap["time"], x, y); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - - } else - throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; - } - } - var slots = map["slots"]; - for (var slotName in slots) { - if (!slots.hasOwnProperty(slotName)) continue; - var slotMap = slots[slotName]; - var slotIndex = skeletonData.findSlotIndex(slotName); - - for (var timelineName in slotMap) { - if (!slotMap.hasOwnProperty(timelineName)) continue; - var values = slotMap[timelineName]; - if (timelineName == "color") { - var timeline = new spine.ColorTimeline(values.length); - timeline.slotIndex = slotIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - var color = valueMap["color"]; - var r = spine.SkeletonJson.toColor(color, 0); - var g = spine.SkeletonJson.toColor(color, 1); - var b = spine.SkeletonJson.toColor(color, 2); - var a = spine.SkeletonJson.toColor(color, 3); - timeline.setFrame(frameIndex, valueMap["time"], r, g, b, a); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 5 - 5]); - - } else if (timelineName == "attachment") { - var timeline = new spine.AttachmentTimeline(values.length); - timeline.slotIndex = slotIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); - - } else - throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; - } - } - skeletonData.animations.push(new spine.Animation(name, timelines, duration)); - } -}; -spine.SkeletonJson.readCurve = function (timeline, frameIndex, valueMap) { - var curve = valueMap["curve"]; - if (!curve) return; - if (curve == "stepped") - timeline.curves.setStepped(frameIndex); - else if (curve instanceof Array) - timeline.curves.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); -}; -spine.SkeletonJson.toColor = function (hexString, colorIndex) { - if (hexString.length != 8) throw "Color hexidecimal length must be 8, recieved: " + hexString; - return parseInt(hexString.substring(colorIndex * 2, 2), 16) / 255; -}; - -spine.Atlas = function (atlasText, textureLoader) { - this.textureLoader = textureLoader; - this.pages = []; - this.regions = []; - - var reader = new spine.AtlasReader(atlasText); - var tuple = []; - tuple.length = 4; - var page = null; - while (true) { - var line = reader.readLine(); - if (line == null) break; - line = reader.trim(line); - if (line.length == 0) - page = null; - else if (!page) { - page = new spine.AtlasPage(); - page.name = line; - - page.format = spine.Atlas.Format[reader.readValue()]; - - reader.readTuple(tuple); - page.minFilter = spine.Atlas.TextureFilter[tuple[0]]; - page.magFilter = spine.Atlas.TextureFilter[tuple[1]]; - - var direction = reader.readValue(); - page.uWrap = spine.Atlas.TextureWrap.clampToEdge; - page.vWrap = spine.Atlas.TextureWrap.clampToEdge; - if (direction == "x") - page.uWrap = spine.Atlas.TextureWrap.repeat; - else if (direction == "y") - page.vWrap = spine.Atlas.TextureWrap.repeat; - else if (direction == "xy") - page.uWrap = page.vWrap = spine.Atlas.TextureWrap.repeat; - - textureLoader.load(page, line); - - this.pages.push(page); - - } else { - var region = new spine.AtlasRegion(); - region.name = line; - region.page = page; - - region.rotate = reader.readValue() == "true"; - - reader.readTuple(tuple); - var x = parseInt(tuple[0]); - var y = parseInt(tuple[1]); - - reader.readTuple(tuple); - var width = parseInt(tuple[0]); - var height = parseInt(tuple[1]); - - region.u = x / page.width; - region.v = y / page.height; - if (region.rotate) { - region.u2 = (x + height) / page.width; - region.v2 = (y + width) / page.height; - } else { - region.u2 = (x + width) / page.width; - region.v2 = (y + height) / page.height; - } - region.x = x; - region.y = y; - region.width = Math.abs(width); - region.height = Math.abs(height); - - if (reader.readTuple(tuple) == 4) { // split is optional - region.splits = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; - - if (reader.readTuple(tuple) == 4) { // pad is optional, but only present with splits - region.pads = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; - - reader.readTuple(tuple); - } - } - - region.originalWidth = parseInt(tuple[0]); - region.originalHeight = parseInt(tuple[1]); - - reader.readTuple(tuple); - region.offsetX = parseInt(tuple[0]); - region.offsetY = parseInt(tuple[1]); - - region.index = parseInt(reader.readValue()); - - this.regions.push(region); - } - } -}; -spine.Atlas.prototype = { - findRegion: function (name) { - var regions = this.regions; - for (var i = 0, n = regions.length; i < n; i++) - if (regions[i].name == name) return regions[i]; - return null; - }, - dispose: function () { - var pages = this.pages; - for (var i = 0, n = pages.length; i < n; i++) - this.textureLoader.unload(pages[i].rendererObject); - }, - updateUVs: function (page) { - var regions = this.regions; - for (var i = 0, n = regions.length; i < n; i++) { - var region = regions[i]; - if (region.page != page) continue; - region.u = region.x / page.width; - region.v = region.y / page.height; - if (region.rotate) { - region.u2 = (region.x + region.height) / page.width; - region.v2 = (region.y + region.width) / page.height; - } else { - region.u2 = (region.x + region.width) / page.width; - region.v2 = (region.y + region.height) / page.height; - } - } - } -}; - -spine.Atlas.Format = { - alpha: 0, - intensity: 1, - luminanceAlpha: 2, - rgb565: 3, - rgba4444: 4, - rgb888: 5, - rgba8888: 6 -}; - -spine.Atlas.TextureFilter = { - nearest: 0, - linear: 1, - mipMap: 2, - mipMapNearestNearest: 3, - mipMapLinearNearest: 4, - mipMapNearestLinear: 5, - mipMapLinearLinear: 6 -}; - -spine.Atlas.TextureWrap = { - mirroredRepeat: 0, - clampToEdge: 1, - repeat: 2 -}; - -spine.AtlasPage = function () {}; -spine.AtlasPage.prototype = { - name: null, - format: null, - minFilter: null, - magFilter: null, - uWrap: null, - vWrap: null, - rendererObject: null, - width: 0, - height: 0 -}; - -spine.AtlasRegion = function () {}; -spine.AtlasRegion.prototype = { - page: null, - name: null, - x: 0, y: 0, - width: 0, height: 0, - u: 0, v: 0, u2: 0, v2: 0, - offsetX: 0, offsetY: 0, - originalWidth: 0, originalHeight: 0, - index: 0, - rotate: false, - splits: null, - pads: null, -}; - -spine.AtlasReader = function (text) { - this.lines = text.split(/\r\n|\r|\n/); -}; -spine.AtlasReader.prototype = { - index: 0, - trim: function (value) { - return value.replace(/^\s+|\s+$/g, ""); - }, - readLine: function () { - if (this.index >= this.lines.length) return null; - return this.lines[this.index++]; - }, - readValue: function () { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) throw "Invalid line: " + line; - return this.trim(line.substring(colon + 1)); - }, - /** Returns the number of tuple values read (2 or 4). */ - readTuple: function (tuple) { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) throw "Invalid line: " + line; - var i = 0, lastMatch= colon + 1; - for (; i < 3; i++) { - var comma = line.indexOf(",", lastMatch); - if (comma == -1) { - if (i == 0) throw "Invalid line: " + line; - break; - } - tuple[i] = this.trim(line.substr(lastMatch, comma - lastMatch)); - lastMatch = comma + 1; - } - tuple[i] = this.trim(line.substring(lastMatch)); - return i + 1; - } -} - -spine.AtlasAttachmentLoader = function (atlas) { - this.atlas = atlas; -} -spine.AtlasAttachmentLoader.prototype = { - newAttachment: function (skin, type, name) { - switch (type) { - case spine.AttachmentType.region: - var region = this.atlas.findRegion(name); - if (!region) throw "Region not found in atlas: " + name + " (" + type + ")"; - var attachment = new spine.RegionAttachment(name); - attachment.rendererObject = region; - attachment.setUVs(region.u, region.v, region.u2, region.v2, region.rotate); - attachment.regionOffsetX = region.offsetX; - attachment.regionOffsetY = region.offsetY; - attachment.regionWidth = region.width; - attachment.regionHeight = region.height; - attachment.regionOriginalWidth = region.originalWidth; - attachment.regionOriginalHeight = region.originalHeight; - return attachment; - } - throw "Unknown attachment type: " + type; - } -} - -PIXI.AnimCache = {}; -spine.Bone.yDown = true; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * This object is one that will allow you to specify custom rendering functions based on render type - * - * @class CustomRenderable - * @extends DisplayObject - * @constructor - */ -PIXI.CustomRenderable = function() -{ - PIXI.DisplayObject.call( this ); - -} - -// constructor -PIXI.CustomRenderable.prototype = Object.create( PIXI.DisplayObject.prototype ); -PIXI.CustomRenderable.prototype.constructor = PIXI.CustomRenderable; - -/** - * If this object is being rendered by a CanvasRenderer it will call this callback - * - * @method renderCanvas - * @param renderer {CanvasRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.renderCanvas = function(renderer) -{ - // override! -} - -/** - * If this object is being rendered by a WebGLRenderer it will call this callback to initialize - * - * @method initWebGL - * @param renderer {WebGLRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.initWebGL = function(renderer) -{ - // override! -} - -/** - * If this object is being rendered by a WebGLRenderer it will call this callback - * - * @method renderWebGL - * @param renderer {WebGLRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.renderWebGL = function(renderGroup, projectionMatrix) -{ - // not sure if both needed? but ya have for now! - // override! -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.BaseTextureCache = {}; -PIXI.texturesToUpdate = []; -PIXI.texturesToDestroy = []; - -/** - * A texture stores the information that represents an image. All textures have a base texture - * - * @class BaseTexture - * @uses EventTarget - * @constructor - * @param source {String} the source object (image or canvas) - */ -PIXI.BaseTexture = function(source) -{ - PIXI.EventTarget.call( this ); - - /** - * [read-only] The width of the base texture set when the image has loaded - * - * @property width - * @type Number - * @readOnly - */ - this.width = 100; - - /** - * [read-only] The height of the base texture set when the image has loaded - * - * @property height - * @type Number - * @readOnly - */ - this.height = 100; - - /** - * [read-only] Describes if the base texture has loaded or not - * - * @property hasLoaded - * @type Boolean - * @readOnly - */ - this.hasLoaded = false; - - /** - * The source that is loaded to create the texture - * - * @property source - * @type Image - */ - this.source = source; - - if(!source)return; - - if(this.source instanceof Image || this.source instanceof HTMLImageElement) - { - if(this.source.complete) - { - this.hasLoaded = true; - this.width = this.source.width; - this.height = this.source.height; - - PIXI.texturesToUpdate.push(this); - } - else - { - - var scope = this; - this.source.onload = function(){ - - scope.hasLoaded = true; - scope.width = scope.source.width; - scope.height = scope.source.height; - - // add it to somewhere... - PIXI.texturesToUpdate.push(scope); - scope.dispatchEvent( { type: 'loaded', content: scope } ); - } - // this.image.src = imageUrl; - } - } - else - { - this.hasLoaded = true; - this.width = this.source.width; - this.height = this.source.height; - - PIXI.texturesToUpdate.push(this); - } - - this._powerOf2 = false; -} - -PIXI.BaseTexture.prototype.constructor = PIXI.BaseTexture; - -/** - * Destroys this base texture - * - * @method destroy - */ -PIXI.BaseTexture.prototype.destroy = function() -{ - if(this.source instanceof Image) - { - this.source.src = null; - } - this.source = null; - PIXI.texturesToDestroy.push(this); -} - -/** - * Helper function that returns a base texture based on an image url - * If the image is not in the base texture cache it will be created and loaded - * - * @static - * @method fromImage - * @param imageUrl {String} The image url of the texture - * @return BaseTexture - */ -PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) -{ - var baseTexture = PIXI.BaseTextureCache[imageUrl]; - if(!baseTexture) - { - // new Image() breaks tex loading in some versions of Chrome. - // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); - if (crossorigin) - { - image.crossOrigin = ''; - } - image.src = imageUrl; - baseTexture = new PIXI.BaseTexture(image); - PIXI.BaseTextureCache[imageUrl] = baseTexture; - } - - return baseTexture; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.TextureCache = {}; -PIXI.FrameCache = {}; - -/** - * A texture stores the information that represents an image or part of an image. It cannot be added - * to the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used - * - * @class Texture - * @uses EventTarget - * @constructor - * @param baseTexture {BaseTexture} The base texture source to create the texture from - * @param frame {Rectangle} The rectangle frame of the texture to show - */ -PIXI.Texture = function(baseTexture, frame) -{ - PIXI.EventTarget.call( this ); - - if(!frame) - { - this.noFrame = true; - frame = new PIXI.Rectangle(0,0,1,1); - } - - if(baseTexture instanceof PIXI.Texture) - baseTexture = baseTexture.baseTexture; - - /** - * The base texture of this texture - * - * @property baseTexture - * @type BaseTexture - */ - this.baseTexture = baseTexture; - - /** - * The frame specifies the region of the base texture that this texture uses - * - * @property frame - * @type Rectangle - */ - this.frame = frame; - - /** - * The trim point - * - * @property trim - * @type Point - */ - this.trim = new PIXI.Point(); - - this.scope = this; - - if(baseTexture.hasLoaded) - { - if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); - //console.log(frame) - - this.setFrame(frame); - } - else - { - var scope = this; - baseTexture.addEventListener( 'loaded', function(){ scope.onBaseTextureLoaded()} ); - } -} - -PIXI.Texture.prototype.constructor = PIXI.Texture; - -/** - * Called when the base texture is loaded - * - * @method onBaseTextureLoaded - * @param event - * @private - */ -PIXI.Texture.prototype.onBaseTextureLoaded = function(event) -{ - var baseTexture = this.baseTexture; - baseTexture.removeEventListener( 'loaded', this.onLoaded ); - - if(this.noFrame)this.frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); - this.noFrame = false; - this.width = this.frame.width; - this.height = this.frame.height; - - this.scope.dispatchEvent( { type: 'update', content: this } ); -} - -/** - * Destroys this texture - * - * @method destroy - * @param destroyBase {Boolean} Whether to destroy the base texture as well - */ -PIXI.Texture.prototype.destroy = function(destroyBase) -{ - if(destroyBase)this.baseTexture.destroy(); -} - -/** - * Specifies the rectangle region of the baseTexture - * - * @method setFrame - * @param frame {Rectangle} The frame of the texture to set it to - */ -PIXI.Texture.prototype.setFrame = function(frame) -{ - this.frame = frame; - this.width = frame.width; - this.height = frame.height; - - if(frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height) - { - throw new Error("Texture Error: frame does not fit inside the base Texture dimensions " + this); - } - - this.updateFrame = true; - - PIXI.Texture.frameUpdates.push(this); - //this.dispatchEvent( { type: 'update', content: this } ); -} - -/** - * Helper function that returns a texture based on an image url - * If the image is not in the texture cache it will be created and loaded - * - * @static - * @method fromImage - * @param imageUrl {String} The image url of the texture - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - * @return Texture - */ -PIXI.Texture.fromImage = function(imageUrl, crossorigin) -{ - var texture = PIXI.TextureCache[imageUrl]; - - if(!texture) - { - texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); - PIXI.TextureCache[imageUrl] = texture; - } - - return texture; -} - -/** - * Helper function that returns a texture based on a frame id - * If the frame id is not in the texture cache an error will be thrown - * - * @static - * @method fromFrame - * @param frameId {String} The frame id of the texture - * @return Texture - */ -PIXI.Texture.fromFrame = function(frameId) -{ - var texture = PIXI.TextureCache[frameId]; - if(!texture)throw new Error("The frameId '"+ frameId +"' does not exist in the texture cache " + this); - return texture; -} - -/** - * Helper function that returns a texture based on a canvas element - * If the canvas is not in the texture cache it will be created and loaded - * - * @static - * @method fromCanvas - * @param canvas {Canvas} The canvas element source of the texture - * @return Texture - */ -PIXI.Texture.fromCanvas = function(canvas) -{ - var baseTexture = new PIXI.BaseTexture(canvas); - return new PIXI.Texture(baseTexture); -} - - -/** - * Adds a texture to the textureCache. - * - * @static - * @method addTextureToCache - * @param texture {Texture} - * @param id {String} the id that the texture will be stored against. - */ -PIXI.Texture.addTextureToCache = function(texture, id) -{ - PIXI.TextureCache[id] = texture; -} - -/** - * Remove a texture from the textureCache. - * - * @static - * @method removeTextureFromCache - * @param id {String} the id of the texture to be removed - * @return {Texture} the texture that was removed - */ -PIXI.Texture.removeTextureFromCache = function(id) -{ - var texture = PIXI.TextureCache[id] - PIXI.TextureCache[id] = null; - return texture; -} - -// this is more for webGL.. it contains updated frames.. -PIXI.Texture.frameUpdates = []; - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - A RenderTexture is a special texture that allows any pixi displayObject to be rendered to it. - - __Hint__: All DisplayObjects (exmpl. Sprites) that renders on RenderTexture should be preloaded. - Otherwise black rectangles will be drawn instead. - - RenderTexture takes snapshot of DisplayObject passed to render method. If DisplayObject is passed to render method, position and rotation of it will be ignored. For example: - - var renderTexture = new PIXI.RenderTexture(800, 600); - var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - sprite.position.x = 800/2; - sprite.position.y = 600/2; - sprite.anchor.x = 0.5; - sprite.anchor.y = 0.5; - renderTexture.render(sprite); - - Sprite in this case will be rendered to 0,0 position. To render this sprite at center DisplayObjectContainer should be used: - - var doc = new PIXI.DisplayObjectContainer(); - doc.addChild(sprite); - renderTexture.render(doc); // Renders to center of renderTexture - - @class RenderTexture - @extends Texture - @constructor - @param width {Number} The width of the render texture - @param height {Number} The height of the render texture - */ -PIXI.RenderTexture = function(width, height) -{ - PIXI.EventTarget.call( this ); - - this.width = width || 100; - this.height = height || 100; - - this.indetityMatrix = PIXI.mat3.create(); - - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); - - if(PIXI.gl) - { - this.initWebGL(); - } - else - { - this.initCanvas(); - } -} - -PIXI.RenderTexture.prototype = Object.create( PIXI.Texture.prototype ); -PIXI.RenderTexture.prototype.constructor = PIXI.RenderTexture; - -/** - * Initializes the webgl data for this texture - * - * @method initWebGL - * @private - */ -PIXI.RenderTexture.prototype.initWebGL = function() -{ - var gl = PIXI.gl; - this.glFramebuffer = gl.createFramebuffer(); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - - this.glFramebuffer.width = this.width; - this.glFramebuffer.height = this.height; - - this.baseTexture = new PIXI.BaseTexture(); - - this.baseTexture.width = this.width; - this.baseTexture.height = this.height; - - this.baseTexture._glTexture = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - - this.baseTexture.isRender = true; - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.baseTexture._glTexture, 0); - - // create a projection matrix.. - this.projection = new PIXI.Point(this.width/2 , this.height/2); - - // set the correct render function.. - this.render = this.renderWebGL; - - -} - - -PIXI.RenderTexture.prototype.resize = function(width, height) -{ - - this.width = width; - this.height = height; - - if(PIXI.gl) - { - this.projection.x = this.width/2 - this.projection.y = this.height/2; - - var gl = PIXI.gl; - gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - } - else - { - - this.frame.width = this.width - this.frame.height = this.height; - this.renderer.resize(this.width, this.height); - } -} - -/** - * Initializes the canvas data for this texture - * - * @method initCanvas - * @private - */ -PIXI.RenderTexture.prototype.initCanvas = function() -{ - this.renderer = new PIXI.CanvasRenderer(this.width, this.height, null, 0); - - this.baseTexture = new PIXI.BaseTexture(this.renderer.view); - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); - - this.render = this.renderCanvas; -} - -/** - * This function will draw the display object to the texture. - * - * @method renderWebGL - * @param displayObject {DisplayObject} The display object to render this texture on - * @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn - * @private - */ -PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, clear) -{ - var gl = PIXI.gl; - - // enable the alpha color mask.. - gl.colorMask(true, true, true, true); - - gl.viewport(0, 0, this.width, this.height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - - if(clear) - { - gl.clearColor(0,0,0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - } - - // THIS WILL MESS WITH HIT TESTING! - var children = displayObject.children; - - //TODO -? create a new one??? dont think so! - var originalWorldTransform = displayObject.worldTransform; - displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; - // modify to flip... - displayObject.worldTransform[4] = -1; - displayObject.worldTransform[5] = this.projection.y * 2; - - - if(position) - { - displayObject.worldTransform[2] = position.x; - displayObject.worldTransform[5] -= position.y; - } - - PIXI.visibleCount++; - displayObject.vcount = PIXI.visibleCount; - - for(var i=0,j=children.length; i} assetURLs an array of image/sprite sheet urls that you would like loaded - * supported. Supported image formats include "jpeg", "jpg", "png", "gif". Supported - * sprite sheet data formats only include "JSON" at this time. Supported bitmap font - * data formats include "xml" and "fnt". - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.AssetLoader = function(assetURLs, crossorigin) -{ - PIXI.EventTarget.call(this); - - /** - * The array of asset URLs that are going to be loaded - * - * @property assetURLs - * @type Array - */ - this.assetURLs = assetURLs; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * Maps file extension to loader types - * - * @property loadersByType - * @type Object - */ - this.loadersByType = { - "jpg": PIXI.ImageLoader, - "jpeg": PIXI.ImageLoader, - "png": PIXI.ImageLoader, - "gif": PIXI.ImageLoader, - "json": PIXI.JsonLoader, - "anim": PIXI.SpineLoader, - "xml": PIXI.BitmapFontLoader, - "fnt": PIXI.BitmapFontLoader - }; - - -}; - -/** - * Fired when an item has loaded - * @event onProgress - */ - -/** - * Fired when all the assets have loaded - * @event onComplete - */ - -// constructor -PIXI.AssetLoader.prototype.constructor = PIXI.AssetLoader; - -/** - * Starts loading the assets sequentially - * - * @method load - */ -PIXI.AssetLoader.prototype.load = function() -{ - var scope = this; - - this.loadCount = this.assetURLs.length; - - for (var i=0; i < this.assetURLs.length; i++) - { - var fileName = this.assetURLs[i]; - var fileType = fileName.split(".").pop().toLowerCase(); - - var loaderClass = this.loadersByType[fileType]; - if(!loaderClass) - throw new Error(fileType + " is an unsupported file type"); - - var loader = new loaderClass(fileName, this.crossorigin); - - loader.addEventListener("loaded", function() - { - scope.onAssetLoaded(); - }); - loader.load(); - } -}; - -/** - * Invoked after each file is loaded - * - * @method onAssetLoaded - * @private - */ -PIXI.AssetLoader.prototype.onAssetLoaded = function() -{ - this.loadCount--; - this.dispatchEvent({type: "onProgress", content: this}); - if(this.onProgress) this.onProgress(); - - if(this.loadCount == 0) - { - this.dispatchEvent({type: "onComplete", content: this}); - if(this.onComplete) this.onComplete(); - } -}; - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The json file loader is used to load in JSON data and parsing it - * When loaded this class will dispatch a "loaded" event - * If load failed this class will dispatch a "error" event - * - * @class JsonLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the JSON file - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.JsonLoader = function (url, crossorigin) { - PIXI.EventTarget.call(this); - - /** - * The url of the bitmap font data - * - * @property url - * @type String - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * [read-only] The base url of the bitmap font data - * - * @property baseUrl - * @type String - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ""); - - /** - * [read-only] Whether the data has loaded yet - * - * @property loaded - * @type Boolean - * @readOnly - */ - this.loaded = false; - -}; - -// constructor -PIXI.JsonLoader.prototype.constructor = PIXI.JsonLoader; - -/** - * Loads the JSON data - * - * @method load - */ -PIXI.JsonLoader.prototype.load = function () { - this.ajaxRequest = new AjaxRequest(); - var scope = this; - this.ajaxRequest.onreadystatechange = function () { - scope.onJSONLoaded(); - }; - - this.ajaxRequest.open("GET", this.url, true); - if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/json"); - this.ajaxRequest.send(null); -}; - -/** - * Invoke when JSON file is loaded - * - * @method onJSONLoaded - * @private - */ -PIXI.JsonLoader.prototype.onJSONLoaded = function () { - if (this.ajaxRequest.readyState == 4) { - if (this.ajaxRequest.status == 200 || window.location.href.indexOf("http") == -1) { - this.json = JSON.parse(this.ajaxRequest.responseText); - - if(this.json.frames) - { - // sprite sheet - var scope = this; - var textureUrl = this.baseUrl + this.json.meta.image; - var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); - var frameData = this.json.frames; - - this.texture = image.texture.baseTexture; - image.addEventListener("loaded", function (event) { - scope.onLoaded(); - }); - - for (var i in frameData) { - var rect = frameData[i].frame; - if (rect) { - PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) { - //var realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) - // calculate the offset! - } - } - } - - image.load(); - - } - else if(this.json.bones) - { - // spine animation - var spineJsonParser = new spine.SkeletonJson(); - var skeletonData = spineJsonParser.readSkeletonData(this.json); - PIXI.AnimCache[this.url] = skeletonData; - this.onLoaded(); - } - else - { - this.onLoaded(); - } - } - else - { - this.onError(); - } - } -}; - -/** - * Invoke when json file loaded - * - * @method onLoaded - * @private - */ -PIXI.JsonLoader.prototype.onLoaded = function () { - this.loaded = true; - this.dispatchEvent({ - type: "loaded", - content: this - }); -}; - -/** - * Invoke when error occured - * - * @method onError - * @private - */ -PIXI.JsonLoader.prototype.onError = function () { - this.dispatchEvent({ - type: "error", - content: this - }); -}; -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The sprite sheet loader is used to load in JSON sprite sheet data - * To generate the data you can use http://www.codeandweb.com/texturepacker and publish the "JSON" format - * There is a free version so thats nice, although the paid version is great value for money. - * It is highly recommended to use Sprite sheets (also know as texture atlas") as it means sprite"s can be batched and drawn together for highly increased rendering speed. - * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() - * This loader will also load the image file that the Spritesheet points to as well as the data. - * When loaded this class will dispatch a "loaded" event - * - * @class SpriteSheetLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the sprite sheet JSON file - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ - -PIXI.SpriteSheetLoader = function (url, crossorigin) { - /* - * i use texture packer to load the assets.. - * http://www.codeandweb.com/texturepacker - * make sure to set the format as "JSON" - */ - PIXI.EventTarget.call(this); - - /** - * The url of the bitmap font data - * - * @property url - * @type String - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * [read-only] The base url of the bitmap font data - * - * @property baseUrl - * @type String - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ""); - - /** - * The texture being loaded - * - * @property texture - * @type Texture - */ - this.texture = null; - - /** - * The frames of the sprite sheet - * - * @property frames - * @type Object - */ - this.frames = {}; -}; - -// constructor -PIXI.SpriteSheetLoader.prototype.constructor = PIXI.SpriteSheetLoader; - -/** - * This will begin loading the JSON file - * - * @method load - */ -PIXI.SpriteSheetLoader.prototype.load = function () { - var scope = this; - var jsonLoader = new PIXI.JsonLoader(this.url, this.crossorigin); - jsonLoader.addEventListener("loaded", function (event) { - scope.json = event.content.json; - scope.onJSONLoaded(); - }); - jsonLoader.load(); -}; - -/** - * Invoke when JSON file is loaded - * - * @method onJSONLoaded - * @private - */ -PIXI.SpriteSheetLoader.prototype.onJSONLoaded = function () { - var scope = this; - var textureUrl = this.baseUrl + this.json.meta.image; - var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); - var frameData = this.json.frames; - - this.texture = image.texture.baseTexture; - image.addEventListener("loaded", function (event) { - scope.onLoaded(); - }); - - for (var i in frameData) { - var rect = frameData[i].frame; - if (rect) { - PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) { - //var realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) - // calculate the offset! - } - } - } - - image.load(); -}; -/** - * Invoke when all files are loaded (json and texture) - * - * @method onLoaded - * @private - */ -PIXI.SpriteSheetLoader.prototype.onLoaded = function () { - this.dispatchEvent({ - type: "loaded", - content: this - }); -}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The image loader class is responsible for loading images file formats ("jpeg", "jpg", "png" and "gif") - * Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() - * When loaded this class will dispatch a 'loaded' event - * - * @class ImageLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the image - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.ImageLoader = function(url, crossorigin) -{ - PIXI.EventTarget.call(this); - - /** - * The texture being loaded - * - * @property texture - * @type Texture - */ - this.texture = PIXI.Texture.fromImage(url, crossorigin); - - /** - * if the image is loaded with loadFramedSpriteSheet - * frames will contain the sprite sheet frames - * - */ - this.frames = []; -}; - -// constructor -PIXI.ImageLoader.prototype.constructor = PIXI.ImageLoader; - -/** - * Loads image or takes it from cache - * - * @method load - */ -PIXI.ImageLoader.prototype.load = function() -{ - if(!this.texture.baseTexture.hasLoaded) - { - var scope = this; - this.texture.baseTexture.addEventListener("loaded", function() - { - scope.onLoaded(); - }); - } - else - { - this.onLoaded(); - } -}; - -/** - * Invoked when image file is loaded or it is already cached and ready to use - * - * @method onLoaded - * @private - */ -PIXI.ImageLoader.prototype.onLoaded = function() -{ - this.dispatchEvent({type: "loaded", content: this}); -}; - -/** - * Loads image and split it to uniform sized frames - * - * - * @method loadFramedSpriteSheet - * @param frameWidth {Number} with of each frame - * @param frameHeight {Number} height of each frame - * @param textureName {String} if given, the frames will be cached in - format - */ -PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) -{ - this.frames = []; - var cols = Math.floor(this.texture.width / frameWidth); - var rows = Math.floor(this.texture.height / frameHeight); - - var i=0; - for (var y=0; y - + + + + diff --git a/examples/example 12 - Spine/index_goblins.html b/examples/example 12 - Spine/index_goblins.html index 550187d..4010633 100644 --- a/examples/example 12 - Spine/index_goblins.html +++ b/examples/example 12 - Spine/index_goblins.html @@ -11,7 +11,7 @@ - + + + diff --git a/examples/example 13 - Graphics/pixi.js b/examples/example 13 - Graphics/pixi.js deleted file mode 100644 index 6d567a2..0000000 --- a/examples/example 13 - Graphics/pixi.js +++ /dev/null @@ -1,10649 +0,0 @@ -/** - * @license - * Pixi.JS - v1.3.0 - * Copyright (c) 2012, Mat Groves - * http://goodboydigital.com/ - * - * Compiled: 2013-09-30 - * - * Pixi.JS is licensed under the MIT License. - * http://www.opensource.org/licenses/mit-license.php - */ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -(function(){ - - var root = this; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * @module PIXI - */ -var PIXI = PIXI || {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The Point object represents a location in a two-dimensional coordinate system, where x represents the horizontal axis and y represents the vertical axis. - * - * @class Point - * @constructor - * @param x {Number} position of the point - * @param y {Number} position of the point - */ -PIXI.Point = function(x, y) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; -} - -/** - * Creates a clone of this point - * - * @method clone - * @return {Point} a copy of the point - */ -PIXI.Point.prototype.clone = function() -{ - return new PIXI.Point(this.x, this.y); -} - -// constructor -PIXI.Point.prototype.constructor = PIXI.Point; - - -/** - * @author Mat Groves http://matgroves.com/ - */ - -/** - * the Rectangle object is an area defined by its position, as indicated by its top-left corner point (x, y) and by its width and its height. - * - * @class Rectangle - * @constructor - * @param x {Number} The X coord of the upper-left corner of the rectangle - * @param y {Number} The Y coord of the upper-left corner of the rectangle - * @param width {Number} The overall width of this rectangle - * @param height {Number} The overall height of this rectangle - */ -PIXI.Rectangle = function(x, y, width, height) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property width - * @type Number - * @default 0 - */ - this.width = width || 0; - - /** - * @property height - * @type Number - * @default 0 - */ - this.height = height || 0; -} - -/** - * Creates a clone of this Rectangle - * - * @method clone - * @return {Rectangle} a copy of the rectangle - */ -PIXI.Rectangle.prototype.clone = function() -{ - return new PIXI.Rectangle(this.x, this.y, this.width, this.height); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this Rectangle - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this Rectangle - */ -PIXI.Rectangle.prototype.contains = function(x, y) -{ - if(this.width <= 0 || this.height <= 0) - return false; - - var x1 = this.x; - if(x >= x1 && x <= x1 + this.width) - { - var y1 = this.y; - - if(y >= y1 && y <= y1 + this.height) - { - return true; - } - } - - return false; -} - -// constructor -PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; - - -/** - * @author Adrien Brault - */ - -/** - * @class Polygon - * @constructor - * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, - * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be - * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the - * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are - * Numbers. - */ -PIXI.Polygon = function(points) -{ - //if points isn't an array, use arguments as the array - if(!(points instanceof Array)) - points = Array.prototype.slice.call(arguments); - - //if this is a flat array of numbers, convert it to points - if(typeof points[0] === 'number') { - var p = []; - for(var i = 0, il = points.length; i < il; i+=2) { - p.push( - new PIXI.Point(points[i], points[i + 1]) - ); - } - - points = p; - } - - this.points = points; -} - -/** - * Creates a clone of this polygon - * - * @method clone - * @return {Polygon} a copy of the polygon - */ -PIXI.Polygon.prototype.clone = function() -{ - var points = []; - for (var i=0; i y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); - - if(intersect) inside = !inside; - } - - return inside; -} - -// constructor -PIXI.Polygon.prototype.constructor = PIXI.Polygon; - -/** - * @author Chad Engler - */ - -/** - * The Circle object can be used to specify a hit area for displayobjects - * - * @class Circle - * @constructor - * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle - * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle - * @param radius {Number} The radius of the circle - */ -PIXI.Circle = function(x, y, radius) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property radius - * @type Number - * @default 0 - */ - this.radius = radius || 0; -} - -/** - * Creates a clone of this Circle instance - * - * @method clone - * @return {Circle} a copy of the polygon - */ -PIXI.Circle.prototype.clone = function() -{ - return new PIXI.Circle(this.x, this.y, this.radius); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this circle - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this polygon - */ -PIXI.Circle.prototype.contains = function(x, y) -{ - if(this.radius <= 0) - return false; - - var dx = (this.x - x), - dy = (this.y - y), - r2 = this.radius * this.radius; - - dx *= dx; - dy *= dy; - - return (dx + dy <= r2); -} - -// constructor -PIXI.Circle.prototype.constructor = PIXI.Circle; - - -/** - * @author Chad Engler - */ - -/** - * The Ellipse object can be used to specify a hit area for displayobjects - * - * @class Ellipse - * @constructor - * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse - * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse - * @param width {Number} The overall width of this ellipse - * @param height {Number} The overall height of this ellipse - */ -PIXI.Ellipse = function(x, y, width, height) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property width - * @type Number - * @default 0 - */ - this.width = width || 0; - - /** - * @property height - * @type Number - * @default 0 - */ - this.height = height || 0; -} - -/** - * Creates a clone of this Ellipse instance - * - * @method clone - * @return {Ellipse} a copy of the ellipse - */ -PIXI.Ellipse.prototype.clone = function() -{ - return new PIXI.Ellipse(this.x, this.y, this.width, this.height); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this ellipse - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this ellipse - */ -PIXI.Ellipse.prototype.contains = function(x, y) -{ - if(this.width <= 0 || this.height <= 0) - return false; - - //normalize the coords to an ellipse with center 0,0 - //and a radius of 0.5 - var normx = ((x - this.x) / this.width) - 0.5, - normy = ((y - this.y) / this.height) - 0.5; - - normx *= normx; - normy *= normy; - - return (normx + normy < 0.25); -} - -PIXI.Ellipse.getBounds = function() -{ - return new PIXI.Rectangle(this.x, this.y, this.width, this.height); -} - -// constructor -PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; - - - -/* - * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV - * you both rock! - */ - -function determineMatrixArrayType() { - PIXI.Matrix = (typeof Float32Array !== 'undefined') ? Float32Array : Array; - return PIXI.Matrix; -} - -determineMatrixArrayType(); - -PIXI.mat3 = {}; - -PIXI.mat3.create = function() -{ - var matrix = new PIXI.Matrix(9); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 1; - matrix[5] = 0; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 1; - - return matrix; -} - - -PIXI.mat3.identity = function(matrix) -{ - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 1; - matrix[5] = 0; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 1; - - return matrix; -} - - -PIXI.mat4 = {}; - -PIXI.mat4.create = function() -{ - var matrix = new PIXI.Matrix(16); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 0; - matrix[5] = 1; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = 1; - matrix[11] = 0; - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; - - return matrix; -} - -PIXI.mat3.multiply = function (mat, mat2, dest) -{ - if (!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[0], a01 = mat[1], a02 = mat[2], - a10 = mat[3], a11 = mat[4], a12 = mat[5], - a20 = mat[6], a21 = mat[7], a22 = mat[8], - - b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], - b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], - b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; - - dest[0] = b00 * a00 + b01 * a10 + b02 * a20; - dest[1] = b00 * a01 + b01 * a11 + b02 * a21; - dest[2] = b00 * a02 + b01 * a12 + b02 * a22; - - dest[3] = b10 * a00 + b11 * a10 + b12 * a20; - dest[4] = b10 * a01 + b11 * a11 + b12 * a21; - dest[5] = b10 * a02 + b11 * a12 + b12 * a22; - - dest[6] = b20 * a00 + b21 * a10 + b22 * a20; - dest[7] = b20 * a01 + b21 * a11 + b22 * a21; - dest[8] = b20 * a02 + b21 * a12 + b22 * a22; - - return dest; -} - -PIXI.mat3.clone = function(mat) -{ - var matrix = new PIXI.Matrix(9); - - matrix[0] = mat[0]; - matrix[1] = mat[1]; - matrix[2] = mat[2]; - matrix[3] = mat[3]; - matrix[4] = mat[4]; - matrix[5] = mat[5]; - matrix[6] = mat[6]; - matrix[7] = mat[7]; - matrix[8] = mat[8]; - - return matrix; -} - -PIXI.mat3.transpose = function (mat, dest) -{ - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) { - var a01 = mat[1], a02 = mat[2], - a12 = mat[5]; - - mat[1] = mat[3]; - mat[2] = mat[6]; - mat[3] = a01; - mat[5] = mat[7]; - mat[6] = a02; - mat[7] = a12; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[3]; - dest[2] = mat[6]; - dest[3] = mat[1]; - dest[4] = mat[4]; - dest[5] = mat[7]; - dest[6] = mat[2]; - dest[7] = mat[5]; - dest[8] = mat[8]; - return dest; -} - -PIXI.mat3.toMat4 = function (mat, dest) -{ - if (!dest) { dest = PIXI.mat4.create(); } - - dest[15] = 1; - dest[14] = 0; - dest[13] = 0; - dest[12] = 0; - - dest[11] = 0; - dest[10] = mat[8]; - dest[9] = mat[7]; - dest[8] = mat[6]; - - dest[7] = 0; - dest[6] = mat[5]; - dest[5] = mat[4]; - dest[4] = mat[3]; - - dest[3] = 0; - dest[2] = mat[2]; - dest[1] = mat[1]; - dest[0] = mat[0]; - - return dest; -} - - -///// - - -PIXI.mat4.create = function() -{ - var matrix = new PIXI.Matrix(16); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 0; - matrix[5] = 1; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = 1; - matrix[11] = 0; - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; - - return matrix; -} - -PIXI.mat4.transpose = function (mat, dest) -{ - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) - { - var a01 = mat[1], a02 = mat[2], a03 = mat[3], - a12 = mat[6], a13 = mat[7], - a23 = mat[11]; - - mat[1] = mat[4]; - mat[2] = mat[8]; - mat[3] = mat[12]; - mat[4] = a01; - mat[6] = mat[9]; - mat[7] = mat[13]; - mat[8] = a02; - mat[9] = a12; - mat[11] = mat[14]; - mat[12] = a03; - mat[13] = a13; - mat[14] = a23; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[4]; - dest[2] = mat[8]; - dest[3] = mat[12]; - dest[4] = mat[1]; - dest[5] = mat[5]; - dest[6] = mat[9]; - dest[7] = mat[13]; - dest[8] = mat[2]; - dest[9] = mat[6]; - dest[10] = mat[10]; - dest[11] = mat[14]; - dest[12] = mat[3]; - dest[13] = mat[7]; - dest[14] = mat[11]; - dest[15] = mat[15]; - return dest; -} - -PIXI.mat4.multiply = function (mat, mat2, dest) -{ - if (!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; - var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; - var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; - var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - - // Cache only the current line of the second matrix - var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; - dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[4]; - b1 = mat2[5]; - b2 = mat2[6]; - b3 = mat2[7]; - dest[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[8]; - b1 = mat2[9]; - b2 = mat2[10]; - b3 = mat2[11]; - dest[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[12]; - b1 = mat2[13]; - b2 = mat2[14]; - b3 = mat2[15]; - dest[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - return dest; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The base class for all objects that are rendered on the screen. - * - * @class DisplayObject - * @constructor - */ -PIXI.DisplayObject = function() -{ - this.last = this; - this.first = this; - /** - * The coordinate of the object relative to the local coordinates of the parent. - * - * @property position - * @type Point - */ - this.position = new PIXI.Point(); - - /** - * The scale factor of the object. - * - * @property scale - * @type Point - */ - this.scale = new PIXI.Point(1,1);//{x:1, y:1}; - - /** - * The pivot point of the displayObject that it rotates around - * - * @property pivot - * @type Point - */ - this.pivot = new PIXI.Point(0,0); - - /** - * The rotation of the object in radians. - * - * @property rotation - * @type Number - */ - this.rotation = 0; - - /** - * The opacity of the object. - * - * @property alpha - * @type Number - */ - this.alpha = 1; - - /** - * The visibility of the object. - * - * @property visible - * @type Boolean - */ - this.visible = true; - - /** - * This is the defined area that will pick up mouse / touch events. It is null by default. - * Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children) - * - * @property hitArea - * @type Rectangle|Circle|Ellipse|Polygon - */ - this.hitArea = null; - - /** - * This is used to indicate if the displayObject should display a mouse hand cursor on rollover - * - * @property buttonMode - * @type Boolean - */ - this.buttonMode = false; - - /** - * Can this object be rendered - * - * @property renderable - * @type Boolean - */ - this.renderable = false; - - /** - * [read-only] The display object container that contains this display object. - * - * @property parent - * @type DisplayObjectContainer - * @readOnly - */ - this.parent = null; - - /** - * [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage. - * - * @property stage - * @type Stage - * @readOnly - */ - this.stage = null; - - /** - * [read-only] The multiplied alpha of the displayobject - * - * @property worldAlpha - * @type Number - * @readOnly - */ - this.worldAlpha = 1; - - /** - * [read-only] Whether or not the object is interactive, do not toggle directly! use the `interactive` property - * - * @property _interactive - * @type Boolean - * @readOnly - * @private - */ - this._interactive = false; - - /** - * [read-only] Current transform of the object based on world (parent) factors - * - * @property worldTransform - * @type Mat3 - * @readOnly - * @private - */ - this.worldTransform = PIXI.mat3.create()//mat3.identity(); - - /** - * [read-only] Current transform of the object locally - * - * @property localTransform - * @type Mat3 - * @readOnly - * @private - */ - this.localTransform = PIXI.mat3.create()//mat3.identity(); - - /** - * [NYI] Unkown - * - * @property color - * @type Array<> - * @private - */ - this.color = []; - - /** - * [NYI] Holds whether or not this object is dynamic, for rendering optimization - * - * @property dynamic - * @type Boolean - * @private - */ - this.dynamic = true; - - // chach that puppy! - this._sr = 0; - this._cr = 1; - - /* - * MOUSE Callbacks - */ - - /** - * A callback that is used when the users clicks on the displayObject with their mouse - * @method click - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user clicks the mouse down over the sprite - * @method mousedown - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject - * for this callback to be fired the mouse must have been pressed down over the displayObject - * @method mouseup - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject - * for this callback to be fired, The touch must have started over the displayObject - * @method mouseupoutside - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the users mouse rolls over the displayObject - * @method mouseover - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the users mouse leaves the displayObject - * @method mouseout - * @param interactionData {InteractionData} - */ - - - /* - * TOUCH Callbacks - */ - - /** - * A callback that is used when the users taps on the sprite with their finger - * basically a touch version of click - * @method tap - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user touch's over the displayObject - * @method touchstart - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases a touch over the displayObject - * @method touchend - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the touch that was over the displayObject - * for this callback to be fired, The touch must have started over the sprite - * @method touchendoutside - * @param interactionData {InteractionData} - */ -} - -// constructor -PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; - -/** - * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default - * Instead of using this function you can now simply set the interactive property to true or false - * - * @method setInteractive - * @param interactive {Boolean} - * @deprecated Simply set the `interactive` property directly - */ -PIXI.DisplayObject.prototype.setInteractive = function(interactive) -{ - this.interactive = interactive; -} - -/** - * Indicates if the sprite will have touch and mouse interactivity. It is false by default - * - * @property interactive - * @type Boolean - * @default false - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'interactive', { - get: function() { - return this._interactive; - }, - set: function(value) { - this._interactive = value; - - // TODO more to be done here.. - // need to sort out a re-crawl! - if(this.stage)this.stage.dirty = true; - } -}); - -/** - * Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. - * In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. - * To remove a mask, set this property to null. - * - * @property mask - * @type Graphics - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { - get: function() { - return this._mask; - }, - set: function(value) { - - - if(value) - { - if(this._mask) - { - value.start = this._mask.start; - value.end = this._mask.end; - } - else - { - this.addFilter(value); - value.renderable = false; - } - } - else - { - this.removeFilter(this._mask); - this._mask.renderable = true; - } - - this._mask = value; - } -}); - -/** - * Sets the filters for the displayObject. Currently there's a few limitations. - * 1: At the moment only one filter can be applied at a time.. - * 2: They cannot be nested. - * 3: There's no padding yet. - * 4: this is a webGL only feature. - * @property filters - * @type Array - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { - get: function() { - return this._filters; - }, - set: function(value) { - - //if(value == ) - if(value) - { - if(this._filters)this.removeFilter(this._filters); - this.addFilter(value) - } - else - { - if(this._filters)this.removeFilter(this._filters); - } - - this._filters = value; - } -}); - -/* - * Adds a filter to this displayObject - * - * @method addFilter - * @param mask {Graphics} the graphics object to use as a filter - * @private - */ -PIXI.DisplayObject.prototype.addFilter = function(data) -{ - //if(this.filter)return; - //this.filter = true; - - // insert a filter block.. - // TODO Onject pool thease bad boys.. - var start = new PIXI.FilterBlock(); - var end = new PIXI.FilterBlock(); - - data.start = start; - data.end = end; - - start.data = data; - end.data = data; - - start.first = start.last = this; - end.first = end.last = this; - - start.open = true; - - /* - * insert start - */ - - var childFirst = start - var childLast = start - var nextObject; - var previousObject; - - previousObject = this.first._iPrev; - - if(previousObject) - { - nextObject = previousObject._iNext; - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - } - else - { - nextObject = this; - } - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - - // now insert the end filter block.. - - /* - * insert end filter - */ - var childFirst = end - var childLast = end - var nextObject = null; - var previousObject = null; - - previousObject = this.last; - nextObject = previousObject._iNext; - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - var updateLast = this; - - var prevLast = this.last; - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = end; - } - updateLast = updateLast.parent; - } - - this.first = start; - - // if webGL... - if(this.__renderGroup) - { - this.__renderGroup.addFilterBlocks(start, end); - } - -} - -/* - * Removes the filter to this displayObject - * - * @method removeFilter - * @private - */ -PIXI.DisplayObject.prototype.removeFilter = function(data) -{ - //if(!this.filter)return; - //this.filter = false; - console.log("YUOIO") - // modify the list.. - var startBlock = data.start; - - - var nextObject = startBlock._iNext; - var previousObject = startBlock._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - if(previousObject)previousObject._iNext = nextObject; - - this.first = startBlock._iNext; - - // remove the end filter - var lastBlock = data.end; - - var nextObject = lastBlock._iNext; - var previousObject = lastBlock._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - - // this is always true too! - var tempLast = lastBlock._iPrev; - // need to make sure the parents last is updated too - var updateLast = this; - while(updateLast.last == lastBlock) - { - updateLast.last = tempLast; - updateLast = updateLast.parent; - if(!updateLast)break; - } - - // if webGL... - if(this.__renderGroup) - { - this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); - } -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.DisplayObject.prototype.updateTransform = function() -{ - // TODO OPTIMIZE THIS!! with dirty - if(this.rotation !== this.rotationCache) - { - this.rotationCache = this.rotation; - this._sr = Math.sin(this.rotation); - this._cr = Math.cos(this.rotation); - } - - var localTransform = this.localTransform; - var parentTransform = this.parent.worldTransform; - var worldTransform = this.worldTransform; - //console.log(localTransform) - localTransform[0] = this._cr * this.scale.x; - localTransform[1] = -this._sr * this.scale.y - localTransform[3] = this._sr * this.scale.x; - localTransform[4] = this._cr * this.scale.y; - - // TODO --> do we even need a local matrix??? - - var px = this.pivot.x; - var py = this.pivot.y; - - // Cache the matrix values (makes for huge speed increases!) - var a00 = localTransform[0], a01 = localTransform[1], a02 = this.position.x - localTransform[0] * px - py * localTransform[1], - a10 = localTransform[3], a11 = localTransform[4], a12 = this.position.y - localTransform[4] * py - px * localTransform[3], - - b00 = parentTransform[0], b01 = parentTransform[1], b02 = parentTransform[2], - b10 = parentTransform[3], b11 = parentTransform[4], b12 = parentTransform[5]; - - localTransform[2] = a02 - localTransform[5] = a12 - - worldTransform[0] = b00 * a00 + b01 * a10; - worldTransform[1] = b00 * a01 + b01 * a11; - worldTransform[2] = b00 * a02 + b01 * a12 + b02; - - worldTransform[3] = b10 * a00 + b11 * a10; - worldTransform[4] = b10 * a01 + b11 * a11; - worldTransform[5] = b10 * a02 + b11 * a12 + b12; - - // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! - // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); - this.worldAlpha = this.alpha * this.parent.worldAlpha; - - this.vcount = PIXI.visibleCount; - -} - -PIXI.visibleCount = 0; -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * A DisplayObjectContainer represents a collection of display objects. - * It is the base class of all display objects that act as a container for other objects. - * - * @class DisplayObjectContainer - * @extends DisplayObject - * @constructor - */ -PIXI.DisplayObjectContainer = function() -{ - PIXI.DisplayObject.call( this ); - - /** - * [read-only] The of children of this container. - * - * @property children - * @type Array - * @readOnly - */ - this.children = []; -} - -// constructor -PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); -PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; - -/** - * Adds a child to the container. - * - * @method addChild - * @param child {DisplayObject} The DisplayObject to add to the container - */ -PIXI.DisplayObjectContainer.prototype.addChild = function(child) -{ - if(child.parent != undefined) - { - - //// COULD BE THIS??? - child.parent.removeChild(child); - // return; - } - - child.parent = this; - - this.children.push(child); - - // update the stage refference.. - - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = this.stage; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // LINKED LIST // - - // modify the list.. - var childFirst = child.first - var childLast = child.last; - var nextObject; - var previousObject; - - // this could be wrong if there is a filter?? - if(this._filters) - { - previousObject = this.last._iPrev; - } - else - { - previousObject = this.last; - } - - nextObject = previousObject._iNext; - - // always true in this case - // need to make sure the parents last is updated too - var updateLast = this; - var prevLast = previousObject; - - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = child.last; - } - updateLast = updateLast.parent; - } - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - // need to remove any render groups.. - if(this.__renderGroup) - { - // being used by a renderTexture.. if it exists then it must be from a render texture; - if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); - // add them to the new render group.. - this.__renderGroup.addDisplayObjectAndChildren(child); - } - -} - -/** - * Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown - * - * @method addChildAt - * @param child {DisplayObject} The child to add - * @param index {Number} The index to place the child in - */ -PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) -{ - if(index >= 0 && index <= this.children.length) - { - if(child.parent != undefined) - { - child.parent.removeChild(child); - } - child.parent = this; - - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = this.stage; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // modify the list.. - var childFirst = child.first; - var childLast = child.last; - var nextObject; - var previousObject; - - if(index == this.children.length) - { - previousObject = this.last; - var updateLast = this; - var prevLast = this.last; - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = child.last; - } - updateLast = updateLast.parent; - } - } - else if(index == 0) - { - previousObject = this; - } - else - { - previousObject = this.children[index-1].last; - } - - nextObject = previousObject._iNext; - - // always true in this case - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - this.children.splice(index, 0, child); - // need to remove any render groups.. - if(this.__renderGroup) - { - // being used by a renderTexture.. if it exists then it must be from a render texture; - if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); - // add them to the new render group.. - this.__renderGroup.addDisplayObjectAndChildren(child); - } - - } - else - { - throw new Error(child + " The index "+ index +" supplied is out of bounds " + this.children.length); - } -} - -/** - * [NYI] Swaps the depth of 2 displayObjects - * - * @method swapChildren - * @param child {DisplayObject} - * @param child2 {DisplayObject} - * @private - */ -PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2) -{ - /* - * this funtion needs to be recoded.. - * can be done a lot faster.. - */ - return; - - // need to fix this function :/ - /* - // TODO I already know this?? - var index = this.children.indexOf( child ); - var index2 = this.children.indexOf( child2 ); - - if ( index !== -1 && index2 !== -1 ) - { - // cool - - /* - if(this.stage) - { - // this is to satisfy the webGL batching.. - // TODO sure there is a nicer way to achieve this! - this.stage.__removeChild(child); - this.stage.__removeChild(child2); - - this.stage.__addChild(child); - this.stage.__addChild(child2); - } - - // swap the positions.. - this.children[index] = child2; - this.children[index2] = child; - - } - else - { - throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); - }*/ -} - -/** - * Returns the Child at the specified index - * - * @method getChildAt - * @param index {Number} The index to get the child from - */ -PIXI.DisplayObjectContainer.prototype.getChildAt = function(index) -{ - if(index >= 0 && index < this.children.length) - { - return this.children[index]; - } - else - { - throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); - } -} - -/** - * Removes a child from the container. - * - * @method removeChild - * @param child {DisplayObject} The DisplayObject to remove - */ -PIXI.DisplayObjectContainer.prototype.removeChild = function(child) -{ - var index = this.children.indexOf( child ); - if ( index !== -1 ) - { - // unlink // - // modify the list.. - var childFirst = child.first; - var childLast = child.last; - - var nextObject = childLast._iNext; - var previousObject = childFirst._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - - if(this.last == childLast) - { - var tempLast = childFirst._iPrev; - // need to make sure the parents last is updated too - var updateLast = this; - while(updateLast.last == childLast.last) - { - updateLast.last = tempLast; - updateLast = updateLast.parent; - if(!updateLast)break; - } - } - - childLast._iNext = null; - childFirst._iPrev = null; - - // update the stage reference.. - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = null; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // webGL trim - if(child.__renderGroup) - { - child.__renderGroup.removeDisplayObjectAndChildren(child); - } - - child.parent = undefined; - this.children.splice( index, 1 ); - } - else - { - throw new Error(child + " The supplied DisplayObject must be a child of the caller " + this); - } -} - -/* - * Updates the container's children's transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.DisplayObjectContainer.prototype.updateTransform = function() -{ - if(!this.visible)return; - - PIXI.DisplayObject.prototype.updateTransform.call( this ); - - for(var i=0,j=this.children.length; i} an array of {Texture} objects that make up the animation - */ -PIXI.MovieClip = function(textures) -{ - PIXI.Sprite.call(this, textures[0]); - - /** - * The array of textures that make up the animation - * - * @property textures - * @type Array - */ - this.textures = textures; - - /** - * The speed that the MovieClip will play at. Higher is faster, lower is slower - * - * @property animationSpeed - * @type Number - * @default 1 - */ - this.animationSpeed = 1; - - /** - * Whether or not the movie clip repeats after playing. - * - * @property loop - * @type Boolean - * @default true - */ - this.loop = true; - - /** - * Function to call when a MovieClip finishes playing - * - * @property onComplete - * @type Function - */ - this.onComplete = null; - - /** - * [read-only] The index MovieClips current frame (this may not have to be a whole number) - * - * @property currentFrame - * @type Number - * @default 0 - * @readOnly - */ - this.currentFrame = 0; - - /** - * [read-only] Indicates if the MovieClip is currently playing - * - * @property playing - * @type Boolean - * @readOnly - */ - this.playing = false; -} - -// constructor -PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); -PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; - -/** -* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures -* assigned to the MovieClip. -* -* @property totalFrames -* @type Number -* @default 0 -* @readOnly -*/ -Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { - get: function() { - - return this.textures.length; - } -}); - - -/** - * Stops the MovieClip - * - * @method stop - */ -PIXI.MovieClip.prototype.stop = function() -{ - this.playing = false; -} - -/** - * Plays the MovieClip - * - * @method play - */ -PIXI.MovieClip.prototype.play = function() -{ - this.playing = true; -} - -/** - * Stops the MovieClip and goes to a specific frame - * - * @method gotoAndStop - * @param frameNumber {Number} frame index to stop at - */ -PIXI.MovieClip.prototype.gotoAndStop = function(frameNumber) -{ - this.playing = false; - this.currentFrame = frameNumber; - var round = (this.currentFrame + 0.5) | 0; - this.setTexture(this.textures[round % this.textures.length]); -} - -/** - * Goes to a specific frame and begins playing the MovieClip - * - * @method gotoAndPlay - * @param frameNumber {Number} frame index to start at - */ -PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) -{ - this.currentFrame = frameNumber; - this.playing = true; -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.MovieClip.prototype.updateTransform = function() -{ - PIXI.Sprite.prototype.updateTransform.call(this); - - if(!this.playing)return; - - this.currentFrame += this.animationSpeed; - - var round = (this.currentFrame + 0.5) | 0; - - if(this.loop || round < this.textures.length) - { - this.setTexture(this.textures[round % this.textures.length]); - } - else if(round >= this.textures.length) - { - this.gotoAndStop(this.textures.length - 1); - if(this.onComplete) - { - this.onComplete(); - } - } -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - - -PIXI.FilterBlock = function() -{ - this.visible = true; - this.renderable = true; -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.ColorMatrixFilter = function() -{ - // set the uniforms - this.uniforms = { - matrix: {type: 'mat4', value: [1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1]}, - }; - - this.fragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform float invert;", - "uniform mat4 matrix;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", - "gl_FragColor = gl_FragColor * vColor;", - "}" - ]; - -} - - -Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { - get: function() { - return this.uniforms.matrix.value; - }, - set: function(value) { - this.uniforms.matrix.value = value; - } -}); -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Text Object will create a line(s) of text to split a line you can use "\n" - * - * @class Text - * @extends Sprite - * @constructor - * @param text {String} The copy that you would like the text to display - * @param [style] {Object} The style parameters - * @param [style.font] {String} default "bold 20pt Arial" The style and size of the font - * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - * @param [style.stroke] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" - * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) - * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used - * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap - */ -PIXI.Text = function(text, style) -{ - this.canvas = document.createElement("canvas"); - this.context = this.canvas.getContext("2d"); - PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas)); - - this.setText(text); - this.setStyle(style); - - this.updateText(); - this.dirty = false; -}; - -// constructor -PIXI.Text.prototype = Object.create(PIXI.Sprite.prototype); -PIXI.Text.prototype.constructor = PIXI.Text; - -/** - * Set the style of the text - * - * @method setStyle - * @param [style] {Object} The style parameters - * @param [style.font="bold 20pt Arial"] {String} The style and size of the font - * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - * @param [style.stroke="black"] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" - * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) - * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used - * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap - */ -PIXI.Text.prototype.setStyle = function(style) -{ - style = style || {}; - style.font = style.font || "bold 20pt Arial"; - style.fill = style.fill || "black"; - style.align = style.align || "left"; - style.stroke = style.stroke || "black"; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136 - style.strokeThickness = style.strokeThickness || 0; - style.wordWrap = style.wordWrap || false; - style.wordWrapWidth = style.wordWrapWidth || 100; - this.style = style; - this.dirty = true; -}; - -/** - * Set the copy for the text object. To split a line you can use "\n" - * - * @methos setText - * @param {String} text The copy that you would like the text to display - */ -PIXI.Text.prototype.setText = function(text) -{ - this.text = text.toString() || " "; - this.dirty = true; -}; - -/** - * Renders text - * - * @method updateText - * @private - */ -PIXI.Text.prototype.updateText = function() -{ - this.context.font = this.style.font; - - var outputText = this.text; - - // word wrap - // preserve original text - if(this.style.wordWrap)outputText = this.wordWrap(this.text); - - //split text into lines - var lines = outputText.split(/(?:\r\n|\r|\n)/); - - //calculate text width - var lineWidths = []; - var maxLineWidth = 0; - for (var i = 0; i < lines.length; i++) - { - var lineWidth = this.context.measureText(lines[i]).width; - lineWidths[i] = lineWidth; - maxLineWidth = Math.max(maxLineWidth, lineWidth); - } - this.canvas.width = maxLineWidth + this.style.strokeThickness; - - //calculate text height - var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; - this.canvas.height = lineHeight * lines.length; - - //set canvas text styles - this.context.fillStyle = this.style.fill; - this.context.font = this.style.font; - - this.context.strokeStyle = this.style.stroke; - this.context.lineWidth = this.style.strokeThickness; - - this.context.textBaseline = "top"; - - //draw lines line by line - for (i = 0; i < lines.length; i++) - { - var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); - - if(this.style.align == "right") - { - linePosition.x += maxLineWidth - lineWidths[i]; - } - else if(this.style.align == "center") - { - linePosition.x += (maxLineWidth - lineWidths[i]) / 2; - } - - if(this.style.stroke && this.style.strokeThickness) - { - this.context.strokeText(lines[i], linePosition.x, linePosition.y); - } - - if(this.style.fill) - { - this.context.fillText(lines[i], linePosition.x, linePosition.y); - } - } - - this.updateTexture(); -}; - -/** - * Updates texture size based on canvas size - * - * @method updateTexture - * @private - */ -PIXI.Text.prototype.updateTexture = function() -{ - this.texture.baseTexture.width = this.canvas.width; - this.texture.baseTexture.height = this.canvas.height; - this.texture.frame.width = this.canvas.width; - this.texture.frame.height = this.canvas.height; - - this._width = this.canvas.width; - this._height = this.canvas.height; - - PIXI.texturesToUpdate.push(this.texture.baseTexture); -}; - -/** - * Updates the transfor of this object - * - * @method updateTransform - * @private - */ -PIXI.Text.prototype.updateTransform = function() -{ - if(this.dirty) - { - this.updateText(); - this.dirty = false; - } - - PIXI.Sprite.prototype.updateTransform.call(this); -}; - -/* - * http://stackoverflow.com/users/34441/ellisbben - * great solution to the problem! - * - * @method determineFontHeight - * @param fontStyle {Object} - * @private - */ -PIXI.Text.prototype.determineFontHeight = function(fontStyle) -{ - // build a little reference dictionary so if the font style has been used return a - // cached version... - var result = PIXI.Text.heightCache[fontStyle]; - - if(!result) - { - var body = document.getElementsByTagName("body")[0]; - var dummy = document.createElement("div"); - var dummyText = document.createTextNode("M"); - dummy.appendChild(dummyText); - dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); - body.appendChild(dummy); - - result = dummy.offsetHeight; - PIXI.Text.heightCache[fontStyle] = result; - - body.removeChild(dummy); - } - - return result; -}; - -/** - * A Text Object will apply wordwrap - * - * @method wordWrap - * @param text {String} - * @private - */ -PIXI.Text.prototype.wordWrap = function(text) -{ - // search good wrap position - var searchWrapPos = function(ctx, text, start, end, wrapWidth) - { - var p = Math.floor((end-start) / 2) + start; - if(p == start) { - return 1; - } - - if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) - { - if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) - { - return p; - } - else - { - return arguments.callee(ctx, text, p, end, wrapWidth); - } - } - else - { - return arguments.callee(ctx, text, start, p, wrapWidth); - } - }; - - var lineWrap = function(ctx, text, wrapWidth) - { - if(ctx.measureText(text).width <= wrapWidth || text.length < 1) - { - return text; - } - var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); - return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); - }; - - var result = ""; - var lines = text.split("\n"); - for (var i = 0; i < lines.length; i++) - { - result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; - } - - return result; -}; - -/** - * Destroys this text object - * - * @method destroy - * @param destroyTexture {Boolean} - */ -PIXI.Text.prototype.destroy = function(destroyTexture) -{ - if(destroyTexture) - { - this.texture.destroy(); - } - -}; - -PIXI.Text.heightCache = {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" - * You can generate the fnt files using - * http://www.angelcode.com/products/bmfont/ for windows or - * http://www.bmglyph.com/ for mac. - * - * @class BitmapText - * @extends DisplayObjectContainer - * @constructor - * @param text {String} The copy that you would like the text to display - * @param style {Object} The style parameters - * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - */ -PIXI.BitmapText = function(text, style) -{ - PIXI.DisplayObjectContainer.call(this); - - this.setText(text); - this.setStyle(style); - this.updateText(); - this.dirty = false - -}; - -// constructor -PIXI.BitmapText.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); -PIXI.BitmapText.prototype.constructor = PIXI.BitmapText; - -/** - * Set the copy for the text object - * - * @method setText - * @param text {String} The copy that you would like the text to display - */ -PIXI.BitmapText.prototype.setText = function(text) -{ - this.text = text || " "; - this.dirty = true; -}; - -/** - * Set the style of the text - * - * @method setStyle - * @param style {Object} The style parameters - * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - */ -PIXI.BitmapText.prototype.setStyle = function(style) -{ - style = style || {}; - style.align = style.align || "left"; - this.style = style; - - var font = style.font.split(" "); - this.fontName = font[font.length - 1]; - this.fontSize = font.length >= 2 ? parseInt(font[font.length - 2], 10) : PIXI.BitmapText.fonts[this.fontName].size; - - this.dirty = true; -}; - -/** - * Renders text - * - * @method updateText - * @private - */ -PIXI.BitmapText.prototype.updateText = function() -{ - var data = PIXI.BitmapText.fonts[this.fontName]; - var pos = new PIXI.Point(); - var prevCharCode = null; - var chars = []; - var maxLineWidth = 0; - var lineWidths = []; - var line = 0; - var scale = this.fontSize / data.size; - for(var i = 0; i < this.text.length; i++) - { - var charCode = this.text.charCodeAt(i); - if(/(?:\r\n|\r|\n)/.test(this.text.charAt(i))) - { - lineWidths.push(pos.x); - maxLineWidth = Math.max(maxLineWidth, pos.x); - line++; - - pos.x = 0; - pos.y += data.lineHeight; - prevCharCode = null; - continue; - } - - var charData = data.chars[charCode]; - if(!charData) continue; - - if(prevCharCode && charData[prevCharCode]) - { - pos.x += charData.kerning[prevCharCode]; - } - chars.push({texture:charData.texture, line: line, charCode: charCode, position: new PIXI.Point(pos.x + charData.xOffset, pos.y + charData.yOffset)}); - pos.x += charData.xAdvance; - - prevCharCode = charCode; - } - - lineWidths.push(pos.x); - maxLineWidth = Math.max(maxLineWidth, pos.x); - - var lineAlignOffsets = []; - for(i = 0; i <= line; i++) - { - var alignOffset = 0; - if(this.style.align == "right") - { - alignOffset = maxLineWidth - lineWidths[i]; - } - else if(this.style.align == "center") - { - alignOffset = (maxLineWidth - lineWidths[i]) / 2; - } - lineAlignOffsets.push(alignOffset); - } - - for(i = 0; i < chars.length; i++) - { - var c = new PIXI.Sprite(chars[i].texture)//PIXI.Sprite.fromFrame(chars[i].charCode); - c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale; - c.position.y = chars[i].position.y * scale; - c.scale.x = c.scale.y = scale; - this.addChild(c); - } - - this.width = pos.x * scale; - this.height = (pos.y + data.lineHeight) * scale; -}; - -/** - * Updates the transfor of this object - * - * @method updateTransform - * @private - */ -PIXI.BitmapText.prototype.updateTransform = function() -{ - if(this.dirty) - { - while(this.children.length > 0) - { - this.removeChild(this.getChildAt(0)); - } - this.updateText(); - - this.dirty = false; - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -}; - -PIXI.BitmapText.fonts = {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - /** - * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive - * This manager also supports multitouch. - * - * @class InteractionManager - * @constructor - * @param stage {Stage} The stage to handle interactions - */ -PIXI.InteractionManager = function(stage) -{ - /** - * a refference to the stage - * - * @property stage - * @type Stage - */ - this.stage = stage; - - /** - * the mouse data - * - * @property mouse - * @type InteractionData - */ - this.mouse = new PIXI.InteractionData(); - - /** - * an object that stores current touches (InteractionData) by id reference - * - * @property touchs - * @type Object - */ - this.touchs = {}; - - - - // helpers - this.tempPoint = new PIXI.Point(); - //this.tempMatrix = mat3.create(); - - this.mouseoverEnabled = true; - - //tiny little interactiveData pool! - this.pool = []; - - this.interactiveItems = []; - this.interactionDOMElement = null; - - //this will make it so that you dont have to call bind all the time - this.onMouseMove = this.onMouseMove.bind( this ); - this.onMouseDown = this.onMouseDown.bind(this); - this.onMouseOut = this.onMouseOut.bind(this); - this.onMouseUp = this.onMouseUp.bind(this); - - this.onTouchStart = this.onTouchStart.bind(this); - this.onTouchEnd = this.onTouchEnd.bind(this); - this.onTouchMove = this.onTouchMove.bind(this); - - - this.last = 0; -} - -// constructor -PIXI.InteractionManager.prototype.constructor = PIXI.InteractionManager; - -/** - * Collects an interactive sprite recursively to have their interactions managed - * - * @method collectInteractiveSprite - * @param displayObject {DisplayObject} the displayObject to collect - * @param iParent {DisplayObject} - * @private - */ -PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObject, iParent) -{ - var children = displayObject.children; - var length = children.length; - - /// make an interaction tree... {item.__interactiveParent} - for (var i = length-1; i >= 0; i--) - { - var child = children[i]; - -// if(child.visible) { - // push all interactive bits - if(child.interactive) - { - iParent.interactiveChildren = true; - //child.__iParent = iParent; - this.interactiveItems.push(child); - - if(child.children.length > 0) - { - this.collectInteractiveSprite(child, child); - } - } - else - { - child.__iParent = null; - - if(child.children.length > 0) - { - this.collectInteractiveSprite(child, iParent); - } - } -// } - } -} - -/** - * Sets the target for event delegation - * - * @method setTarget - * @param target {WebGLRenderer|CanvasRenderer} the renderer to bind events to - * @private - */ -PIXI.InteractionManager.prototype.setTarget = function(target) -{ - this.target = target; - - //check if the dom element has been set. If it has don't do anything - if( this.interactionDOMElement === null ) { - - this.setTargetDomElement( target.view ); - } - - document.body.addEventListener('mouseup', this.onMouseUp, true); -} - - -/** - * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM - * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element - * to receive those events - * - * @method setTargetDomElement - * @param domElement {DOMElement} the dom element which will receive mouse and touch events - * @private - */ -PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) -{ - //remove previouse listeners - if( this.interactionDOMElement !== null ) - { - this.interactionDOMElement.style['-ms-content-zooming'] = ''; - this.interactionDOMElement.style['-ms-touch-action'] = ''; - - this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); - this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); - this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); - - // aint no multi touch just yet! - this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); - this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); - this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); - } - - - if (window.navigator.msPointerEnabled) - { - // time to remove some of that zoom in ja.. - domElement.style['-ms-content-zooming'] = 'none'; - domElement.style['-ms-touch-action'] = 'none'; - - // DO some window specific touch! - } - - this.interactionDOMElement = domElement; - - domElement.addEventListener('mousemove', this.onMouseMove, true); - domElement.addEventListener('mousedown', this.onMouseDown, true); - domElement.addEventListener('mouseout', this.onMouseOut, true); - - // aint no multi touch just yet! - domElement.addEventListener('touchstart', this.onTouchStart, true); - domElement.addEventListener('touchend', this.onTouchEnd, true); - domElement.addEventListener('touchmove', this.onTouchMove, true); -} - - -/** - * updates the state of interactive objects - * - * @method update - * @private - */ -PIXI.InteractionManager.prototype.update = function() -{ - if(!this.target)return; - - // frequency of 30fps?? - var now = Date.now(); - var diff = now - this.last; - diff = (diff * 30) / 1000; - if(diff < 1)return; - this.last = now; - // - - // ok.. so mouse events?? - // yes for now :) - // OPTIMSE - how often to check?? - if(this.dirty) - { - this.dirty = false; - - var len = this.interactiveItems.length; - - for (var i=0; i < len; i++) { - this.interactiveItems[i].interactiveChildren = false; - } - - this.interactiveItems = []; - - if(this.stage.interactive)this.interactiveItems.push(this.stage); - // go through and collect all the objects that are interactive.. - this.collectInteractiveSprite(this.stage, this.stage); - } - - // loop through interactive objects! - var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - - //if(!item.visible)continue; - - // OPTIMISATION - only calculate every time if the mousemove function exists.. - // OK so.. does the object have any other interactive functions? - // hit-test the clip! - - - if(item.mouseover || item.mouseout || item.buttonMode) - { - // ok so there are some functions so lets hit test it.. - item.__hit = this.hitTest(item, this.mouse); - this.mouse.target = item; - // ok so deal with interactions.. - // loks like there was a hit! - if(item.__hit) - { - if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; - - if(!item.__isOver) - { - - if(item.mouseover)item.mouseover(this.mouse); - item.__isOver = true; - } - } - else - { - if(item.__isOver) - { - // roll out! - if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; - } - } - } - - // ---> - } -} - -/** - * Is called when the mouse moves accross the renderer element - * - * @method onMouseMove - * @param event {Event} The DOM event of the mouse moving - * @private - */ -PIXI.InteractionManager.prototype.onMouseMove = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - // TODO optimize by not check EVERY TIME! maybe half as often? // - var rect = this.interactionDOMElement.getBoundingClientRect(); - - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); - - var length = this.interactiveItems.length; - var global = this.mouse.global; - - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mousemove) - { - //call the function! - item.mousemove(this.mouse); - } - } -} - -/** - * Is called when the mouse button is pressed down on the renderer element - * - * @method onMouseDown - * @param event {Event} The DOM event of a mouse button being pressed down - * @private - */ -PIXI.InteractionManager.prototype.onMouseDown = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - - // loop through inteaction tree... - // hit test each item! -> - // get interactive items under point?? - //stage.__i - var length = this.interactiveItems.length; - var global = this.mouse.global; - - var index = 0; - var parent = this.stage; - - // while - // hit test - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mousedown || item.click) - { - item.__mouseIsDown = true; - item.__hit = this.hitTest(item, this.mouse); - - if(item.__hit) - { - //call the function! - if(item.mousedown)item.mousedown(this.mouse); - item.__isDown = true; - - // just the one! - if(!item.interactiveChildren)break; - } - } - } -} - - -PIXI.InteractionManager.prototype.onMouseOut = function(event) -{ - var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.__isOver) - { - this.mouse.target = item; - if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; - } - } -} - -/** - * Is called when the mouse button is released on the renderer element - * - * @method onMouseUp - * @param event {Event} The DOM event of a mouse button being released - * @private - */ -PIXI.InteractionManager.prototype.onMouseUp = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - - var global = this.mouse.global; - - - var length = this.interactiveItems.length; - var up = false; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mouseup || item.mouseupoutside || item.click) - { - item.__hit = this.hitTest(item, this.mouse); - - if(item.__hit && !up) - { - //call the function! - if(item.mouseup) - { - item.mouseup(this.mouse); - } - if(item.__isDown) - { - if(item.click)item.click(this.mouse); - } - - if(!item.interactiveChildren)up = true; - } - else - { - if(item.__isDown) - { - if(item.mouseupoutside)item.mouseupoutside(this.mouse); - } - } - - item.__isDown = false; - } - } -} - -/** - * Tests if the current mouse coords hit a sprite - * - * @method hitTest - * @param item {DisplayObject} The displayObject to test for a hit - * @param interactionData {InteractionData} The interactiondata object to update in the case of a hit - * @private - */ -PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) -{ - var global = interactionData.global; - - if(item.vcount !== PIXI.visibleCount)return false; - - var isSprite = (item instanceof PIXI.Sprite), - worldTransform = item.worldTransform, - a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10), - x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, - y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - interactionData.target = item; - - //a sprite or display object with a hit area defined - if(item.hitArea && item.hitArea.contains) { - if(item.hitArea.contains(x, y)) { - //if(isSprite) - interactionData.target = item; - - return true; - } - - return false; - } - // a sprite with no hitarea defined - else if(isSprite) - { - var width = item.texture.frame.width, - height = item.texture.frame.height, - x1 = -width * item.anchor.x, - y1; - - if(x > x1 && x < x1 + width) - { - y1 = -height * item.anchor.y; - - if(y > y1 && y < y1 + height) - { - // set the target property if a hit is true! - interactionData.target = item - return true; - } - } - } - - var length = item.children.length; - - for (var i = 0; i < length; i++) - { - var tempItem = item.children[i]; - var hit = this.hitTest(tempItem, interactionData); - if(hit) - { - // hmm.. TODO SET CORRECT TARGET? - interactionData.target = item - return true; - } - } - - return false; -} - -/** - * Is called when a touch is moved accross the renderer element - * - * @method onTouchMove - * @param event {Event} The DOM event of a touch moving accross the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchMove = function(event) -{ - var rect = this.interactionDOMElement.getBoundingClientRect(); - var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - var touchData = this.touchs[touchEvent.identifier]; - touchData.originalEvent = event || window.event; - - // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - } - - var length = this.interactiveItems.length; - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - if(item.touchmove)item.touchmove(touchData); - } -} - -/** - * Is called when a touch is started on the renderer element - * - * @method onTouchStart - * @param event {Event} The DOM event of a touch starting on the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchStart = function(event) -{ - var rect = this.interactionDOMElement.getBoundingClientRect(); - - var changedTouches = event.changedTouches; - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - - var touchData = this.pool.pop(); - if(!touchData)touchData = new PIXI.InteractionData(); - - touchData.originalEvent = event || window.event; - - this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - - var length = this.interactiveItems.length; - - for (var j = 0; j < length; j++) - { - var item = this.interactiveItems[j]; - - if(item.touchstart || item.tap) - { - item.__hit = this.hitTest(item, touchData); - - if(item.__hit) - { - //call the function! - if(item.touchstart)item.touchstart(touchData); - item.__isDown = true; - item.__touchData = touchData; - - if(!item.interactiveChildren)break; - } - } - } - } -} - -/** - * Is called when a touch is ended on the renderer element - * - * @method onTouchEnd - * @param event {Event} The DOM event of a touch ending on the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchEnd = function(event) -{ - //this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.interactionDOMElement.getBoundingClientRect(); - var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - var touchData = this.touchs[touchEvent.identifier]; - var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - - var length = this.interactiveItems.length; - for (var j = 0; j < length; j++) - { - var item = this.interactiveItems[j]; - var itemTouchData = item.__touchData; // <-- Here! - item.__hit = this.hitTest(item, touchData); - - if(itemTouchData == touchData) - { - // so this one WAS down... - touchData.originalEvent = event || window.event; - // hitTest?? - - if(item.touchend || item.tap) - { - if(item.__hit && !up) - { - if(item.touchend)item.touchend(touchData); - if(item.__isDown) - { - if(item.tap)item.tap(touchData); - } - - if(!item.interactiveChildren)up = true; - } - else - { - if(item.__isDown) - { - if(item.touchendoutside)item.touchendoutside(touchData); - } - } - - item.__isDown = false; - } - - item.__touchData = null; - - } - else - { - - } - } - // remove the touch.. - this.pool.push(touchData); - this.touchs[touchEvent.identifier] = null; - } -} - -/** - * Holds all information related to an Interaction event - * - * @class InteractionData - * @constructor - */ -PIXI.InteractionData = function() -{ - /** - * This point stores the global coords of where the touch/mouse event happened - * - * @property global - * @type Point - */ - this.global = new PIXI.Point(); - - // this is here for legacy... but will remove - this.local = new PIXI.Point(); - - /** - * The target Sprite that was interacted with - * - * @property target - * @type Sprite - */ - this.target; - - /** - * When passed to an event handler, this will be the original DOM Event that was captured - * - * @property originalEvent - * @type Event - */ - this.originalEvent; -} - -/** - * This will return the local coords of the specified displayObject for this InteractionData - * - * @method getLocalPosition - * @param displayObject {DisplayObject} The DisplayObject that you would like the local coords off - * @return {Point} A point containing the coords of the InteractionData position relative to the DisplayObject - */ -PIXI.InteractionData.prototype.getLocalPosition = function(displayObject) -{ - var worldTransform = displayObject.worldTransform; - var global = this.global; - - // do a cheeky transform to get the mouse coords; - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - // set the mouse coords... - return new PIXI.Point(a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, - a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id) -} - -// constructor -PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Stage represents the root of the display tree. Everything connected to the stage is rendered - * - * @class Stage - * @extends DisplayObjectContainer - * @constructor - * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format - * like: 0xFFFFFF for white - */ -PIXI.Stage = function(backgroundColor) -{ - PIXI.DisplayObjectContainer.call( this ); - - /** - * [read-only] Current transform of the object based on world (parent) factors - * - * @property worldTransform - * @type Mat3 - * @readOnly - * @private - */ - this.worldTransform = PIXI.mat3.create(); - - /** - * Whether or not the stage is interactive - * - * @property interactive - * @type Boolean - */ - this.interactive = true; - - /** - * The interaction manage for this stage, manages all interactive activity on the stage - * - * @property interactive - * @type InteractionManager - */ - this.interactionManager = new PIXI.InteractionManager(this); - - /** - * Whether the stage is dirty and needs to have interactions updated - * - * @property dirty - * @type Boolean - * @private - */ - this.dirty = true; - - this.__childrenAdded = []; - this.__childrenRemoved = []; - - //the stage is it's own stage - this.stage = this; - - //optimize hit detection a bit - this.stage.hitArea = new PIXI.Rectangle(0,0,100000, 100000); - - this.setBackgroundColor(backgroundColor); - this.worldVisible = true; -} - -// constructor -PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Stage.prototype.constructor = PIXI.Stage; - -/** - * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. - * This is useful for when you have other DOM elements ontop of the Canvas element. - * - * @method setInteractionDelegate - * @param domElement {DOMElement} This new domElement which will receive mouse/touch events - */ -PIXI.Stage.prototype.setInteractionDelegate = function(domElement) -{ - this.interactionManager.setTargetDomElement( domElement ); -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.Stage.prototype.updateTransform = function() -{ - this.worldAlpha = 1; - this.vcount = PIXI.visibleCount; - - for(var i=0,j=this.children.length; i> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; -} - -/** - * A polyfill for Function.prototype.bind - * - * @method bind - */ -if (typeof Function.prototype.bind != 'function') { - Function.prototype.bind = (function () { - var slice = Array.prototype.slice; - return function (thisArg) { - var target = this, boundArgs = slice.call(arguments, 1); - - if (typeof target != 'function') throw new TypeError(); - - function bound() { - var args = boundArgs.concat(slice.call(arguments)); - target.apply(this instanceof bound ? this : thisArg, args); - } - - bound.prototype = (function F(proto) { - proto && (F.prototype = proto); - if (!(this instanceof F)) return new F; - })(target.prototype); - - return bound; - }; - })(); -} - -/** - * A wrapper for ajax requests to be handled cross browser - * - * @class AjaxRequest - * @constructor - */ -var AjaxRequest = PIXI.AjaxRequest = function() -{ - var activexmodes = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Microsoft.XMLHTTP"] //activeX versions to check for in IE - - if (window.ActiveXObject) - { //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken) - for (var i=0; i>>>>>>>>") - console.log("_") - var safe = 0; - var tmp = item.first; - console.log(tmp); - - while(tmp._iNext) - { - safe++; - tmp = tmp._iNext; - console.log(tmp); - // console.log(tmp); - - if(safe > 100) - { - console.log("BREAK") - break - } - } -} - - - - - - -/** - * https://github.com/mrdoob/eventtarget.js/ - * THankS mr DOob! - */ - -/** - * Adds event emitter functionality to a class - * - * @class EventTarget - * @example - * function MyEmitter() { - * PIXI.EventTarget.call(this); //mixes in event target stuff - * } - * - * var em = new MyEmitter(); - * em.emit({ type: 'eventName', data: 'some data' }); - */ -PIXI.EventTarget = function () { - - var listeners = {}; - - this.addEventListener = this.on = function ( type, listener ) { - - - if ( listeners[ type ] === undefined ) { - - listeners[ type ] = []; - - } - - if ( listeners[ type ].indexOf( listener ) === - 1 ) { - - listeners[ type ].push( listener ); - } - - }; - - this.dispatchEvent = this.emit = function ( event ) { - - if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { - - return; - - } - - for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { - - listeners[ event.type ][ i ]( event ); - - } - - }; - - this.removeEventListener = this.off = function ( type, listener ) { - - var index = listeners[ type ].indexOf( listener ); - - if ( index !== - 1 ) { - - listeners[ type ].splice( index, 1 ); - - } - - }; - -}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * This helper function will automatically detect which renderer you should be using. - * WebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by - * the browser then this function will return a canvas renderer - * - * @method autoDetectRenderer - * @static - * @param width {Number} the width of the renderers view - * @param height {Number} the height of the renderers view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) - * - * antialias - */ -PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) -{ - if(!width)width = 800; - if(!height)height = 600; - - // BORROWED from Mr Doob (mrdoob.com) - var webgl = ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(); - - //console.log(webgl); - if( webgl ) - { - return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); - } - - return new PIXI.CanvasRenderer(width, height, view, transparent); -}; - - - -/* - PolyK library - url: http://polyk.ivank.net - Released under MIT licence. - - Copyright (c) 2012 Ivan Kuckir - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - - This is an amazing lib! - - slightly modified by mat groves (matgroves.com); -*/ - -PIXI.PolyK = {}; - -/** - * Triangulates shapes for webGL graphic fills - * - * @method Triangulate - * @namespace PolyK - * @constructor - */ -PIXI.PolyK.Triangulate = function(p) -{ - var sign = true; - - var n = p.length>>1; - if(n<3) return []; - var tgs = []; - var avl = []; - for(var i=0; i 3) - { - var i0 = avl[(i+0)%al]; - var i1 = avl[(i+1)%al]; - var i2 = avl[(i+2)%al]; - - var ax = p[2*i0], ay = p[2*i0+1]; - var bx = p[2*i1], by = p[2*i1+1]; - var cx = p[2*i2], cy = p[2*i2+1]; - - var earFound = false; - if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) - { - earFound = true; - for(var j=0; j 3*al) - { - // need to flip flip reverse it! - // reset! - if(sign) - { - var tgs = []; - avl = []; - for(var i=0; i= 0) && (v >= 0) && (u + v < 1); -} - -/** - * Checks if a shape is convex - * - * @class _convex - * @namespace PolyK - * @private - */ -PIXI.PolyK._convex = function(ax, ay, bx, by, cx, cy, sign) -{ - return ((ay-by)*(cx-bx) + (bx-ax)*(cy-by) >= 0) == sign; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/* - * the default suoer fast shader! - */ - -PIXI.shaderFragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", - "gl_FragColor = gl_FragColor * vColor;", - "}" -]; - -PIXI.shaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - - "uniform vec2 projectionVector;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "void main(void) {", - "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" -]; - -/* - * the triangle strip shader.. - */ - -PIXI.stripShaderFragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform float alpha;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", - "gl_FragColor = gl_FragColor * alpha;", - "}" -]; - - -PIXI.stripShaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" -]; - -/* - * primitive shader.. - */ - -PIXI.primitiveShaderFragmentSrc = [ - "precision mediump float;", - "varying vec4 vColor;", - "void main(void) {", - "gl_FragColor = vColor;", - "}" -]; - -PIXI.primitiveShaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec4 aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "uniform float alpha;", - "varying vec4 vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vColor = aColor * alpha;", - "}" -]; - -PIXI.shaderStack = []; - -PIXI.initPrimitiveShader = function() -{ - var gl = PIXI.gl; - - var shaderProgram = PIXI.compileProgram(PIXI.primitiveShaderVertexSrc, PIXI.primitiveShaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); - - - //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - //gl.enableVertexAttribArray(shaderProgram.colorAttribute); -//gl.enableVertexAttribArray(program.textureCoordAttribute); - - shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); - - PIXI.primitiveProgram = shaderProgram; - - -} - -PIXI.initDefaultShader = function() -{ - PIXI.defaultShader = new PIXI.PixiShader(); - PIXI.defaultShader.init(); - PIXI.activateShader(PIXI.defaultShader); - /* - PIXI.shaderStack.push(PIXI.defaultShader); - PIXI.current*/ -} - -PIXI.initDefaultStripShader = function() -{ - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.stripShaderVertexSrc, PIXI.stripShaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); - shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); - - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.stripShaderProgram = shaderProgram; -} - -PIXI.CompileVertexShader = function(gl, shaderSrc) -{ - return PIXI._CompileShader(gl, shaderSrc, gl.VERTEX_SHADER); -} - -PIXI.CompileFragmentShader = function(gl, shaderSrc) -{ - return PIXI._CompileShader(gl, shaderSrc, gl.FRAGMENT_SHADER); -} - -PIXI._CompileShader = function(gl, shaderSrc, shaderType) -{ - var src = shaderSrc.join("\n"); - var shader = gl.createShader(shaderType); - gl.shaderSource(shader, src); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - alert(gl.getShaderInfoLog(shader)); - return null; - } - - return shader; -} - - -PIXI.compileProgram = function(vertexSrc, fragmentSrc) -{ - var gl = PIXI.gl; - var fragmentShader = PIXI.CompileFragmentShader(gl, fragmentSrc); - var vertexShader = PIXI.CompileVertexShader(gl, vertexSrc); - - var shaderProgram = gl.createProgram(); - - gl.attachShader(shaderProgram, vertexShader); - gl.attachShader(shaderProgram, fragmentShader); - gl.linkProgram(shaderProgram); - - if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { - alert("Could not initialise shaders"); - } - - return shaderProgram; -} - -PIXI.activateShader = function(shader) -{ - PIXI.shaderStack.push(shader); - - //console.log(">>>") - var gl = PIXI.gl; - - var shaderProgram = shader.program; - - // map uniforms.. - gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - - shader.syncUniforms(); - - PIXI.currentShader = shaderProgram; -} - - -PIXI.popShader = function() -{ - var gl = PIXI.gl; - // activate last program.. - var lastProgram = PIXI.shaderStack.pop(); - - var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; - - gl.useProgram(shaderProgram); - - PIXI.currentShader = shaderProgram; -} - -PIXI.activatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.primitiveProgram); - - //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); - //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); - gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); - - //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); - //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); -} - -PIXI.deactivatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.currentShader); - - gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); - //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); - //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -PIXI.PixiShader = function() -{ - // the webGL program.. - this.program; - - this.fragmentSrc = [ - "precision lowp float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", - "}" - ]; - -} - -PIXI.PixiShader.prototype.init = function() -{ - var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) - - var gl = PIXI.gl; - - gl.useProgram(program); - - // get the default shader bits! - program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); - program.colorAttribute = gl.getAttribLocation(program, "aColor"); - program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); - - program.projectionVector = gl.getUniformLocation(program, "projectionVector"); - program.samplerUniform = gl.getUniformLocation(program, "uSampler"); - - // add those custom shaders! - for (var key in this.uniforms) - { - // get the uniform locations.. - program[key] = gl.getUniformLocation(program, key); - } - - this.program = program; -} - -PIXI.PixiShader.prototype.syncUniforms = function() -{ - var gl = PIXI.gl; - - for (var key in this.uniforms) - { - //var - var type = this.uniforms[key].type; - - // need to grow this! - if(type == "f") - { - gl.uniform1f(this.program[key], this.uniforms[key].value); - } - else if(type == "mat4") - { - gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); - } - } - -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A set of functions used by the webGL renderer to draw the primitive graphics data - * - * @class CanvasGraphics - */ -PIXI.WebGLGraphics = function() -{ - -} - -/** - * Renders the graphics object - * - * @static - * @private - * @method renderGraphics - * @param graphics {Graphics} - * @param projection {Object} - */ -PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) -{ - var gl = PIXI.gl; - - if(!graphics._webGL)graphics._webGL = {points:[], indices:[], lastIndex:0, - buffer:gl.createBuffer(), - indexBuffer:gl.createBuffer()}; - - if(graphics.dirty) - { - graphics.dirty = false; - - if(graphics.clearDirty) - { - graphics.clearDirty = false; - - graphics._webGL.lastIndex = 0; - graphics._webGL.points = []; - graphics._webGL.indices = []; - - } - - PIXI.WebGLGraphics.updateGraphics(graphics); - } - - - PIXI.activatePrimitiveShader(); - - // This could be speeded up fo sure! - var m = PIXI.mat3.clone(graphics.worldTransform); - - PIXI.mat3.transpose(m); - - // set the matrix transform for the - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - gl.uniformMatrix3fv(PIXI.primitiveProgram.translationMatrix, false, m); - - gl.uniform2f(PIXI.primitiveProgram.projectionVector, projection.x, projection.y); - - gl.uniform1f(PIXI.primitiveProgram.alpha, graphics.worldAlpha); - - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - - // WHY DOES THIS LINE NEED TO BE THERE??? - //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - // its not even used.. but need to be set or it breaks? - // only on pc though.. - - gl.vertexAttribPointer(PIXI.primitiveProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 4 * 6, 0); - gl.vertexAttribPointer(PIXI.primitiveProgram.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4); - - // set the index buffer! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); - - gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); - - PIXI.deactivatePrimitiveShader(); - - // return to default shader... -// PIXI.activateShader(PIXI.defaultShader); -} - -/** - * Updates the graphics object - * - * @static - * @private - * @method updateGraphics - * @param graphics {Graphics} - */ -PIXI.WebGLGraphics.updateGraphics = function(graphics) -{ - for (var i=graphics._webGL.lastIndex; i < graphics.graphicsData.length; i++) - { - var data = graphics.graphicsData[i]; - - if(data.type == PIXI.Graphics.POLY) - { - if(data.fill) - { - if(data.points.length>3) - PIXI.WebGLGraphics.buildPoly(data, graphics._webGL); - } - - if(data.lineWidth > 0) - { - PIXI.WebGLGraphics.buildLine(data, graphics._webGL); - } - } - else if(data.type == PIXI.Graphics.RECT) - { - PIXI.WebGLGraphics.buildRectangle(data, graphics._webGL); - } - else if(data.type == PIXI.Graphics.CIRC || data.type == PIXI.Graphics.ELIP) - { - PIXI.WebGLGraphics.buildCircle(data, graphics._webGL); - } - }; - - graphics._webGL.lastIndex = graphics.graphicsData.length; - - var gl = PIXI.gl; - - graphics._webGL.glPoints = new Float32Array(graphics._webGL.points); - - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - gl.bufferData(gl.ARRAY_BUFFER, graphics._webGL.glPoints, gl.STATIC_DRAW); - - graphics._webGL.glIndicies = new Uint16Array(graphics._webGL.indices); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.glIndicies, gl.STATIC_DRAW); -} - -/** - * Builds a rectangle to draw - * - * @static - * @private - * @method buildRectangle - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData) -{ - // --- // - // need to convert points to a nice regular data - // - var rectData = graphicsData.points; - var x = rectData[0]; - var y = rectData[1]; - var width = rectData[2]; - var height = rectData[3]; - - - if(graphicsData.fill) - { - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var verts = webGLData.points; - var indices = webGLData.indices; - - var vertPos = verts.length/6; - - // start - verts.push(x, y); - verts.push(r, g, b, alpha); - - verts.push(x + width, y); - verts.push(r, g, b, alpha); - - verts.push(x , y + height); - verts.push(r, g, b, alpha); - - verts.push(x + width, y + height); - verts.push(r, g, b, alpha); - - // insert 2 dead triangles.. - indices.push(vertPos, vertPos, vertPos+1, vertPos+2, vertPos+3, vertPos+3) - } - - if(graphicsData.lineWidth) - { - graphicsData.points = [x, y, - x + width, y, - x + width, y + height, - x, y + height, - x, y]; - - PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); - } - -} - -/** - * Builds a circle to draw - * - * @static - * @private - * @method buildCircle - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData) -{ - // --- // - // need to convert points to a nice regular data - // - var rectData = graphicsData.points; - var x = rectData[0]; - var y = rectData[1]; - var width = rectData[2]; - var height = rectData[3]; - - var totalSegs = 40; - var seg = (Math.PI * 2) / totalSegs ; - - if(graphicsData.fill) - { - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var verts = webGLData.points; - var indices = webGLData.indices; - - var vecPos = verts.length/6; - - indices.push(vecPos); - - for (var i=0; i < totalSegs + 1 ; i++) - { - verts.push(x,y, r, g, b, alpha); - - verts.push(x + Math.sin(seg * i) * width, - y + Math.cos(seg * i) * height, - r, g, b, alpha); - - indices.push(vecPos++, vecPos++); - }; - - indices.push(vecPos-1); - } - - if(graphicsData.lineWidth) - { - graphicsData.points = []; - - for (var i=0; i < totalSegs + 1; i++) - { - graphicsData.points.push(x + Math.sin(seg * i) * width, - y + Math.cos(seg * i) * height) - }; - - PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); - } - -} - -/** - * Builds a line to draw - * - * @static - * @private - * @method buildLine - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) -{ - // TODO OPTIMISE! - - var wrap = true; - var points = graphicsData.points; - if(points.length == 0)return; - - // get first and last point.. figure out the middle! - var firstPoint = new PIXI.Point( points[0], points[1] ); - var lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - - // if the first point is the last point - goona have issues :) - if(firstPoint.x == lastPoint.x && firstPoint.y == lastPoint.y) - { - points.pop(); - points.pop(); - - lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - - var midPointX = lastPoint.x + (firstPoint.x - lastPoint.x) *0.5; - var midPointY = lastPoint.y + (firstPoint.y - lastPoint.y) *0.5; - - points.unshift(midPointX, midPointY); - points.push(midPointX, midPointY) - } - - var verts = webGLData.points; - var indices = webGLData.indices; - var length = points.length / 2; - var indexCount = points.length; - var indexStart = verts.length/6; - - // DRAW the Line - var width = graphicsData.lineWidth / 2; - - // sort color - var color = HEXtoRGB(graphicsData.lineColor); - var alpha = graphicsData.lineAlpha; - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var p1x, p1y, p2x, p2y, p3x, p3y; - var perpx, perpy, perp2x, perp2y, perp3x, perp3y; - var ipx, ipy; - var a1, b1, c1, a2, b2, c2; - var denom, pdist, dist; - - p1x = points[0]; - p1y = points[1]; - - p2x = points[2]; - p2y = points[3]; - - perpx = -(p1y - p2y); - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - // start - verts.push(p1x - perpx , p1y - perpy, - r, g, b, alpha); - - verts.push(p1x + perpx , p1y + perpy, - r, g, b, alpha); - - for (var i = 1; i < length-1; i++) - { - p1x = points[(i-1)*2]; - p1y = points[(i-1)*2 + 1]; - - p2x = points[(i)*2] - p2y = points[(i)*2 + 1] - - p3x = points[(i+1)*2]; - p3y = points[(i+1)*2 + 1]; - - perpx = -(p1y - p2y); - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - perp2x = -(p2y - p3y); - perp2y = p2x - p3x; - - dist = Math.sqrt(perp2x*perp2x + perp2y*perp2y); - perp2x /= dist; - perp2y /= dist; - perp2x *= width; - perp2y *= width; - - a1 = (-perpy + p1y) - (-perpy + p2y); - b1 = (-perpx + p2x) - (-perpx + p1x); - c1 = (-perpx + p1x) * (-perpy + p2y) - (-perpx + p2x) * (-perpy + p1y); - a2 = (-perp2y + p3y) - (-perp2y + p2y); - b2 = (-perp2x + p2x) - (-perp2x + p3x); - c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y); - - denom = a1*b2 - a2*b1; - - if (denom == 0) { - denom+=1; - } - - px = (b1*c2 - b2*c1)/denom; - py = (a2*c1 - a1*c2)/denom; - - pdist = (px -p2x) * (px -p2x) + (py -p2y) + (py -p2y); - - if(pdist > 140 * 140) - { - perp3x = perpx - perp2x; - perp3y = perpy - perp2y; - - dist = Math.sqrt(perp3x*perp3x + perp3y*perp3y); - perp3x /= dist; - perp3y /= dist; - perp3x *= width; - perp3y *= width; - - verts.push(p2x - perp3x, p2y -perp3y); - verts.push(r, g, b, alpha); - - verts.push(p2x + perp3x, p2y +perp3y); - verts.push(r, g, b, alpha); - - verts.push(p2x - perp3x, p2y -perp3y); - verts.push(r, g, b, alpha); - - indexCount++; - } - else - { - verts.push(px , py); - verts.push(r, g, b, alpha); - - verts.push(p2x - (px-p2x), p2y - (py - p2y)); - verts.push(r, g, b, alpha); - } - } - - p1x = points[(length-2)*2] - p1y = points[(length-2)*2 + 1] - - p2x = points[(length-1)*2] - p2y = points[(length-1)*2 + 1] - - perpx = -(p1y - p2y) - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - verts.push(p2x - perpx , p2y - perpy) - verts.push(r, g, b, alpha); - - verts.push(p2x + perpx , p2y + perpy) - verts.push(r, g, b, alpha); - - indices.push(indexStart); - - for (var i=0; i < indexCount; i++) - { - indices.push(indexStart++); - }; - - indices.push(indexStart-1); -} - -/** - * Builds a polygon to draw - * - * @static - * @private - * @method buildPoly - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData) -{ - var points = graphicsData.points; - if(points.length < 6)return; - - // get first and last point.. figure out the middle! - var verts = webGLData.points; - var indices = webGLData.indices; - - var length = points.length / 2; - - // sort color - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var triangles = PIXI.PolyK.Triangulate(points); - - var vertPos = verts.length / 6; - - for (var i=0; i < triangles.length; i+=3) - { - indices.push(triangles[i] + vertPos); - indices.push(triangles[i] + vertPos); - indices.push(triangles[i+1] + vertPos); - indices.push(triangles[i+2] +vertPos); - indices.push(triangles[i+2] + vertPos); - }; - - for (var i = 0; i < length; i++) - { - verts.push(points[i * 2], points[i * 2 + 1], - r, g, b, alpha); - }; -} - -function HEXtoRGB(hex) { - return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; -} - - - - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI._defaultFrame = new PIXI.Rectangle(0,0,1,1); - -// an instance of the gl context.. -// only one at the moment :/ -PIXI.gl; - -/** - * the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer - * should be used for browsers support webGL. This Render works by automatically managing webGLBatchs. - * So no need for Sprite Batch's or Sprite Cloud's - * Dont forget to add the view to your DOM or you will not see anything :) - * - * @class WebGLRenderer - * @constructor - * @param width=0 {Number} the width of the canvas view - * @param height=0 {Number} the height of the canvas view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) - * - */ -PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) -{ - // do a catch.. only 1 webGL renderer.. - - this.transparent = !!transparent; - - this.width = width || 800; - this.height = height || 600; - - this.view = view || document.createElement( 'canvas' ); - this.view.width = this.width; - this.view.height = this.height; - - // deal with losing context.. - var scope = this; - this.view.addEventListener('webglcontextlost', function(event) { scope.handleContextLost(event); }, false) - this.view.addEventListener('webglcontextrestored', function(event) { scope.handleContextRestored(event); }, false) - - this.batchs = []; - - try - { - PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { - alpha: this.transparent, - antialias:!!antialias, // SPEED UP?? - premultipliedAlpha:false, - stencil:true - }); - } - catch (e) - { - throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); - } - - PIXI.initDefaultShader(); - PIXI.initPrimitiveShader(); - PIXI.initDefaultStripShader(); - - -// PIXI.activateDefaultShader(); - - var gl = this.gl; - PIXI.WebGLRenderer.gl = gl; - - this.batch = new PIXI.WebGLBatch(gl); - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - - gl.enable(gl.BLEND); - gl.colorMask(true, true, true, this.transparent); - - PIXI.projection = new PIXI.Point(400, 300); - - this.resize(this.width, this.height); - this.contextLost = false; - - PIXI.activateShader(PIXI.defaultShader); - - this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); - -} - -// constructor -PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; - -/** - * Gets a new WebGLBatch from the pool - * - * @static - * @method getBatch - * @return {WebGLBatch} - * @private - */ -PIXI.WebGLRenderer.getBatch = function() -{ - if(PIXI._batchs.length == 0) - { - return new PIXI.WebGLBatch(PIXI.WebGLRenderer.gl); - } - else - { - return PIXI._batchs.pop(); - } -} - -/** - * Puts a batch back into the pool - * - * @static - * @method returnBatch - * @param batch {WebGLBatch} The batch to return - * @private - */ -PIXI.WebGLRenderer.returnBatch = function(batch) -{ - batch.clean(); - PIXI._batchs.push(batch); -} - -/** - * Renders the stage to its webGL view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.WebGLRenderer.prototype.render = function(stage) -{ - if(this.contextLost)return; - - - // if rendering a new stage clear the batchs.. - if(this.__stage !== stage) - { - // TODO make this work - // dont think this is needed any more? - this.__stage = stage; - this.stageRenderGroup.setRenderable(stage); - } - - // TODO not needed now... - // update children if need be - // best to remove first! - /*for (var i=0; i < stage.__childrenRemoved.length; i++) - { - var group = stage.__childrenRemoved[i].__renderGroup - if(group)group.removeDisplayObject(stage.__childrenRemoved[i]); - }*/ - - // update any textures - PIXI.WebGLRenderer.updateTextures(); - - // update the scene graph - PIXI.visibleCount++; - stage.updateTransform(); - - var gl = this.gl; - - // -- Does this need to be set every frame? -- // - gl.colorMask(true, true, true, this.transparent); - gl.viewport(0, 0, this.width, this.height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); - gl.clear(gl.COLOR_BUFFER_BIT); - - // HACK TO TEST - - this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; - this.stageRenderGroup.render(PIXI.projection); - - // interaction - // run interaction! - if(stage.interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - - // after rendering lets confirm all frames that have been uodated.. - if(PIXI.Texture.frameUpdates.length > 0) - { - for (var i=0; i < PIXI.Texture.frameUpdates.length; i++) - { - PIXI.Texture.frameUpdates[i].updateFrame = false; - }; - - PIXI.Texture.frameUpdates = []; - } -} - -/** - * Updates the textures loaded into this webgl renderer - * - * @static - * @method updateTextures - * @private - */ -PIXI.WebGLRenderer.updateTextures = function() -{ - //TODO break this out into a texture manager... - for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); - PIXI.texturesToUpdate = []; - PIXI.texturesToDestroy = []; -} - -/** - * Updates a loaded webgl texture - * - * @static - * @method updateTexture - * @param texture {Texture} The texture to update - * @private - */ -PIXI.WebGLRenderer.updateTexture = function(texture) -{ - //TODO break this out into a texture manager... - var gl = PIXI.gl; - - if(!texture._glTexture) - { - texture._glTexture = gl.createTexture(); - } - - if(texture.hasLoaded) - { - gl.bindTexture(gl.TEXTURE_2D, texture._glTexture); - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - - // reguler... - - if(!texture._powerOf2) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - } - - gl.bindTexture(gl.TEXTURE_2D, null); - } -} - -/** - * Destroys a loaded webgl texture - * - * @method destroyTexture - * @param texture {Texture} The texture to update - * @private - */ -PIXI.WebGLRenderer.destroyTexture = function(texture) -{ - //TODO break this out into a texture manager... - var gl = PIXI.gl; - - if(texture._glTexture) - { - texture._glTexture = gl.createTexture(); - gl.deleteTexture(gl.TEXTURE_2D, texture._glTexture); - } -} - -/** - * resizes the webGL view to the specified width and height - * - * @method resize - * @param width {Number} the new width of the webGL view - * @param height {Number} the new height of the webGL view - */ -PIXI.WebGLRenderer.prototype.resize = function(width, height) -{ - this.width = width; - this.height = height; - - this.view.width = width; - this.view.height = height; - - this.gl.viewport(0, 0, this.width, this.height); - - //var projectionMatrix = this.projectionMatrix; - - PIXI.projection.x = this.width/2; - PIXI.projection.y = this.height/2; - -// projectionMatrix[0] = 2/this.width; -// projectionMatrix[5] = -2/this.height; -// projectionMatrix[12] = -1; -// projectionMatrix[13] = 1; -} - -/** - * Handles a lost webgl context - * - * @method handleContextLost - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextLost = function(event) -{ - event.preventDefault(); - this.contextLost = true; -} - -/** - * Handles a restored webgl context - * - * @method handleContextRestored - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextRestored = function(event) -{ - this.gl = this.view.getContext("experimental-webgl", { - alpha: true - }); - - this.initShaders(); - - for(var key in PIXI.TextureCache) - { - var texture = PIXI.TextureCache[key].baseTexture; - texture._glTexture = null; - PIXI.WebGLRenderer.updateTexture(texture); - }; - - for (var i=0; i < this.batchs.length; i++) - { - this.batchs[i].restoreLostContext(this.gl)// - this.batchs[i].dirty = true; - }; - - PIXI._restoreBatchs(this.gl); - - this.contextLost = false; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI._batchs = []; - -/** - * @private - */ -PIXI._getBatch = function(gl) -{ - if(PIXI._batchs.length == 0) - { - return new PIXI.WebGLBatch(gl); - } - else - { - return PIXI._batchs.pop(); - } -} - -/** - * @private - */ -PIXI._returnBatch = function(batch) -{ - batch.clean(); - PIXI._batchs.push(batch); -} - -/** - * @private - */ -PIXI._restoreBatchs = function(gl) -{ - for (var i=0; i < PIXI._batchs.length; i++) - { - PIXI._batchs[i].restoreLostContext(gl); - }; -} - -/** - * A WebGLBatch Enables a group of sprites to be drawn using the same settings. - * if a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch. - * All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites - * in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled - * automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster - * the webGL renderer will run. - * - * @class WebGLBatch - * @constructor - * @param gl {WebGLContext} an instance of the webGL context - */ -PIXI.WebGLBatch = function(gl) -{ - this.gl = gl; - - this.size = 0; - - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); - this.blendMode = PIXI.blendModes.NORMAL; - this.dynamicSize = 1; -} - -// constructor -PIXI.WebGLBatch.prototype.constructor = PIXI.WebGLBatch; - -/** - * Cleans the batch so that is can be returned to an object pool and reused - * - * @method clean - */ -PIXI.WebGLBatch.prototype.clean = function() -{ - this.verticies = []; - this.uvs = []; - this.indices = []; - this.colors = []; - this.dynamicSize = 1; - this.texture = null; - this.last = null; - this.size = 0; - this.head; - this.tail; -} - -/** - * Recreates the buffers in the event of a context loss - * - * @method restoreLostContext - * @param gl {WebGLContext} - */ -PIXI.WebGLBatch.prototype.restoreLostContext = function(gl) -{ - this.gl = gl; - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); -} - -/** - * inits the batch's texture and blend mode based if the supplied sprite - * - * @method init - * @param sprite {Sprite} the first sprite to be added to the batch. Only sprites with - * the same base texture and blend mode will be allowed to be added to this batch - */ -PIXI.WebGLBatch.prototype.init = function(sprite) -{ - sprite.batch = this; - this.dirty = true; - this.blendMode = sprite.blendMode; - this.texture = sprite.texture.baseTexture; - this.head = sprite; - this.tail = sprite; - this.size = 1; - - this.growBatch(); -} - -/** - * inserts a sprite before the specified sprite - * - * @method insertBefore - * @param sprite {Sprite} the sprite to be added - * @param nextSprite {nextSprite} the first sprite will be inserted before this sprite - */ -PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) -{ - this.size++; - - sprite.batch = this; - this.dirty = true; - var tempPrev = nextSprite.__prev; - nextSprite.__prev = sprite; - sprite.__next = nextSprite; - - if(tempPrev) - { - sprite.__prev = tempPrev; - tempPrev.__next = sprite; - } - else - { - this.head = sprite; - } -} - -/** - * inserts a sprite after the specified sprite - * - * @method insertAfter - * @param sprite {Sprite} the sprite to be added - * @param previousSprite {Sprite} the first sprite will be inserted after this sprite - */ -PIXI.WebGLBatch.prototype.insertAfter = function(sprite, previousSprite) -{ - this.size++; - - sprite.batch = this; - this.dirty = true; - - var tempNext = previousSprite.__next; - previousSprite.__next = sprite; - sprite.__prev = previousSprite; - - if(tempNext) - { - sprite.__next = tempNext; - tempNext.__prev = sprite; - } - else - { - this.tail = sprite - } -} - -/** - * removes a sprite from the batch - * - * @method remove - * @param sprite {Sprite} the sprite to be removed - */ -PIXI.WebGLBatch.prototype.remove = function(sprite) -{ - this.size--; - - if(this.size == 0) - { - sprite.batch = null; - sprite.__prev = null; - sprite.__next = null; - return; - } - - if(sprite.__prev) - { - sprite.__prev.__next = sprite.__next; - } - else - { - this.head = sprite.__next; - this.head.__prev = null; - } - - if(sprite.__next) - { - sprite.__next.__prev = sprite.__prev; - } - else - { - this.tail = sprite.__prev; - this.tail.__next = null - } - - sprite.batch = null; - sprite.__next = null; - sprite.__prev = null; - this.dirty = true; -} - -/** - * Splits the batch into two with the specified sprite being the start of the new batch. - * - * @method split - * @param sprite {Sprite} the sprite that indicates where the batch should be split - * @return {WebGLBatch} the new batch - */ -PIXI.WebGLBatch.prototype.split = function(sprite) -{ - this.dirty = true; - - var batch = new PIXI.WebGLBatch(this.gl); - batch.init(sprite); - batch.texture = this.texture; - batch.tail = this.tail; - - this.tail = sprite.__prev; - this.tail.__next = null; - - sprite.__prev = null; - // return a splite batch! - - // TODO this size is wrong! - // need to recalculate :/ problem with a linked list! - // unless it gets calculated in the "clean"? - - // need to loop through items as there is no way to know the length on a linked list :/ - var tempSize = 0; - while(sprite) - { - tempSize++; - sprite.batch = batch; - sprite = sprite.__next; - } - - batch.size = tempSize; - this.size -= tempSize; - - return batch; -} - -/** - * Merges two batchs together - * - * @method merge - * @param batch {WebGLBatch} the batch that will be merged - */ -PIXI.WebGLBatch.prototype.merge = function(batch) -{ - this.dirty = true; - - this.tail.__next = batch.head; - batch.head.__prev = this.tail; - - this.size += batch.size; - - this.tail = batch.tail; - - var sprite = batch.head; - while(sprite) - { - sprite.batch = this; - sprite = sprite.__next; - } -} - -/** - * Grows the size of the batch. As the elements in the batch cannot have a dynamic size this - * function is used to increase the size of the batch. It also creates a little extra room so - * that the batch does not need to be resized every time a sprite is added - * - * @method growBatch - */ -PIXI.WebGLBatch.prototype.growBatch = function() -{ - var gl = this.gl; - if( this.size == 1) - { - this.dynamicSize = 1; - } - else - { - this.dynamicSize = this.size * 1.5 - } - // grow verts - this.verticies = new Float32Array(this.dynamicSize * 8); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); - - this.uvs = new Float32Array( this.dynamicSize * 8 ); - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); - - this.dirtyUVS = true; - - this.colors = new Float32Array( this.dynamicSize * 4 ); - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); - - this.dirtyColors = true; - - this.indices = new Uint16Array(this.dynamicSize * 6); - var length = this.indices.length/6; - - for (var i=0; i < length; i++) - { - var index2 = i * 6; - var index3 = i * 4; - this.indices[index2 + 0] = index3 + 0; - this.indices[index2 + 1] = index3 + 1; - this.indices[index2 + 2] = index3 + 2; - this.indices[index2 + 3] = index3 + 0; - this.indices[index2 + 4] = index3 + 2; - this.indices[index2 + 5] = index3 + 3; - }; - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); -} - -/** - * Refresh's all the data in the batch and sync's it with the webGL buffers - * - * @method refresh - */ -PIXI.WebGLBatch.prototype.refresh = function() -{ - var gl = this.gl; - - if (this.dynamicSize < this.size) - { - this.growBatch(); - } - - var indexRun = 0; - var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index; - var a, b, c, d, tx, ty; - - var displayObject = this.head; - - while(displayObject) - { - index = indexRun * 8; - - var texture = displayObject.texture; - - var frame = texture.frame; - var tw = texture.baseTexture.width; - var th = texture.baseTexture.height; - - this.uvs[index + 0] = frame.x / tw; - this.uvs[index +1] = frame.y / th; - - this.uvs[index +2] = (frame.x + frame.width) / tw; - this.uvs[index +3] = frame.y / th; - - this.uvs[index +4] = (frame.x + frame.width) / tw; - this.uvs[index +5] = (frame.y + frame.height) / th; - - this.uvs[index +6] = frame.x / tw; - this.uvs[index +7] = (frame.y + frame.height) / th; - - displayObject.updateFrame = false; - - colorIndex = indexRun * 4; - this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; - - displayObject = displayObject.__next; - - indexRun ++; - } - - this.dirtyUVS = true; - this.dirtyColors = true; -} - -/** - * Updates all the relevant geometry and uploads the data to the GPU - * - * @method update - */ -PIXI.WebGLBatch.prototype.update = function() -{ - var gl = this.gl; - var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index, index2, index3 - - var a, b, c, d, tx, ty; - - var indexRun = 0; - - var displayObject = this.head; - - while(displayObject) - { - if(displayObject.vcount === PIXI.visibleCount) - { - width = displayObject.texture.frame.width; - height = displayObject.texture.frame.height; - - // TODO trim?? - aX = displayObject.anchor.x;// - displayObject.texture.trim.x - aY = displayObject.anchor.y; //- displayObject.texture.trim.y - w0 = width * (1-aX); - w1 = width * -aX; - - h0 = height * (1-aY); - h1 = height * -aY; - - index = indexRun * 8; - - worldTransform = displayObject.worldTransform; - - a = worldTransform[0]; - b = worldTransform[3]; - c = worldTransform[1]; - d = worldTransform[4]; - tx = worldTransform[2]; - ty = worldTransform[5]; - - this.verticies[index + 0 ] = a * w1 + c * h1 + tx; - this.verticies[index + 1 ] = d * h1 + b * w1 + ty; - - this.verticies[index + 2 ] = a * w0 + c * h1 + tx; - this.verticies[index + 3 ] = d * h1 + b * w0 + ty; - - this.verticies[index + 4 ] = a * w0 + c * h0 + tx; - this.verticies[index + 5 ] = d * h0 + b * w0 + ty; - - this.verticies[index + 6] = a * w1 + c * h0 + tx; - this.verticies[index + 7] = d * h0 + b * w1 + ty; - - if(displayObject.updateFrame || displayObject.texture.updateFrame) - { - this.dirtyUVS = true; - - var texture = displayObject.texture; - - var frame = texture.frame; - var tw = texture.baseTexture.width; - var th = texture.baseTexture.height; - - this.uvs[index + 0] = frame.x / tw; - this.uvs[index +1] = frame.y / th; - - this.uvs[index +2] = (frame.x + frame.width) / tw; - this.uvs[index +3] = frame.y / th; - - this.uvs[index +4] = (frame.x + frame.width) / tw; - this.uvs[index +5] = (frame.y + frame.height) / th; - - this.uvs[index +6] = frame.x / tw; - this.uvs[index +7] = (frame.y + frame.height) / th; - - displayObject.updateFrame = false; - } - - // TODO this probably could do with some optimisation.... - if(displayObject.cacheAlpha != displayObject.worldAlpha) - { - displayObject.cacheAlpha = displayObject.worldAlpha; - - var colorIndex = indexRun * 4; - this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; - this.dirtyColors = true; - } - } - else - { - index = indexRun * 8; - - this.verticies[index + 0 ] = 0; - this.verticies[index + 1 ] = 0; - - this.verticies[index + 2 ] = 0; - this.verticies[index + 3 ] = 0; - - this.verticies[index + 4 ] = 0; - this.verticies[index + 5 ] = 0; - - this.verticies[index + 6] = 0; - this.verticies[index + 7] = 0; - } - - indexRun++; - displayObject = displayObject.__next; - } -} - -/** - * Draws the batch to the frame buffer - * - * @method render - */ -PIXI.WebGLBatch.prototype.render = function(start, end) -{ - start = start || 0; - - if(end == undefined)end = this.size; - - if(this.dirty) - { - this.refresh(); - this.dirty = false; - } - - if (this.size == 0)return; - - this.update(); - var gl = this.gl; - - //TODO optimize this! - - var shaderProgram = PIXI.currentShader; - - //gl.useProgram(shaderProgram); - - // update the verts.. - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - // ok.. - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - // update the uvs - var isDefault = (shaderProgram == PIXI.shaderProgram) - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - - if(this.dirtyUVS) - { - this.dirtyUVS = false; - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvs); - } - - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this.texture._glTexture); - - // update color! - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - - if(this.dirtyColors) - { - this.dirtyColors = false; - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.colors); - } - - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - var len = end - start; - - // DRAW THAT this! - gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A WebGLBatch Enables a group of sprites to be drawn using the same settings. - * if a group of sprites all have the same baseTexture and blendMode then they can be - * grouped into a batch. All the sprites in a batch can then be drawn in one go by the - * GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch - * even if the batch only contains one sprite. Batching is handled automatically by the - * webGL renderer. A good tip is: the smaller the number of batchs there are, the faster - * the webGL renderer will run. - * - * @class WebGLBatch - * @contructor - * @param gl {WebGLContext} An instance of the webGL context - */ -PIXI.WebGLRenderGroup = function(gl) -{ - this.gl = gl; - this.root; - - this.backgroundColor; - this.batchs = []; - this.toRemove = []; -} - -// constructor -PIXI.WebGLRenderGroup.prototype.constructor = PIXI.WebGLRenderGroup; - -/** - * Add a display object to the webgl renderer - * - * @method setRenderable - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.setRenderable = function(displayObject) -{ - // has this changed?? - if(this.root)this.removeDisplayObjectAndChildren(this.root); - - displayObject.worldVisible = displayObject.visible; - - // soooooo // - // to check if any batchs exist already?? - - // TODO what if its already has an object? should remove it - this.root = displayObject; - this.addDisplayObjectAndChildren(displayObject); -} - -/** - * Renders the stage to its webgl view - * - * @method render - * @param projection {Object} - */ -PIXI.WebGLRenderGroup.prototype.render = function(projection) -{ - PIXI.WebGLRenderer.updateTextures(); - - var gl = this.gl; - - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - // will render all the elements in the group - var renderable; - for (var i=0; i < this.batchs.length; i++) - { - - renderable = this.batchs[i]; - if(renderable instanceof PIXI.WebGLBatch) - { - this.batchs[i].render(); - continue; - } - - // non sprite batch.. - var worldVisible = renderable.vcount === PIXI.visibleCount; - - if(renderable instanceof PIXI.TilingSprite) - { - if(worldVisible)this.renderTilingSprite(renderable, projection); - } - else if(renderable instanceof PIXI.Strip) - { - if(worldVisible)this.renderStrip(renderable, projection); - } - else if(renderable instanceof PIXI.Graphics) - { - if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); - } - else if(renderable instanceof PIXI.FilterBlock) - { - this.handleFilterBlock(renderable, projection); - } - } - -} - -/** - * Renders a specific displayObject - * - * @method renderSpecific - * @param displayObject {DisplayObject} - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection) -{ - PIXI.WebGLRenderer.updateTextures(); - - var gl = this.gl; - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - - // to do! - // render part of the scene... - - var startIndex; - var startBatchIndex; - - var endIndex; - var endBatchIndex; - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.first; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - var startBatch = nextRenderable.batch; - - if(nextRenderable instanceof PIXI.Sprite) - { - startBatch = nextRenderable.batch; - - var head = startBatch.head; - var next = head; - - // ok now we have the batch.. need to find the start index! - if(head == nextRenderable) - { - startIndex = 0; - } - else - { - startIndex = 1; - - while(head.__next != nextRenderable) - { - startIndex++; - head = head.__next; - } - } - } - else - { - startBatch = nextRenderable; - } - - // Get the LAST renderable object - var lastRenderable = displayObject; - var endBatch; - var lastItem = displayObject; - while(lastItem.children.length > 0) - { - lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem.last; - } - - if(lastRenderable instanceof PIXI.Sprite) - { - endBatch = lastRenderable.batch; - - var head = endBatch.head; - - if(head == lastRenderable) - { - endIndex = 0; - } - else - { - endIndex = 1; - - while(head.__next != lastRenderable) - { - endIndex++; - head = head.__next; - } - } - } - else - { - endBatch = lastRenderable; - } - - // TODO - need to fold this up a bit! - - if(startBatch == endBatch) - { - if(startBatch instanceof PIXI.WebGLBatch) - { - startBatch.render(startIndex, endIndex+1); - } - else - { - this.renderSpecial(startBatch, projection); - } - return; - } - - // now we have first and last! - startBatchIndex = this.batchs.indexOf(startBatch); - endBatchIndex = this.batchs.indexOf(endBatch); - - // DO the first batch - if(startBatch instanceof PIXI.WebGLBatch) - { - startBatch.render(startIndex); - } - else - { - this.renderSpecial(startBatch, projection); - } - - // DO the middle batchs.. - for (var i=startBatchIndex+1; i < endBatchIndex; i++) - { - renderable = this.batchs[i]; - - if(renderable instanceof PIXI.WebGLBatch) - { - this.batchs[i].render(); - } - else - { - this.renderSpecial(renderable, projection); - } - } - - // DO the last batch.. - if(endBatch instanceof PIXI.WebGLBatch) - { - endBatch.render(0, endIndex+1); - } - else - { - this.renderSpecial(endBatch, projection); - } -} - -/** - * Renders a specific renderable - * - * @method renderSpecial - * @param renderable {DisplayObject} - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) -{ - var sta = PIXI.shaderStack.length; - - var worldVisible = renderable.vcount === PIXI.visibleCount - - if(renderable instanceof PIXI.TilingSprite) - { - if(worldVisible)this.renderTilingSprite(renderable, projection); - } - else if(renderable instanceof PIXI.Strip) - { - if(worldVisible)this.renderStrip(renderable, projection); - } - else if(renderable instanceof PIXI.CustomRenderable) - { - if(worldVisible) renderable.renderWebGL(this, projection); - } - else if(renderable instanceof PIXI.Graphics) - { - if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); - } - else if(renderable instanceof PIXI.FilterBlock) - { - this.handleFilterBlock(renderable, projection); - } -} - -PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) -{ - /* - * for now only masks are supported.. - */ - var gl = PIXI.gl; - - if(renderable.open) - { - if(renderable.data instanceof Array) - { - var filter = renderable.data[0]; - - if(!filter.shader) - { - var shader = new PIXI.PixiShader(); - - shader.fragmentSrc = filter.fragmentSrc; - shader.uniforms = filter.uniforms; - shader.init(); - - filter.shader = shader - } - - PIXI.activateShader(filter.shader); - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - } - else - { - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); - - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - } - else - { - if(renderable.data instanceof Array) - { - PIXI.popShader(); - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - } - else - { - gl.disable(gl.STENCIL_TEST); - } - } -} - -/** - * Updates a webgl texture - * - * @method updateTexture - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject) -{ - - // TODO definitely can optimse this function.. - - this.removeObject(displayObject); - - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - var previousRenderable = displayObject.first; - while(previousRenderable != this.root) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.last; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - - this.insertObject(displayObject, previousRenderable, nextRenderable); -} - -/** - * Adds filter blocks - * - * @method addFilterBlocks - * @param start {FilterBlock} - * @param end {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) -{ - start.__renderGroup = this; - end.__renderGroup = this; - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - var previousRenderable = start; - while(previousRenderable != this.root.first) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - this.insertAfter(start, previousRenderable); - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var previousRenderable2 = end; - while(previousRenderable2 != this.root.first) - { - previousRenderable2 = previousRenderable2._iPrev; - if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; - } - this.insertAfter(end, previousRenderable2); -} - -/** - * Remove filter blocks - * - * @method removeFilterBlocks - * @param start {FilterBlock} - * @param end {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeFilterBlocks = function(start, end) -{ - this.removeObject(start); - this.removeObject(end); -} - -/** - * Adds a display object and children to the webgl context - * - * @method addDisplayObjectAndChildren - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayObject) -{ - if(displayObject.__renderGroup)displayObject.__renderGroup.removeDisplayObjectAndChildren(displayObject); - - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - - var previousRenderable = displayObject.first; - while(previousRenderable != this.root.first) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.last; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - - // one the display object hits this. we can break the loop - - var tempObject = displayObject.first; - var testObject = displayObject.last._iNext; - do - { - tempObject.__renderGroup = this; - - if(tempObject.renderable) - { - - this.insertObject(tempObject, previousRenderable, nextRenderable); - previousRenderable = tempObject; - } - - tempObject = tempObject._iNext; - } - while(tempObject != testObject) -} - -/** - * Removes a display object and children to the webgl context - * - * @method removeDisplayObjectAndChildren - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren = function(displayObject) -{ - if(displayObject.__renderGroup != this)return; - -// var displayObject = displayObject.first; - var lastObject = displayObject.last; - do - { - displayObject.__renderGroup = null; - if(displayObject.renderable)this.removeObject(displayObject); - displayObject = displayObject._iNext; - } - while(displayObject) -} - -/** - * Inserts a displayObject into the linked list - * - * @method insertObject - * @param displayObject {DisplayObject} - * @param previousObject {DisplayObject} - * @param nextObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousObject, nextObject) -{ - // while looping below THE OBJECT MAY NOT HAVE BEEN ADDED - var previousSprite = previousObject; - var nextSprite = nextObject; - - /* - * so now we have the next renderable and the previous renderable - * - */ - if(displayObject instanceof PIXI.Sprite) - { - var previousBatch - var nextBatch - - if(previousSprite instanceof PIXI.Sprite) - { - previousBatch = previousSprite.batch; - if(previousBatch) - { - if(previousBatch.texture == displayObject.texture.baseTexture && previousBatch.blendMode == displayObject.blendMode) - { - previousBatch.insertAfter(displayObject, previousSprite); - return; - } - } - } - else - { - // TODO reword! - previousBatch = previousSprite; - } - - if(nextSprite) - { - if(nextSprite instanceof PIXI.Sprite) - { - nextBatch = nextSprite.batch; - - //batch may not exist if item was added to the display list but not to the webGL - if(nextBatch) - { - if(nextBatch.texture == displayObject.texture.baseTexture && nextBatch.blendMode == displayObject.blendMode) - { - nextBatch.insertBefore(displayObject, nextSprite); - return; - } - else - { - if(nextBatch == previousBatch) - { - // THERE IS A SPLIT IN THIS BATCH! // - var splitBatch = previousBatch.split(nextSprite); - // COOL! - // add it back into the array - /* - * OOPS! - * seems the new sprite is in the middle of a batch - * lets split it.. - */ - var batch = PIXI.WebGLRenderer.getBatch(); - - var index = this.batchs.indexOf( previousBatch ); - batch.init(displayObject); - this.batchs.splice(index+1, 0, batch, splitBatch); - - return; - } - } - } - } - else - { - // TODO re-word! - - nextBatch = nextSprite; - } - } - - /* - * looks like it does not belong to any batch! - * but is also not intersecting one.. - * time to create anew one! - */ - - var batch = PIXI.WebGLRenderer.getBatch(); - batch.init(displayObject); - - if(previousBatch) // if this is invalid it means - { - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, batch); - } - else - { - this.batchs.push(batch); - } - - return; - } - else if(displayObject instanceof PIXI.TilingSprite) - { - - // add to a batch!! - this.initTilingSprite(displayObject); - // this.batchs.push(displayObject); - - } - else if(displayObject instanceof PIXI.Strip) - { - // add to a batch!! - this.initStrip(displayObject); - // this.batchs.push(displayObject); - } - else if(displayObject)// instanceof PIXI.Graphics) - { - //displayObject.initWebGL(this); - - // add to a batch!! - //this.initStrip(displayObject); - //this.batchs.push(displayObject); - } - - this.insertAfter(displayObject, previousSprite); - - // insert and SPLIT! - -} - -/** - * Inserts a displayObject into the linked list - * - * @method insertAfter - * @param item {DisplayObject} - * @param displayObject {DisplayObject} The object to insert - * @private - */ -PIXI.WebGLRenderGroup.prototype.insertAfter = function(item, displayObject) -{ - if(displayObject instanceof PIXI.Sprite) - { - var previousBatch = displayObject.batch; - - if(previousBatch) - { - // so this object is in a batch! - - // is it not? need to split the batch - if(previousBatch.tail == displayObject) - { - // is it tail? insert in to batchs - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, item); - } - else - { - // TODO MODIFY ADD / REMOVE CHILD TO ACCOUNT FOR FILTERS (also get prev and next) // - - // THERE IS A SPLIT IN THIS BATCH! // - var splitBatch = previousBatch.split(displayObject.__next); - - // COOL! - // add it back into the array - /* - * OOPS! - * seems the new sprite is in the middle of a batch - * lets split it.. - */ - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, item, splitBatch); - } - } - else - { - this.batchs.push(item); - } - } - else - { - var index = this.batchs.indexOf( displayObject ); - this.batchs.splice(index+1, 0, item); - } -} - -/** - * Removes a displayObject from the linked list - * - * @method removeObject - * @param displayObject {DisplayObject} The object to remove - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) -{ - // loop through children.. - // display object // - - // add a child from the render group.. - // remove it and all its children! - //displayObject.cacheVisible = false;//displayObject.visible; - - /* - * removing is a lot quicker.. - * - */ - var batchToRemove; - - if(displayObject instanceof PIXI.Sprite) - { - // should always have a batch! - var batch = displayObject.batch; - if(!batch)return; // this means the display list has been altered befre rendering - - batch.remove(displayObject); - - if(batch.size==0) - { - batchToRemove = batch; - } - } - else - { - batchToRemove = displayObject; - } - - /* - * Looks like there is somthing that needs removing! - */ - if(batchToRemove) - { - var index = this.batchs.indexOf( batchToRemove ); - if(index == -1)return;// this means it was added then removed before rendered - - // ok so.. check to see if you adjacent batchs should be joined. - // TODO may optimise? - if(index == 0 || index == this.batchs.length-1) - { - // wha - eva! just get of the empty batch! - this.batchs.splice(index, 1); - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - - return; - } - - if(this.batchs[index-1] instanceof PIXI.WebGLBatch && this.batchs[index+1] instanceof PIXI.WebGLBatch) - { - if(this.batchs[index-1].texture == this.batchs[index+1].texture && this.batchs[index-1].blendMode == this.batchs[index+1].blendMode) - { - //console.log("MERGE") - this.batchs[index-1].merge(this.batchs[index+1]); - - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - PIXI.WebGLRenderer.returnBatch(this.batchs[index+1]); - this.batchs.splice(index, 2); - return; - } - } - - this.batchs.splice(index, 1); - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - } -} - - -/** - * Initializes a tiling sprite - * - * @method initTilingSprite - * @param sprite {TilingSprite} The tiling sprite to initialize - * @private - */ -PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) -{ - var gl = this.gl; - - // make the texture tilable.. - - sprite.verticies = new Float32Array([0, 0, - sprite.width, 0, - sprite.width, sprite.height, - 0, sprite.height]); - - sprite.uvs = new Float32Array([0, 0, - 1, 0, - 1, 1, - 0, 1]); - - sprite.colors = new Float32Array([1,1,1,1]); - - sprite.indices = new Uint16Array([0, 1, 3,2])//, 2]); - - sprite._vertexBuffer = gl.createBuffer(); - sprite._indexBuffer = gl.createBuffer(); - sprite._uvBuffer = gl.createBuffer(); - sprite._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.verticies, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.uvs, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.colors, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sprite._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sprite.indices, gl.STATIC_DRAW); - -// return ( (x > 0) && ((x & (x - 1)) == 0) ); - - if(sprite.texture.baseTexture._glTexture) - { - gl.bindTexture(gl.TEXTURE_2D, sprite.texture.baseTexture._glTexture); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - sprite.texture.baseTexture._powerOf2 = true; - } - else - { - sprite.texture.baseTexture._powerOf2 = true; - } -} - -/** - * Renders a Strip - * - * @method renderStrip - * @param strip {Strip} The strip to render - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) -{ - var gl = this.gl; - var shaderProgram = PIXI.stripShaderProgram; - - - gl.useProgram(shaderProgram); - - var m = PIXI.mat3.clone(strip.worldTransform); - - PIXI.mat3.transpose(m); - - // set the matrix transform for the - gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); - gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); - -/* - if(strip.blendMode == PIXI.blendModes.NORMAL) - { - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - } - else - { - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR); - } - */ - - - if(!strip.dirty) - { - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, strip.verticies) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - } - else - { - strip.dirty = false; - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); - - } - - gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - - gl.useProgram(PIXI.currentProgram); -} - -/** - * Renders a TilingSprite - * - * @method renderTilingSprite - * @param sprite {TilingSprite} The tiling sprite to render - * @param projectionMatrix {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderTilingSprite = function(sprite, projectionMatrix) -{ - var gl = this.gl; - var shaderProgram = PIXI.shaderProgram; - - var tilePosition = sprite.tilePosition; - var tileScale = sprite.tileScale; - - var offsetX = tilePosition.x/sprite.texture.baseTexture.width; - var offsetY = tilePosition.y/sprite.texture.baseTexture.height; - - var scaleX = (sprite.width / sprite.texture.baseTexture.width) / tileScale.x; - var scaleY = (sprite.height / sprite.texture.baseTexture.height) / tileScale.y; - - sprite.uvs[0] = 0 - offsetX; - sprite.uvs[1] = 0 - offsetY; - - sprite.uvs[2] = (1 * scaleX) -offsetX; - sprite.uvs[3] = 0 - offsetY; - - sprite.uvs[4] = (1 *scaleX) - offsetX; - sprite.uvs[5] = (1 *scaleY) - offsetY; - - sprite.uvs[6] = 0 - offsetX; - sprite.uvs[7] = (1 *scaleY) - offsetY; - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, sprite.uvs) - - this.renderStrip(sprite, projectionMatrix); -} - -/** - * Initializes a strip to be rendered - * - * @method initStrip - * @param strip {Strip} The strip to initialize - * @private - */ -PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) -{ - // build the strip! - var gl = this.gl; - var shaderProgram = this.shaderProgram; - - strip._vertexBuffer = gl.createBuffer(); - strip._indexBuffer = gl.createBuffer(); - strip._uvBuffer = gl.createBuffer(); - strip._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW); - - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * the CanvasRenderer draws the stage and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. - * Dont forget to add the view to your DOM or you will not see anything :) - * - * @class CanvasRenderer - * @constructor - * @param width=0 {Number} the width of the canvas view - * @param height=0 {Number} the height of the canvas view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - */ -PIXI.CanvasRenderer = function(width, height, view, transparent) -{ - this.transparent = transparent; - - /** - * The width of the canvas view - * - * @property width - * @type Number - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @property height - * @type Number - * @default 600 - */ - this.height = height || 600; - - /** - * The canvas element that the everything is drawn to - * - * @property view - * @type Canvas - */ - this.view = view || document.createElement( 'canvas' ); - - /** - * The canvas context that the everything is drawn to - * @property context - * @type Canvas 2d Context - */ - this.context = this.view.getContext("2d"); - - this.refresh = true; - // hack to enable some hardware acceleration! - //this.view.style["transform"] = "translatez(0)"; - - this.view.width = this.width; - this.view.height = this.height; - this.count = 0; -} - -// constructor -PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; - -/** - * Renders the stage to its canvas view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.CanvasRenderer.prototype.render = function(stage) -{ - - //stage.__childrenAdded = []; - //stage.__childrenRemoved = []; - - // update textures if need be - PIXI.texturesToUpdate = []; - PIXI.texturesToDestroy = []; - - PIXI.visibleCount++; - stage.updateTransform(); - - // update the background color - if(this.view.style.backgroundColor!=stage.backgroundColorString && !this.transparent)this.view.style.backgroundColor = stage.backgroundColorString; - - this.context.setTransform(1,0,0,1,0,0); - this.context.clearRect(0, 0, this.width, this.height) - this.renderDisplayObject(stage); - //as - - // run interaction! - if(stage.interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - - // remove frame updates.. - if(PIXI.Texture.frameUpdates.length > 0) - { - PIXI.Texture.frameUpdates = []; - } - - -} - -/** - * resizes the canvas view to the specified width and height - * - * @method resize - * @param width {Number} the new width of the canvas view - * @param height {Number} the new height of the canvas view - */ -PIXI.CanvasRenderer.prototype.resize = function(width, height) -{ - this.width = width; - this.height = height; - - this.view.width = width; - this.view.height = height; -} - -/** - * Renders a display object - * - * @method renderDisplayObject - * @param displayObject {DisplayObject} The displayObject to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) -{ - // no loger recurrsive! - var transform; - var context = this.context; - - context.globalCompositeOperation = 'source-over'; - - // one the display object hits this. we can break the loop - var testObject = displayObject.last._iNext; - displayObject = displayObject.first; - - do - { - transform = displayObject.worldTransform; - - if(!displayObject.visible) - { - displayObject = displayObject.last._iNext; - continue; - } - - if(!displayObject.renderable) - { - displayObject = displayObject._iNext; - continue; - } - - if(displayObject instanceof PIXI.Sprite) - { - - var frame = displayObject.texture.frame; - - if(frame && frame.width && frame.height) - { - context.globalAlpha = displayObject.worldAlpha; - - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); - - context.drawImage(displayObject.texture.baseTexture.source, - frame.x, - frame.y, - frame.width, - frame.height, - (displayObject.anchor.x) * -frame.width, - (displayObject.anchor.y) * -frame.height, - frame.width, - frame.height); - } - } - else if(displayObject instanceof PIXI.Strip) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - this.renderStrip(displayObject); - } - else if(displayObject instanceof PIXI.TilingSprite) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - this.renderTilingSprite(displayObject); - } - else if(displayObject instanceof PIXI.CustomRenderable) - { - displayObject.renderCanvas(this); - } - else if(displayObject instanceof PIXI.Graphics) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - PIXI.CanvasGraphics.renderGraphics(displayObject, context); - } - else if(displayObject instanceof PIXI.FilterBlock) - { - if(PIXI.FilterBlock.data instanceof PIXI.Graphics) - { - if(displayObject.open) - { - context.save(); - - var cacheAlpha = displayObject.mask.alpha; - var maskTransform = displayObject.mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - displayObject.mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); - context.clip(); - - displayObject.mask.worldAlpha = cacheAlpha; - } - else - { - context.restore(); - } - } - else - { - // only masks supported right now! - } - } - // count++ - displayObject = displayObject._iNext; - - - } - while(displayObject != testObject) - - -} - -/** - * Renders a flat strip - * - * @method renderStripFlat - * @param strip {Strip} The Strip to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip) -{ - var context = this.context; - var verticies = strip.verticies; - var uvs = strip.uvs; - - var length = verticies.length/2; - this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - - // draw some triangles! - var index = i*2; - - var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; - var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - }; - - context.fillStyle = "#FF0000"; - context.fill(); - context.closePath(); -} - -/** - * Renders a tiling sprite - * - * @method renderTilingSprite - * @param sprite {TilingSprite} The tilingsprite to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) -{ - var context = this.context; - - context.globalAlpha = sprite.worldAlpha; - - if(!sprite.__tilePattern) sprite.__tilePattern = context.createPattern(sprite.texture.baseTexture.source, "repeat"); - - context.beginPath(); - - var tilePosition = sprite.tilePosition; - var tileScale = sprite.tileScale; - - // offset - context.scale(tileScale.x,tileScale.y); - context.translate(tilePosition.x, tilePosition.y); - - context.fillStyle = sprite.__tilePattern; - context.fillRect(-tilePosition.x,-tilePosition.y,sprite.width / tileScale.x, sprite.height / tileScale.y); - - context.scale(1/tileScale.x, 1/tileScale.y); - context.translate(-tilePosition.x, -tilePosition.y); - - context.closePath(); -} - -/** - * Renders a strip - * - * @method renderStrip - * @param strip {Strip} The Strip to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderStrip = function(strip) -{ - var context = this.context; - - // draw triangles!! - var verticies = strip.verticies; - var uvs = strip.uvs; - - var length = verticies.length/2; - this.count++; - for (var i=1; i < length-2; i++) - { - - // draw some triangles! - var index = i*2; - - var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; - var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - - var u0 = uvs[index] * strip.texture.width, u1 = uvs[index+2] * strip.texture.width, u2 = uvs[index+4]* strip.texture.width; - var v0 = uvs[index+1]* strip.texture.height, v1 = uvs[index+3] * strip.texture.height, v2 = uvs[index+5]* strip.texture.height; - - - 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 delta_a = x0*v1 + v0*x2 + x1*v2 - v1*x2 - v0*x1 - x0*v2; - var delta_b = u0*x1 + x0*u2 + u1*x2 - x1*u2 - x0*u1 - u0*x2; - var delta_c = u0*v1*x2 + v0*x1*u2 + x0*u1*v2 - x0*v1*u2 - v0*u1*x2 - u0*x1*v2; - var delta_d = y0*v1 + v0*y2 + y1*v2 - v1*y2 - v0*y1 - y0*v2; - var delta_e = u0*y1 + y0*u2 + u1*y2 - y1*u2 - y0*u1 - u0*y2; - var delta_f = u0*v1*y2 + v0*y1*u2 + y0*u1*v2 - y0*v1*u2 - v0*u1*y2 - u0*y1*v2; - - - - - context.transform(delta_a/delta, delta_d/delta, - delta_b/delta, delta_e/delta, - delta_c/delta, delta_f/delta); - - context.drawImage(strip.texture.baseTexture.source, 0, 0); - context.restore(); - }; - -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * A set of functions used by the canvas renderer to draw the primitive graphics data - * - * @class CanvasGraphics - */ -PIXI.CanvasGraphics = function() -{ - -} - - -/* - * Renders the graphics object - * - * @static - * @private - * @method renderGraphics - * @param graphics {Graphics} - * @param context {Context2D} - */ -PIXI.CanvasGraphics.renderGraphics = function(graphics, context) -{ - var worldAlpha = graphics.worldAlpha; - - for (var i=0; i < graphics.graphicsData.length; i++) - { - var data = graphics.graphicsData[i]; - var points = data.points; - - context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); - - context.lineWidth = data.lineWidth; - - if(data.type == PIXI.Graphics.POLY) - { - context.beginPath(); - - context.moveTo(points[0], points[1]); - - for (var j=1; j < points.length/2; j++) - { - context.lineTo(points[j * 2], points[j * 2 + 1]); - } - - // if the first and last point are the same close the path - much neater :) - if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) - { - context.closePath(); - } - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - else if(data.type == PIXI.Graphics.RECT) - { - - if(data.fillColor || data.fillColor === 0) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fillRect(points[0], points[1], points[2], points[3]); - - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.strokeRect(points[0], points[1], points[2], points[3]); - } - - } - else if(data.type == PIXI.Graphics.CIRC) - { - // TODO - need to be Undefined! - context.beginPath(); - context.arc(points[0], points[1], points[2],0,2*Math.PI); - context.closePath(); - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - else if(data.type == PIXI.Graphics.ELIP) - { - - // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - - var elipseData = data.points; - - var w = elipseData[2] * 2; - var h = elipseData[3] * 2; - - var x = elipseData[0] - w/2; - var y = elipseData[1] - h/2; - - context.beginPath(); - - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - - context.moveTo(x, ym); - context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - - context.closePath(); - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - - }; -} - -/* - * Renders a graphics mask - * - * @static - * @private - * @method renderGraphicsMask - * @param graphics {Graphics} - * @param context {Context2D} - */ -PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) -{ - var worldAlpha = graphics.worldAlpha; - - var len = graphics.graphicsData.length; - if(len > 1) - { - len = 1; - console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") - } - - for (var i=0; i < 1; i++) - { - var data = graphics.graphicsData[i]; - var points = data.points; - - if(data.type == PIXI.Graphics.POLY) - { - context.beginPath(); - context.moveTo(points[0], points[1]); - - for (var j=1; j < points.length/2; j++) - { - context.lineTo(points[j * 2], points[j * 2 + 1]); - } - - // if the first and last point are the same close the path - much neater :) - if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) - { - context.closePath(); - } - - } - else if(data.type == PIXI.Graphics.RECT) - { - context.beginPath(); - context.rect(points[0], points[1], points[2], points[3]); - context.closePath(); - } - else if(data.type == PIXI.Graphics.CIRC) - { - // TODO - need to be Undefined! - context.beginPath(); - context.arc(points[0], points[1], points[2],0,2*Math.PI); - context.closePath(); - } - else if(data.type == PIXI.Graphics.ELIP) - { - - // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - var elipseData = data.points; - - var w = elipseData[2] * 2; - var h = elipseData[3] * 2; - - var x = elipseData[0] - w/2; - var y = elipseData[1] - h/2; - - context.beginPath(); - - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - - context.moveTo(x, ym); - context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - context.closePath(); - } - - - }; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. - * It is important to know that with the webGL renderer only simple polys can be filled at this stage - * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png - * - * @class Graphics - * @extends DisplayObjectContainer - * @constructor - */ -PIXI.Graphics = function() -{ - PIXI.DisplayObjectContainer.call( this ); - - this.renderable = true; - - /** - * The alpha of the fill of this graphics object - * - * @property fillAlpha - * @type Number - */ - this.fillAlpha = 1; - - /** - * The width of any lines drawn - * - * @property lineWidth - * @type Number - */ - this.lineWidth = 0; - - /** - * The color of any lines drawn - * - * @property lineColor - * @type String - */ - this.lineColor = "black"; - - /** - * Graphics data - * - * @property graphicsData - * @type Array - * @private - */ - this.graphicsData = []; - - /** - * Current path - * - * @property currentPath - * @type Object - * @private - */ - this.currentPath = {points:[]}; -} - -// constructor -PIXI.Graphics.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Graphics.prototype.constructor = PIXI.Graphics; - -/** - * Specifies a line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method. - * - * @method lineStyle - * @param lineWidth {Number} width of the line to draw, will update the object's stored style - * @param color {Number} color of the line to draw, will update the object's stored style - * @param alpha {Number} alpha of the line to draw, will update the object's stored style - */ -PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.lineWidth = lineWidth || 0; - this.lineColor = color || 0; - this.lineAlpha = (alpha == undefined) ? 1 : alpha; - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - - this.graphicsData.push(this.currentPath); -} - -/** - * Moves the current drawing position to (x, y). - * - * @method moveTo - * @param x {Number} the X coord to move to - * @param y {Number} the Y coord to move to - */ -PIXI.Graphics.prototype.moveTo = function(x, y) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - - this.currentPath.points.push(x, y); - - this.graphicsData.push(this.currentPath); -} - -/** - * Draws a line using the current line style from the current drawing position to (x, y); - * the current drawing position is then set to (x, y). - * - * @method lineTo - * @param x {Number} the X coord to draw to - * @param y {Number} the Y coord to draw to - */ -PIXI.Graphics.prototype.lineTo = function(x, y) -{ - this.currentPath.points.push(x, y); - this.dirty = true; -} - -/** - * Specifies a simple one-color fill that subsequent calls to other Graphics methods - * (such as lineTo() or drawCircle()) use when drawing. - * - * @method beginFill - * @param color {uint} the color of the fill - * @param alpha {Number} the alpha - */ -PIXI.Graphics.prototype.beginFill = function(color, alpha) -{ - this.filling = true; - this.fillColor = color || 0; - this.fillAlpha = (alpha == undefined) ? 1 : alpha; -} - -/** - * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. - * - * @method endFill - */ -PIXI.Graphics.prototype.endFill = function() -{ - this.filling = false; - this.fillColor = null; - this.fillAlpha = 1; -} - -/** - * @method drawRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - */ -PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, width, height], type:PIXI.Graphics.RECT}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Draws a circle. - * - * @method drawCircle - * @param x {Number} The X coord of the center of the circle - * @param y {Number} The Y coord of the center of the circle - * @param radius {Number} The radius of the circle - */ -PIXI.Graphics.prototype.drawCircle = function( x, y, radius) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Draws an elipse. - * - * @method drawElipse - * @param x {Number} - * @param y {Number} - * @param width {Number} - * @param height {Number} - */ -PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, width, height], type:PIXI.Graphics.ELIP}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @method clear - */ -PIXI.Graphics.prototype.clear = function() -{ - this.lineWidth = 0; - this.filling = false; - - this.dirty = true; - this.clearDirty = true; - this.graphicsData = []; -} - -// SOME TYPES: -PIXI.Graphics.POLY = 0; -PIXI.Graphics.RECT = 1; -PIXI.Graphics.CIRC = 2; -PIXI.Graphics.ELIP = 3; - -/** - * @author Mat Groves http://matgroves.com/ - */ - -PIXI.Strip = function(texture, width, height) -{ - PIXI.DisplayObjectContainer.call( this ); - this.texture = texture; - this.blendMode = PIXI.blendModes.NORMAL; - - try - { - this.uvs = new Float32Array([0, 1, - 1, 1, - 1, 0, 0,1]); - - this.verticies = new Float32Array([0, 0, - 0,0, - 0,0, 0, - 0, 0]); - - this.colors = new Float32Array([1, 1, 1, 1]); - - this.indices = new Uint16Array([0, 1, 2, 3]); - } - catch(error) - { - this.uvs = [0, 1, - 1, 1, - 1, 0, 0,1]; - - this.verticies = [0, 0, - 0,0, - 0,0, 0, - 0, 0]; - - this.colors = [1, 1, 1, 1]; - - this.indices = [0, 1, 2, 3]; - } - - - /* - this.uvs = new Float32Array() - this.verticies = new Float32Array() - this.colors = new Float32Array() - this.indices = new Uint16Array() -*/ - this.width = width; - this.height = height; - - // load the texture! - if(texture.baseTexture.hasLoaded) - { - this.width = this.texture.frame.width; - this.height = this.texture.frame.height; - this.updateFrame = true; - } - else - { - this.onTextureUpdateBind = this.onTextureUpdate.bind(this); - this.texture.addEventListener( 'update', this.onTextureUpdateBind ); - } - - this.renderable = true; -} - -// constructor -PIXI.Strip.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Strip.prototype.constructor = PIXI.Strip; - -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; -} - -PIXI.Strip.prototype.onTextureUpdate = function(event) -{ - this.updateFrame = true; -} -// some helper functions.. - - -/** - * @author Mat Groves http://matgroves.com/ - */ - - -PIXI.Rope = function(texture, points) -{ - PIXI.Strip.call( this, texture ); - this.points = points; - - try - { - this.verticies = new Float32Array( points.length * 4); - this.uvs = new Float32Array( points.length * 4); - this.colors = new Float32Array( points.length * 2); - this.indices = new Uint16Array( points.length * 2); - } - catch(error) - { - this.verticies = verticies - - this.uvs = uvs - this.colors = colors - this.indices = indices - } - - this.refresh(); -} - - -// constructor -PIXI.Rope.prototype = Object.create( PIXI.Strip.prototype ); -PIXI.Rope.prototype.constructor = PIXI.Rope; - -PIXI.Rope.prototype.refresh = function() -{ - var points = this.points; - if(points.length < 1)return; - - var uvs = this.uvs - var indices = this.indices; - var colors = this.colors; - - var lastPoint = points[0]; - var nextPoint; - var perp = {x:0, y:0}; - var point = points[0]; - - this.count-=0.2; - - - uvs[0] = 0 - uvs[1] = 1 - uvs[2] = 0 - uvs[3] = 1 - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length; - - for (var i = 1; i < total; i++) - { - - var point = points[i]; - var index = i * 4; - // time to do some smart drawing! - var 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; - } -} - -PIXI.Rope.prototype.updateTransform = function() -{ - - var points = this.points; - if(points.length < 1)return; - - var verticies = this.verticies - - var lastPoint = points[0]; - var nextPoint; - var perp = {x:0, y:0}; - var point = points[0]; - - this.count-=0.2; - - verticies[0] = point.x + perp.x - verticies[1] = point.y + perp.y //+ 200 - verticies[2] = point.x - perp.x - verticies[3] = point.y - perp.y//+200 - // time to do some smart drawing! - - var total = points.length; - - for (var i = 1; i < total; i++) - { - - var point = points[i]; - var 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; - - var ratio = (1 - (i / (total-1))) * 10; - if(ratio > 1)ratio = 1; - - var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); - var 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; - - verticies[index] = point.x + perp.x - verticies[index+1] = point.y + perp.y - verticies[index+2] = point.x - perp.x - verticies[index+3] = point.y - perp.y - - lastPoint = point; - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); -} - -PIXI.Rope.prototype.setTexture = function(texture) -{ - // stop current texture - this.texture = texture; - this.updateFrame = true; -} - - - - - -/** - * @author Mat Groves http://matgroves.com/ - */ - -/** - * A tiling sprite is a fast way of rendering a tiling image - * - * @class TilingSprite - * @extends DisplayObjectContainer - * @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.DisplayObjectContainer.call( this ); - - /** - * The texture that the sprite is using - * - * @property texture - * @type Texture - */ - this.texture = texture; - - /** - * The width of the tiling sprite - * - * @property width - * @type Number - */ - this.width = width; - - /** - * The height of the tiling sprite - * - * @property height - * @type Number - */ - this.height = height; - - /** - * The scaling of the image that is being tiled - * - * @property tileScale - * @type Point - */ - this.tileScale = 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); - - this.renderable = true; - - this.blendMode = PIXI.blendModes.NORMAL -} - -// constructor -PIXI.TilingSprite.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite; - -/** - * Sets the texture of the tiling sprite - * - * @method setTexture - * @param texture {Texture} The PIXI texture that is displayed by the sprite - */ -PIXI.TilingSprite.prototype.setTexture = function(texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - - // stop current texture - this.texture = texture; - this.updateFrame = true; -} - -/** - * When the texture is updated, this event will fire to update the frame - * - * @method onTextureUpdate - * @param event - * @private - */ -PIXI.TilingSprite.prototype.onTextureUpdate = function(event) -{ - this.updateFrame = true; -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * - * Awesome JS run time provided by EsotericSoftware - * https://github.com/EsotericSoftware/spine-runtimes - * - */ - -/** - * 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)) { - continue; - } - var spriteName = attachment.rendererObject.name; - var sprite = this.createSprite(slot, attachment.rendererObject); - slot.currentSprite = sprite; - slot.currentSpriteName = spriteName; - slotContainer.addChild(sprite); - } -}; - -PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); -PIXI.Spine.prototype.constructor = PIXI.Spine; - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.Spine.prototype.updateTransform = function () { - this.lastTime = this.lastTime || Date.now(); - var timeDelta = (Date.now() - this.lastTime) * 0.001; - this.lastTime = Date.now(); - this.state.update(timeDelta); - 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 instanceof spine.RegionAttachment)) { - slotContainer.visible = false; - continue; - } - - 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.rendererObject); - slotContainer.addChild(sprite); - } - slot.currentSprite = slot.sprites[spriteName]; - slot.currentSpriteName = spriteName; - } - } - slotContainer.visible = true; - - 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 * Math.PI / 180); - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -}; - - -PIXI.Spine.prototype.createSprite = function (slot, descriptor) { - var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); - sprite.scale = descriptor.scale; - sprite.rotation = descriptor.rotation; - sprite.anchor.x = sprite.anchor.y = 0.5; - - slot.sprites = slot.sprites || {}; - slot.sprites[descriptor.name] = sprite; - return sprite; -}; - -/* - * Awesome JS run time provided by EsotericSoftware - * - * https://github.com/EsotericSoftware/spine-runtimes - * - */ - -var spine = {}; - -spine.BoneData = function (name, parent) { - this.name = name; - this.parent = parent; -}; -spine.BoneData.prototype = { - length: 0, - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1 -}; - -spine.SlotData = function (name, boneData) { - this.name = name; - this.boneData = boneData; -}; -spine.SlotData.prototype = { - r: 1, g: 1, b: 1, a: 1, - attachmentName: null -}; - -spine.Bone = function (boneData, parent) { - this.data = boneData; - this.parent = parent; - this.setToSetupPose(); -}; -spine.Bone.yDown = false; -spine.Bone.prototype = { - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1, - m00: 0, m01: 0, worldX: 0, // a b x - m10: 0, m11: 0, worldY: 0, // c d y - worldRotation: 0, - worldScaleX: 1, worldScaleY: 1, - updateWorldTransform: function (flipX, flipY) { - var parent = this.parent; - if (parent != null) { - this.worldX = this.x * parent.m00 + this.y * parent.m01 + parent.worldX; - this.worldY = this.x * parent.m10 + this.y * parent.m11 + parent.worldY; - this.worldScaleX = parent.worldScaleX * this.scaleX; - this.worldScaleY = parent.worldScaleY * this.scaleY; - this.worldRotation = parent.worldRotation + this.rotation; - } else { - this.worldX = this.x; - this.worldY = this.y; - this.worldScaleX = this.scaleX; - this.worldScaleY = this.scaleY; - this.worldRotation = this.rotation; - } - var radians = this.worldRotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - this.m00 = cos * this.worldScaleX; - this.m10 = sin * this.worldScaleX; - this.m01 = -sin * this.worldScaleY; - this.m11 = cos * this.worldScaleY; - if (flipX) { - this.m00 = -this.m00; - this.m01 = -this.m01; - } - if (flipY) { - this.m10 = -this.m10; - this.m11 = -this.m11; - } - if (spine.Bone.yDown) { - this.m10 = -this.m10; - this.m11 = -this.m11; - } - }, - setToSetupPose: function () { - var data = this.data; - this.x = data.x; - this.y = data.y; - this.rotation = data.rotation; - this.scaleX = data.scaleX; - this.scaleY = data.scaleY; - } -}; - -spine.Slot = function (slotData, skeleton, bone) { - this.data = slotData; - this.skeleton = skeleton; - this.bone = bone; - this.setToSetupPose(); -}; -spine.Slot.prototype = { - r: 1, g: 1, b: 1, a: 1, - _attachmentTime: 0, - attachment: null, - setAttachment: function (attachment) { - this.attachment = attachment; - this._attachmentTime = this.skeleton.time; - }, - setAttachmentTime: function (time) { - this._attachmentTime = this.skeleton.time - time; - }, - getAttachmentTime: function () { - return this.skeleton.time - this._attachmentTime; - }, - setToSetupPose: function () { - var data = this.data; - this.r = data.r; - this.g = data.g; - this.b = data.b; - this.a = data.a; - - var slotDatas = this.skeleton.data.slots; - for (var i = 0, n = slotDatas.length; i < n; i++) { - if (slotDatas[i] == data) { - this.setAttachment(!data.attachmentName ? null : this.skeleton.getAttachmentBySlotIndex(i, data.attachmentName)); - break; - } - } - } -}; - -spine.Skin = function (name) { - this.name = name; - this.attachments = {}; -}; -spine.Skin.prototype = { - addAttachment: function (slotIndex, name, attachment) { - this.attachments[slotIndex + ":" + name] = attachment; - }, - getAttachment: function (slotIndex, name) { - return this.attachments[slotIndex + ":" + name]; - }, - _attachAll: function (skeleton, oldSkin) { - for (var key in oldSkin.attachments) { - var colon = key.indexOf(":"); - var slotIndex = parseInt(key.substring(0, colon)); - var name = key.substring(colon + 1); - var slot = skeleton.slots[slotIndex]; - if (slot.attachment && slot.attachment.name == name) { - var attachment = this.getAttachment(slotIndex, name); - if (attachment) slot.setAttachment(attachment); - } - } - } -}; - -spine.Animation = function (name, timelines, duration) { - this.name = name; - this.timelines = timelines; - this.duration = duration; -}; -spine.Animation.prototype = { - apply: function (skeleton, time, loop) { - if (loop && this.duration != 0) time %= this.duration; - var timelines = this.timelines; - for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, time, 1); - }, - mix: function (skeleton, time, loop, alpha) { - if (loop && this.duration != 0) time %= this.duration; - var timelines = this.timelines; - for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, time, alpha); - } -}; - -spine.binarySearch = function (values, target, step) { - var low = 0; - var high = Math.floor(values.length / step) - 2; - if (high == 0) return step; - var current = high >>> 1; - while (true) { - if (values[(current + 1) * step] <= target) - low = current + 1; - else - high = current; - if (low == high) return (low + 1) * step; - current = (low + high) >>> 1; - } -}; -spine.linearSearch = function (values, target, step) { - for (var i = 0, last = values.length - step; i <= last; i += step) - if (values[i] > target) return i; - return -1; -}; - -spine.Curves = function (frameCount) { - this.curves = []; // dfx, dfy, ddfx, ddfy, dddfx, dddfy, ... - this.curves.length = (frameCount - 1) * 6; -}; -spine.Curves.prototype = { - setLinear: function (frameIndex) { - this.curves[frameIndex * 6] = 0/*LINEAR*/; - }, - setStepped: function (frameIndex) { - this.curves[frameIndex * 6] = -1/*STEPPED*/; - }, - /** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next. - * cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of - * the difference between the keyframe's values. */ - setCurve: function (frameIndex, cx1, cy1, cx2, cy2) { - var subdiv_step = 1 / 10/*BEZIER_SEGMENTS*/; - var subdiv_step2 = subdiv_step * subdiv_step; - var subdiv_step3 = subdiv_step2 * subdiv_step; - var pre1 = 3 * subdiv_step; - var pre2 = 3 * subdiv_step2; - var pre4 = 6 * subdiv_step2; - var pre5 = 6 * subdiv_step3; - var tmp1x = -cx1 * 2 + cx2; - var tmp1y = -cy1 * 2 + cy2; - var tmp2x = (cx1 - cx2) * 3 + 1; - var tmp2y = (cy1 - cy2) * 3 + 1; - var i = frameIndex * 6; - var curves = this.curves; - curves[i] = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; - curves[i + 1] = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; - curves[i + 2] = tmp1x * pre4 + tmp2x * pre5; - curves[i + 3] = tmp1y * pre4 + tmp2y * pre5; - curves[i + 4] = tmp2x * pre5; - curves[i + 5] = tmp2y * pre5; - }, - getCurvePercent: function (frameIndex, percent) { - percent = percent < 0 ? 0 : (percent > 1 ? 1 : percent); - var curveIndex = frameIndex * 6; - var curves = this.curves; - var dfx = curves[curveIndex]; - if (!dfx/*LINEAR*/) return percent; - if (dfx == -1/*STEPPED*/) return 0; - var dfy = curves[curveIndex + 1]; - var ddfx = curves[curveIndex + 2]; - var ddfy = curves[curveIndex + 3]; - var dddfx = curves[curveIndex + 4]; - var dddfy = curves[curveIndex + 5]; - var x = dfx, y = dfy; - var i = 10/*BEZIER_SEGMENTS*/ - 2; - while (true) { - if (x >= percent) { - var lastX = x - dfx; - var lastY = y - dfy; - return lastY + (y - lastY) * (percent - lastX) / (x - lastX); - } - if (i == 0) break; - i--; - dfx += ddfx; - dfy += ddfy; - ddfx += dddfx; - ddfy += dddfy; - x += dfx; - y += dfy; - } - return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1. - } -}; - -spine.RotateTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, angle, ... - this.frames.length = frameCount * 2; -}; -spine.RotateTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 2; - }, - setFrame: function (frameIndex, time, angle) { - frameIndex *= 2; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = angle; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 2]) { // Time is after last frame. - var amount = bone.data.rotation + frames[frames.length - 1] - bone.rotation; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - bone.rotation += amount * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 2); - var lastFrameValue = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex - 2/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent); - - var amount = frames[frameIndex + 1/*FRAME_VALUE*/] - lastFrameValue; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - amount = bone.data.rotation + (lastFrameValue + amount * percent) - bone.rotation; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - bone.rotation += amount * alpha; - } -}; - -spine.TranslateTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, x, y, ... - this.frames.length = frameCount * 3; -}; -spine.TranslateTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 3; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 3; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = x; - this.frames[frameIndex + 2] = y; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 3]) { // Time is after last frame. - bone.x += (bone.data.x + frames[frames.length - 2] - bone.x) * alpha; - bone.y += (bone.data.y + frames[frames.length - 1] - bone.y) * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 3); - var lastFrameX = frames[frameIndex - 2]; - var lastFrameY = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); - - bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; - bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; - } -}; - -spine.ScaleTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, x, y, ... - this.frames.length = frameCount * 3; -}; -spine.ScaleTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 3; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 3; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = x; - this.frames[frameIndex + 2] = y; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 3]) { // Time is after last frame. - bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 3); - var lastFrameX = frames[frameIndex - 2]; - var lastFrameY = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); - - bone.scaleX += (bone.data.scaleX - 1 + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - 1 + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.scaleY) * alpha; - } -}; - -spine.ColorTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, r, g, b, a, ... - this.frames.length = frameCount * 5; -}; -spine.ColorTimeline.prototype = { - slotIndex: 0, - getFrameCount: function () { - return this.frames.length / 2; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 5; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = r; - this.frames[frameIndex + 2] = g; - this.frames[frameIndex + 3] = b; - this.frames[frameIndex + 4] = a; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var slot = skeleton.slots[this.slotIndex]; - - if (time >= frames[frames.length - 5]) { // Time is after last frame. - var i = frames.length - 1; - slot.r = frames[i - 3]; - slot.g = frames[i - 2]; - slot.b = frames[i - 1]; - slot.a = frames[i]; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 5); - var lastFrameR = frames[frameIndex - 4]; - var lastFrameG = frames[frameIndex - 3]; - var lastFrameB = frames[frameIndex - 2]; - var lastFrameA = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex - 5/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent); - - var r = lastFrameR + (frames[frameIndex + 1/*FRAME_R*/] - lastFrameR) * percent; - var g = lastFrameG + (frames[frameIndex + 2/*FRAME_G*/] - lastFrameG) * percent; - var b = lastFrameB + (frames[frameIndex + 3/*FRAME_B*/] - lastFrameB) * percent; - var a = lastFrameA + (frames[frameIndex + 4/*FRAME_A*/] - lastFrameA) * percent; - if (alpha < 1) { - slot.r += (r - slot.r) * alpha; - slot.g += (g - slot.g) * alpha; - slot.b += (b - slot.b) * alpha; - slot.a += (a - slot.a) * alpha; - } else { - slot.r = r; - slot.g = g; - slot.b = b; - slot.a = a; - } - } -}; - -spine.AttachmentTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, ... - this.frames.length = frameCount; - this.attachmentNames = []; // time, ... - this.attachmentNames.length = frameCount; -}; -spine.AttachmentTimeline.prototype = { - slotIndex: 0, - getFrameCount: function () { - return this.frames.length; - }, - setFrame: function (frameIndex, time, attachmentName) { - this.frames[frameIndex] = time; - this.attachmentNames[frameIndex] = attachmentName; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var frameIndex; - if (time >= frames[frames.length - 1]) // Time is after last frame. - frameIndex = frames.length - 1; - else - frameIndex = spine.binarySearch(frames, time, 1) - 1; - - var attachmentName = this.attachmentNames[frameIndex]; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); - } -}; - -spine.SkeletonData = function () { - this.bones = []; - this.slots = []; - this.skins = []; - this.animations = []; -}; -spine.SkeletonData.prototype = { - defaultSkin: null, - /** @return May be null. */ - findBone: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].name == boneName) return bones[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findBoneIndex: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].name == boneName) return i; - return -1; - }, - /** @return May be null. */ - findSlot: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) { - if (slots[i].name == slotName) return slot[i]; - } - return null; - }, - /** @return -1 if the bone was not found. */ - findSlotIndex: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].name == slotName) return i; - return -1; - }, - /** @return May be null. */ - findSkin: function (skinName) { - var skins = this.skins; - for (var i = 0, n = skins.length; i < n; i++) - if (skins[i].name == skinName) return skins[i]; - return null; - }, - /** @return May be null. */ - findAnimation: function (animationName) { - var animations = this.animations; - for (var i = 0, n = animations.length; i < n; i++) - if (animations[i].name == animationName) return animations[i]; - return null; - } -}; - -spine.Skeleton = function (skeletonData) { - this.data = skeletonData; - - this.bones = []; - for (var i = 0, n = skeletonData.bones.length; i < n; i++) { - var boneData = skeletonData.bones[i]; - var parent = !boneData.parent ? null : this.bones[skeletonData.bones.indexOf(boneData.parent)]; - this.bones.push(new spine.Bone(boneData, parent)); - } - - this.slots = []; - this.drawOrder = []; - for (var i = 0, n = skeletonData.slots.length; i < n; i++) { - var slotData = skeletonData.slots[i]; - var bone = this.bones[skeletonData.bones.indexOf(slotData.boneData)]; - var slot = new spine.Slot(slotData, this, bone); - this.slots.push(slot); - this.drawOrder.push(slot); - } -}; -spine.Skeleton.prototype = { - x: 0, y: 0, - skin: null, - r: 1, g: 1, b: 1, a: 1, - time: 0, - flipX: false, flipY: false, - /** Updates the world transform for each bone. */ - updateWorldTransform: function () { - var flipX = this.flipX; - var flipY = this.flipY; - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - bones[i].updateWorldTransform(flipX, flipY); - }, - /** Sets the bones and slots to their setup pose values. */ - setToSetupPose: function () { - this.setBonesToSetupPose(); - this.setSlotsToSetupPose(); - }, - setBonesToSetupPose: function () { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - bones[i].setToSetupPose(); - }, - setSlotsToSetupPose: function () { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - slots[i].setToSetupPose(i); - }, - /** @return May return null. */ - getRootBone: function () { - return this.bones.length == 0 ? null : this.bones[0]; - }, - /** @return May be null. */ - findBone: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].data.name == boneName) return bones[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findBoneIndex: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].data.name == boneName) return i; - return -1; - }, - /** @return May be null. */ - findSlot: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].data.name == slotName) return slots[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findSlotIndex: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].data.name == slotName) return i; - return -1; - }, - setSkinByName: function (skinName) { - var skin = this.data.findSkin(skinName); - if (!skin) throw "Skin not found: " + skinName; - this.setSkin(skin); - }, - /** Sets the skin used to look up attachments not found in the {@link SkeletonData#getDefaultSkin() default skin}. Attachments - * from the new skin are attached if the corresponding attachment from the old skin was attached. - * @param newSkin May be null. */ - setSkin: function (newSkin) { - if (this.skin && newSkin) newSkin._attachAll(this, this.skin); - this.skin = newSkin; - }, - /** @return May be null. */ - getAttachmentBySlotName: function (slotName, attachmentName) { - return this.getAttachmentBySlotIndex(this.data.findSlotIndex(slotName), attachmentName); - }, - /** @return May be null. */ - getAttachmentBySlotIndex: function (slotIndex, attachmentName) { - if (this.skin) { - var attachment = this.skin.getAttachment(slotIndex, attachmentName); - if (attachment) return attachment; - } - if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); - return null; - }, - /** @param attachmentName May be null. */ - setAttachment: function (slotName, attachmentName) { - var slots = this.slots; - for (var i = 0, n = slots.size; i < n; i++) { - var slot = slots[i]; - if (slot.data.name == slotName) { - var attachment = null; - if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); - if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; - } - slot.setAttachment(attachment); - return; - } - } - throw "Slot not found: " + slotName; - }, - update: function (delta) { - time += delta; - } -}; - -spine.AttachmentType = { - region: 0 -}; - -spine.RegionAttachment = function () { - this.offset = []; - this.offset.length = 8; - this.uvs = []; - this.uvs.length = 8; -}; -spine.RegionAttachment.prototype = { - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1, - width: 0, height: 0, - rendererObject: null, - regionOffsetX: 0, regionOffsetY: 0, - regionWidth: 0, regionHeight: 0, - regionOriginalWidth: 0, regionOriginalHeight: 0, - setUVs: function (u, v, u2, v2, rotate) { - var uvs = this.uvs; - if (rotate) { - uvs[2/*X2*/] = u; - uvs[3/*Y2*/] = v2; - uvs[4/*X3*/] = u; - uvs[5/*Y3*/] = v; - uvs[6/*X4*/] = u2; - uvs[7/*Y4*/] = v; - uvs[0/*X1*/] = u2; - uvs[1/*Y1*/] = v2; - } else { - uvs[0/*X1*/] = u; - uvs[1/*Y1*/] = v2; - uvs[2/*X2*/] = u; - uvs[3/*Y2*/] = v; - uvs[4/*X3*/] = u2; - uvs[5/*Y3*/] = v; - uvs[6/*X4*/] = u2; - uvs[7/*Y4*/] = v2; - } - }, - updateOffset: function () { - var regionScaleX = this.width / this.regionOriginalWidth * this.scaleX; - var regionScaleY = this.height / this.regionOriginalHeight * this.scaleY; - var localX = -this.width / 2 * this.scaleX + this.regionOffsetX * regionScaleX; - var localY = -this.height / 2 * this.scaleY + this.regionOffsetY * regionScaleY; - var localX2 = localX + this.regionWidth * regionScaleX; - var localY2 = localY + this.regionHeight * regionScaleY; - var radians = this.rotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - var localXCos = localX * cos + this.x; - var localXSin = localX * sin; - var localYCos = localY * cos + this.y; - var localYSin = localY * sin; - var localX2Cos = localX2 * cos + this.x; - var localX2Sin = localX2 * sin; - var localY2Cos = localY2 * cos + this.y; - var localY2Sin = localY2 * sin; - var offset = this.offset; - offset[0/*X1*/] = localXCos - localYSin; - offset[1/*Y1*/] = localYCos + localXSin; - offset[2/*X2*/] = localXCos - localY2Sin; - offset[3/*Y2*/] = localY2Cos + localXSin; - offset[4/*X3*/] = localX2Cos - localY2Sin; - offset[5/*Y3*/] = localY2Cos + localX2Sin; - offset[6/*X4*/] = localX2Cos - localYSin; - offset[7/*Y4*/] = localYCos + localX2Sin; - }, - computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; - y += bone.worldY; - var m00 = bone.m00; - var m01 = bone.m01; - var m10 = bone.m10; - var m11 = bone.m11; - var offset = this.offset; - vertices[0/*X1*/] = offset[0/*X1*/] * m00 + offset[1/*Y1*/] * m01 + x; - vertices[1/*Y1*/] = offset[0/*X1*/] * m10 + offset[1/*Y1*/] * m11 + y; - vertices[2/*X2*/] = offset[2/*X2*/] * m00 + offset[3/*Y2*/] * m01 + x; - vertices[3/*Y2*/] = offset[2/*X2*/] * m10 + offset[3/*Y2*/] * m11 + y; - vertices[4/*X3*/] = offset[4/*X3*/] * m00 + offset[5/*X3*/] * m01 + x; - vertices[5/*X3*/] = offset[4/*X3*/] * m10 + offset[5/*X3*/] * m11 + y; - vertices[6/*X4*/] = offset[6/*X4*/] * m00 + offset[7/*Y4*/] * m01 + x; - vertices[7/*Y4*/] = offset[6/*X4*/] * m10 + offset[7/*Y4*/] * m11 + y; - } -} - -spine.AnimationStateData = function (skeletonData) { - this.skeletonData = skeletonData; - this.animationToMixTime = {}; -}; -spine.AnimationStateData.prototype = { - defaultMix: 0, - setMixByName: function (fromName, toName, duration) { - var from = this.skeletonData.findAnimation(fromName); - if (!from) throw "Animation not found: " + fromName; - var to = this.skeletonData.findAnimation(toName); - if (!to) throw "Animation not found: " + toName; - this.setMix(from, to, duration); - }, - setMix: function (from, to, duration) { - this.animationToMixTime[from.name + ":" + to.name] = duration; - }, - getMix: function (from, to) { - var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : this.defaultMix; - } -}; - -spine.AnimationState = function (stateData) { - this.data = stateData; - this.queue = []; -}; -spine.AnimationState.prototype = { - current: null, - previous: null, - currentTime: 0, - previousTime: 0, - currentLoop: false, - previousLoop: false, - mixTime: 0, - mixDuration: 0, - update: function (delta) { - this.currentTime += delta; - this.previousTime += delta; - this.mixTime += delta; - - if (this.queue.length > 0) { - var entry = this.queue[0]; - if (this.currentTime >= entry.delay) { - this._setAnimation(entry.animation, entry.loop); - this.queue.shift(); - } - } - }, - apply: function (skeleton) { - if (!this.current) return; - if (this.previous) { - this.previous.apply(skeleton, this.previousTime, this.previousLoop); - var alpha = this.mixTime / this.mixDuration; - if (alpha >= 1) { - alpha = 1; - this.previous = null; - } - this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else - this.current.apply(skeleton, this.currentTime, this.currentLoop); - }, - clearAnimation: function () { - this.previous = null; - this.current = null; - this.queue.length = 0; - }, - _setAnimation: function (animation, loop) { - this.previous = null; - if (animation && this.current) { - this.mixDuration = this.data.getMix(this.current, animation); - if (this.mixDuration > 0) { - this.mixTime = 0; - this.previous = this.current; - this.previousTime = this.currentTime; - this.previousLoop = this.currentLoop; - } - } - this.current = animation; - this.currentLoop = loop; - this.currentTime = 0; - }, - /** @see #setAnimation(Animation, Boolean) */ - setAnimationByName: function (animationName, loop) { - var animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw "Animation not found: " + animationName; - this.setAnimation(animation, loop); - }, - /** Set the current animation. Any queued animations are cleared and the current animation time is set to 0. - * @param animation May be null. */ - setAnimation: function (animation, loop) { - this.queue.length = 0; - this._setAnimation(animation, loop); - }, - /** @see #addAnimation(Animation, Boolean, Number) */ - addAnimationByName: function (animationName, loop, delay) { - var animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw "Animation not found: " + animationName; - this.addAnimation(animation, loop, delay); - }, - /** Adds an animation to be played delay seconds after the current or last queued animation. - * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */ - addAnimation: function (animation, loop, delay) { - var entry = {}; - entry.animation = animation; - entry.loop = loop; - - if (!delay || delay <= 0) { - var previousAnimation = this.queue.length == 0 ? this.current : this.queue[this.queue.length - 1].animation; - if (previousAnimation != null) - delay = previousAnimation.duration - this.data.getMix(previousAnimation, animation) + (delay || 0); - else - delay = 0; - } - entry.delay = delay; - - this.queue.push(entry); - }, - /** Returns true if no animation is set or if the current time is greater than the animation duration, regardless of looping. */ - isComplete: function () { - return !this.current || this.currentTime >= this.current.duration; - } -}; - -spine.SkeletonJson = function (attachmentLoader) { - this.attachmentLoader = attachmentLoader; -}; -spine.SkeletonJson.prototype = { - scale: 1, - readSkeletonData: function (root) { - var skeletonData = new spine.SkeletonData(); - - // Bones. - var bones = root["bones"]; - for (var i = 0, n = bones.length; i < n; i++) { - var boneMap = bones[i]; - var parent = null; - if (boneMap["parent"]) { - parent = skeletonData.findBone(boneMap["parent"]); - if (!parent) throw "Parent bone not found: " + boneMap["parent"]; - } - var boneData = new spine.BoneData(boneMap["name"], parent); - boneData.length = (boneMap["length"] || 0) * this.scale; - boneData.x = (boneMap["x"] || 0) * this.scale; - boneData.y = (boneMap["y"] || 0) * this.scale; - boneData.rotation = (boneMap["rotation"] || 0); - boneData.scaleX = boneMap["scaleX"] || 1; - boneData.scaleY = boneMap["scaleY"] || 1; - skeletonData.bones.push(boneData); - } - - // Slots. - var slots = root["slots"]; - for (var i = 0, n = slots.length; i < n; i++) { - var slotMap = slots[i]; - var boneData = skeletonData.findBone(slotMap["bone"]); - if (!boneData) throw "Slot bone not found: " + slotMap["bone"]; - var slotData = new spine.SlotData(slotMap["name"], boneData); - - var color = slotMap["color"]; - if (color) { - slotData.r = spine.SkeletonJson.toColor(color, 0); - slotData.g = spine.SkeletonJson.toColor(color, 1); - slotData.b = spine.SkeletonJson.toColor(color, 2); - slotData.a = spine.SkeletonJson.toColor(color, 3); - } - - slotData.attachmentName = slotMap["attachment"]; - - skeletonData.slots.push(slotData); - } - - // Skins. - var skins = root["skins"]; - for (var skinName in skins) { - if (!skins.hasOwnProperty(skinName)) continue; - var skinMap = skins[skinName]; - var skin = new spine.Skin(skinName); - for (var slotName in skinMap) { - if (!skinMap.hasOwnProperty(slotName)) continue; - var slotIndex = skeletonData.findSlotIndex(slotName); - var slotEntry = skinMap[slotName]; - for (var attachmentName in slotEntry) { - if (!slotEntry.hasOwnProperty(attachmentName)) continue; - var attachment = this.readAttachment(skin, attachmentName, slotEntry[attachmentName]); - if (attachment != null) skin.addAttachment(slotIndex, attachmentName, attachment); - } - } - skeletonData.skins.push(skin); - if (skin.name == "default") skeletonData.defaultSkin = skin; - } - - // Animations. - var animations = root["animations"]; - for (var animationName in animations) { - if (!animations.hasOwnProperty(animationName)) continue; - this.readAnimation(animationName, animations[animationName], skeletonData); - } - - return skeletonData; - }, - readAttachment: function (skin, name, map) { - name = map["name"] || name; - - var type = spine.AttachmentType[map["type"] || "region"]; - - if (type == spine.AttachmentType.region) { - var attachment = new spine.RegionAttachment(); - attachment.x = (map["x"] || 0) * this.scale; - attachment.y = (map["y"] || 0) * this.scale; - attachment.scaleX = map["scaleX"] || 1; - attachment.scaleY = map["scaleY"] || 1; - attachment.rotation = map["rotation"] || 0; - attachment.width = (map["width"] || 32) * this.scale; - attachment.height = (map["height"] || 32) * this.scale; - attachment.updateOffset(); - - attachment.rendererObject = {}; - attachment.rendererObject.name = name; - attachment.rendererObject.scale = {}; - attachment.rendererObject.scale.x = attachment.scaleX; - attachment.rendererObject.scale.y = attachment.scaleY; - attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; - return attachment; - } - - throw "Unknown attachment type: " + type; - }, - - readAnimation: function (name, map, skeletonData) { - var timelines = []; - var duration = 0; - - var bones = map["bones"]; - for (var boneName in bones) { - if (!bones.hasOwnProperty(boneName)) continue; - var boneIndex = skeletonData.findBoneIndex(boneName); - if (boneIndex == -1) throw "Bone not found: " + boneName; - var boneMap = bones[boneName]; - - for (var timelineName in boneMap) { - if (!boneMap.hasOwnProperty(timelineName)) continue; - var values = boneMap[timelineName]; - if (timelineName == "rotate") { - var timeline = new spine.RotateTimeline(values.length); - timeline.boneIndex = boneIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - timeline.setFrame(frameIndex, valueMap["time"], valueMap["angle"]); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 2 - 2]); - - } else if (timelineName == "translate" || timelineName == "scale") { - var timeline; - var timelineScale = 1; - if (timelineName == "scale") - timeline = new spine.ScaleTimeline(values.length); - else { - timeline = new spine.TranslateTimeline(values.length); - timelineScale = this.scale; - } - timeline.boneIndex = boneIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - var x = (valueMap["x"] || 0) * timelineScale; - var y = (valueMap["y"] || 0) * timelineScale; - timeline.setFrame(frameIndex, valueMap["time"], x, y); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - - } else - throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; - } - } - var slots = map["slots"]; - for (var slotName in slots) { - if (!slots.hasOwnProperty(slotName)) continue; - var slotMap = slots[slotName]; - var slotIndex = skeletonData.findSlotIndex(slotName); - - for (var timelineName in slotMap) { - if (!slotMap.hasOwnProperty(timelineName)) continue; - var values = slotMap[timelineName]; - if (timelineName == "color") { - var timeline = new spine.ColorTimeline(values.length); - timeline.slotIndex = slotIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - var color = valueMap["color"]; - var r = spine.SkeletonJson.toColor(color, 0); - var g = spine.SkeletonJson.toColor(color, 1); - var b = spine.SkeletonJson.toColor(color, 2); - var a = spine.SkeletonJson.toColor(color, 3); - timeline.setFrame(frameIndex, valueMap["time"], r, g, b, a); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 5 - 5]); - - } else if (timelineName == "attachment") { - var timeline = new spine.AttachmentTimeline(values.length); - timeline.slotIndex = slotIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); - - } else - throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; - } - } - skeletonData.animations.push(new spine.Animation(name, timelines, duration)); - } -}; -spine.SkeletonJson.readCurve = function (timeline, frameIndex, valueMap) { - var curve = valueMap["curve"]; - if (!curve) return; - if (curve == "stepped") - timeline.curves.setStepped(frameIndex); - else if (curve instanceof Array) - timeline.curves.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); -}; -spine.SkeletonJson.toColor = function (hexString, colorIndex) { - if (hexString.length != 8) throw "Color hexidecimal length must be 8, recieved: " + hexString; - return parseInt(hexString.substring(colorIndex * 2, 2), 16) / 255; -}; - -spine.Atlas = function (atlasText, textureLoader) { - this.textureLoader = textureLoader; - this.pages = []; - this.regions = []; - - var reader = new spine.AtlasReader(atlasText); - var tuple = []; - tuple.length = 4; - var page = null; - while (true) { - var line = reader.readLine(); - if (line == null) break; - line = reader.trim(line); - if (line.length == 0) - page = null; - else if (!page) { - page = new spine.AtlasPage(); - page.name = line; - - page.format = spine.Atlas.Format[reader.readValue()]; - - reader.readTuple(tuple); - page.minFilter = spine.Atlas.TextureFilter[tuple[0]]; - page.magFilter = spine.Atlas.TextureFilter[tuple[1]]; - - var direction = reader.readValue(); - page.uWrap = spine.Atlas.TextureWrap.clampToEdge; - page.vWrap = spine.Atlas.TextureWrap.clampToEdge; - if (direction == "x") - page.uWrap = spine.Atlas.TextureWrap.repeat; - else if (direction == "y") - page.vWrap = spine.Atlas.TextureWrap.repeat; - else if (direction == "xy") - page.uWrap = page.vWrap = spine.Atlas.TextureWrap.repeat; - - textureLoader.load(page, line); - - this.pages.push(page); - - } else { - var region = new spine.AtlasRegion(); - region.name = line; - region.page = page; - - region.rotate = reader.readValue() == "true"; - - reader.readTuple(tuple); - var x = parseInt(tuple[0]); - var y = parseInt(tuple[1]); - - reader.readTuple(tuple); - var width = parseInt(tuple[0]); - var height = parseInt(tuple[1]); - - region.u = x / page.width; - region.v = y / page.height; - if (region.rotate) { - region.u2 = (x + height) / page.width; - region.v2 = (y + width) / page.height; - } else { - region.u2 = (x + width) / page.width; - region.v2 = (y + height) / page.height; - } - region.x = x; - region.y = y; - region.width = Math.abs(width); - region.height = Math.abs(height); - - if (reader.readTuple(tuple) == 4) { // split is optional - region.splits = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; - - if (reader.readTuple(tuple) == 4) { // pad is optional, but only present with splits - region.pads = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; - - reader.readTuple(tuple); - } - } - - region.originalWidth = parseInt(tuple[0]); - region.originalHeight = parseInt(tuple[1]); - - reader.readTuple(tuple); - region.offsetX = parseInt(tuple[0]); - region.offsetY = parseInt(tuple[1]); - - region.index = parseInt(reader.readValue()); - - this.regions.push(region); - } - } -}; -spine.Atlas.prototype = { - findRegion: function (name) { - var regions = this.regions; - for (var i = 0, n = regions.length; i < n; i++) - if (regions[i].name == name) return regions[i]; - return null; - }, - dispose: function () { - var pages = this.pages; - for (var i = 0, n = pages.length; i < n; i++) - this.textureLoader.unload(pages[i].rendererObject); - }, - updateUVs: function (page) { - var regions = this.regions; - for (var i = 0, n = regions.length; i < n; i++) { - var region = regions[i]; - if (region.page != page) continue; - region.u = region.x / page.width; - region.v = region.y / page.height; - if (region.rotate) { - region.u2 = (region.x + region.height) / page.width; - region.v2 = (region.y + region.width) / page.height; - } else { - region.u2 = (region.x + region.width) / page.width; - region.v2 = (region.y + region.height) / page.height; - } - } - } -}; - -spine.Atlas.Format = { - alpha: 0, - intensity: 1, - luminanceAlpha: 2, - rgb565: 3, - rgba4444: 4, - rgb888: 5, - rgba8888: 6 -}; - -spine.Atlas.TextureFilter = { - nearest: 0, - linear: 1, - mipMap: 2, - mipMapNearestNearest: 3, - mipMapLinearNearest: 4, - mipMapNearestLinear: 5, - mipMapLinearLinear: 6 -}; - -spine.Atlas.TextureWrap = { - mirroredRepeat: 0, - clampToEdge: 1, - repeat: 2 -}; - -spine.AtlasPage = function () {}; -spine.AtlasPage.prototype = { - name: null, - format: null, - minFilter: null, - magFilter: null, - uWrap: null, - vWrap: null, - rendererObject: null, - width: 0, - height: 0 -}; - -spine.AtlasRegion = function () {}; -spine.AtlasRegion.prototype = { - page: null, - name: null, - x: 0, y: 0, - width: 0, height: 0, - u: 0, v: 0, u2: 0, v2: 0, - offsetX: 0, offsetY: 0, - originalWidth: 0, originalHeight: 0, - index: 0, - rotate: false, - splits: null, - pads: null, -}; - -spine.AtlasReader = function (text) { - this.lines = text.split(/\r\n|\r|\n/); -}; -spine.AtlasReader.prototype = { - index: 0, - trim: function (value) { - return value.replace(/^\s+|\s+$/g, ""); - }, - readLine: function () { - if (this.index >= this.lines.length) return null; - return this.lines[this.index++]; - }, - readValue: function () { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) throw "Invalid line: " + line; - return this.trim(line.substring(colon + 1)); - }, - /** Returns the number of tuple values read (2 or 4). */ - readTuple: function (tuple) { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) throw "Invalid line: " + line; - var i = 0, lastMatch= colon + 1; - for (; i < 3; i++) { - var comma = line.indexOf(",", lastMatch); - if (comma == -1) { - if (i == 0) throw "Invalid line: " + line; - break; - } - tuple[i] = this.trim(line.substr(lastMatch, comma - lastMatch)); - lastMatch = comma + 1; - } - tuple[i] = this.trim(line.substring(lastMatch)); - return i + 1; - } -} - -spine.AtlasAttachmentLoader = function (atlas) { - this.atlas = atlas; -} -spine.AtlasAttachmentLoader.prototype = { - newAttachment: function (skin, type, name) { - switch (type) { - case spine.AttachmentType.region: - var region = this.atlas.findRegion(name); - if (!region) throw "Region not found in atlas: " + name + " (" + type + ")"; - var attachment = new spine.RegionAttachment(name); - attachment.rendererObject = region; - attachment.setUVs(region.u, region.v, region.u2, region.v2, region.rotate); - attachment.regionOffsetX = region.offsetX; - attachment.regionOffsetY = region.offsetY; - attachment.regionWidth = region.width; - attachment.regionHeight = region.height; - attachment.regionOriginalWidth = region.originalWidth; - attachment.regionOriginalHeight = region.originalHeight; - return attachment; - } - throw "Unknown attachment type: " + type; - } -} - -PIXI.AnimCache = {}; -spine.Bone.yDown = true; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * This object is one that will allow you to specify custom rendering functions based on render type - * - * @class CustomRenderable - * @extends DisplayObject - * @constructor - */ -PIXI.CustomRenderable = function() -{ - PIXI.DisplayObject.call( this ); - -} - -// constructor -PIXI.CustomRenderable.prototype = Object.create( PIXI.DisplayObject.prototype ); -PIXI.CustomRenderable.prototype.constructor = PIXI.CustomRenderable; - -/** - * If this object is being rendered by a CanvasRenderer it will call this callback - * - * @method renderCanvas - * @param renderer {CanvasRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.renderCanvas = function(renderer) -{ - // override! -} - -/** - * If this object is being rendered by a WebGLRenderer it will call this callback to initialize - * - * @method initWebGL - * @param renderer {WebGLRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.initWebGL = function(renderer) -{ - // override! -} - -/** - * If this object is being rendered by a WebGLRenderer it will call this callback - * - * @method renderWebGL - * @param renderer {WebGLRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.renderWebGL = function(renderGroup, projectionMatrix) -{ - // not sure if both needed? but ya have for now! - // override! -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.BaseTextureCache = {}; -PIXI.texturesToUpdate = []; -PIXI.texturesToDestroy = []; - -/** - * A texture stores the information that represents an image. All textures have a base texture - * - * @class BaseTexture - * @uses EventTarget - * @constructor - * @param source {String} the source object (image or canvas) - */ -PIXI.BaseTexture = function(source) -{ - PIXI.EventTarget.call( this ); - - /** - * [read-only] The width of the base texture set when the image has loaded - * - * @property width - * @type Number - * @readOnly - */ - this.width = 100; - - /** - * [read-only] The height of the base texture set when the image has loaded - * - * @property height - * @type Number - * @readOnly - */ - this.height = 100; - - /** - * [read-only] Describes if the base texture has loaded or not - * - * @property hasLoaded - * @type Boolean - * @readOnly - */ - this.hasLoaded = false; - - /** - * The source that is loaded to create the texture - * - * @property source - * @type Image - */ - this.source = source; - - if(!source)return; - - if(this.source instanceof Image || this.source instanceof HTMLImageElement) - { - if(this.source.complete) - { - this.hasLoaded = true; - this.width = this.source.width; - this.height = this.source.height; - - PIXI.texturesToUpdate.push(this); - } - else - { - - var scope = this; - this.source.onload = function(){ - - scope.hasLoaded = true; - scope.width = scope.source.width; - scope.height = scope.source.height; - - // add it to somewhere... - PIXI.texturesToUpdate.push(scope); - scope.dispatchEvent( { type: 'loaded', content: scope } ); - } - // this.image.src = imageUrl; - } - } - else - { - this.hasLoaded = true; - this.width = this.source.width; - this.height = this.source.height; - - PIXI.texturesToUpdate.push(this); - } - - this._powerOf2 = false; -} - -PIXI.BaseTexture.prototype.constructor = PIXI.BaseTexture; - -/** - * Destroys this base texture - * - * @method destroy - */ -PIXI.BaseTexture.prototype.destroy = function() -{ - if(this.source instanceof Image) - { - this.source.src = null; - } - this.source = null; - PIXI.texturesToDestroy.push(this); -} - -/** - * Helper function that returns a base texture based on an image url - * If the image is not in the base texture cache it will be created and loaded - * - * @static - * @method fromImage - * @param imageUrl {String} The image url of the texture - * @return BaseTexture - */ -PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) -{ - var baseTexture = PIXI.BaseTextureCache[imageUrl]; - if(!baseTexture) - { - // new Image() breaks tex loading in some versions of Chrome. - // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); - if (crossorigin) - { - image.crossOrigin = ''; - } - image.src = imageUrl; - baseTexture = new PIXI.BaseTexture(image); - PIXI.BaseTextureCache[imageUrl] = baseTexture; - } - - return baseTexture; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.TextureCache = {}; -PIXI.FrameCache = {}; - -/** - * A texture stores the information that represents an image or part of an image. It cannot be added - * to the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used - * - * @class Texture - * @uses EventTarget - * @constructor - * @param baseTexture {BaseTexture} The base texture source to create the texture from - * @param frame {Rectangle} The rectangle frame of the texture to show - */ -PIXI.Texture = function(baseTexture, frame) -{ - PIXI.EventTarget.call( this ); - - if(!frame) - { - this.noFrame = true; - frame = new PIXI.Rectangle(0,0,1,1); - } - - if(baseTexture instanceof PIXI.Texture) - baseTexture = baseTexture.baseTexture; - - /** - * The base texture of this texture - * - * @property baseTexture - * @type BaseTexture - */ - this.baseTexture = baseTexture; - - /** - * The frame specifies the region of the base texture that this texture uses - * - * @property frame - * @type Rectangle - */ - this.frame = frame; - - /** - * The trim point - * - * @property trim - * @type Point - */ - this.trim = new PIXI.Point(); - - this.scope = this; - - if(baseTexture.hasLoaded) - { - if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); - //console.log(frame) - - this.setFrame(frame); - } - else - { - var scope = this; - baseTexture.addEventListener( 'loaded', function(){ scope.onBaseTextureLoaded()} ); - } -} - -PIXI.Texture.prototype.constructor = PIXI.Texture; - -/** - * Called when the base texture is loaded - * - * @method onBaseTextureLoaded - * @param event - * @private - */ -PIXI.Texture.prototype.onBaseTextureLoaded = function(event) -{ - var baseTexture = this.baseTexture; - baseTexture.removeEventListener( 'loaded', this.onLoaded ); - - if(this.noFrame)this.frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); - this.noFrame = false; - this.width = this.frame.width; - this.height = this.frame.height; - - this.scope.dispatchEvent( { type: 'update', content: this } ); -} - -/** - * Destroys this texture - * - * @method destroy - * @param destroyBase {Boolean} Whether to destroy the base texture as well - */ -PIXI.Texture.prototype.destroy = function(destroyBase) -{ - if(destroyBase)this.baseTexture.destroy(); -} - -/** - * Specifies the rectangle region of the baseTexture - * - * @method setFrame - * @param frame {Rectangle} The frame of the texture to set it to - */ -PIXI.Texture.prototype.setFrame = function(frame) -{ - this.frame = frame; - this.width = frame.width; - this.height = frame.height; - - if(frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height) - { - throw new Error("Texture Error: frame does not fit inside the base Texture dimensions " + this); - } - - this.updateFrame = true; - - PIXI.Texture.frameUpdates.push(this); - //this.dispatchEvent( { type: 'update', content: this } ); -} - -/** - * Helper function that returns a texture based on an image url - * If the image is not in the texture cache it will be created and loaded - * - * @static - * @method fromImage - * @param imageUrl {String} The image url of the texture - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - * @return Texture - */ -PIXI.Texture.fromImage = function(imageUrl, crossorigin) -{ - var texture = PIXI.TextureCache[imageUrl]; - - if(!texture) - { - texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); - PIXI.TextureCache[imageUrl] = texture; - } - - return texture; -} - -/** - * Helper function that returns a texture based on a frame id - * If the frame id is not in the texture cache an error will be thrown - * - * @static - * @method fromFrame - * @param frameId {String} The frame id of the texture - * @return Texture - */ -PIXI.Texture.fromFrame = function(frameId) -{ - var texture = PIXI.TextureCache[frameId]; - if(!texture)throw new Error("The frameId '"+ frameId +"' does not exist in the texture cache " + this); - return texture; -} - -/** - * Helper function that returns a texture based on a canvas element - * If the canvas is not in the texture cache it will be created and loaded - * - * @static - * @method fromCanvas - * @param canvas {Canvas} The canvas element source of the texture - * @return Texture - */ -PIXI.Texture.fromCanvas = function(canvas) -{ - var baseTexture = new PIXI.BaseTexture(canvas); - return new PIXI.Texture(baseTexture); -} - - -/** - * Adds a texture to the textureCache. - * - * @static - * @method addTextureToCache - * @param texture {Texture} - * @param id {String} the id that the texture will be stored against. - */ -PIXI.Texture.addTextureToCache = function(texture, id) -{ - PIXI.TextureCache[id] = texture; -} - -/** - * Remove a texture from the textureCache. - * - * @static - * @method removeTextureFromCache - * @param id {String} the id of the texture to be removed - * @return {Texture} the texture that was removed - */ -PIXI.Texture.removeTextureFromCache = function(id) -{ - var texture = PIXI.TextureCache[id] - PIXI.TextureCache[id] = null; - return texture; -} - -// this is more for webGL.. it contains updated frames.. -PIXI.Texture.frameUpdates = []; - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - A RenderTexture is a special texture that allows any pixi displayObject to be rendered to it. - - __Hint__: All DisplayObjects (exmpl. Sprites) that renders on RenderTexture should be preloaded. - Otherwise black rectangles will be drawn instead. - - RenderTexture takes snapshot of DisplayObject passed to render method. If DisplayObject is passed to render method, position and rotation of it will be ignored. For example: - - var renderTexture = new PIXI.RenderTexture(800, 600); - var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - sprite.position.x = 800/2; - sprite.position.y = 600/2; - sprite.anchor.x = 0.5; - sprite.anchor.y = 0.5; - renderTexture.render(sprite); - - Sprite in this case will be rendered to 0,0 position. To render this sprite at center DisplayObjectContainer should be used: - - var doc = new PIXI.DisplayObjectContainer(); - doc.addChild(sprite); - renderTexture.render(doc); // Renders to center of renderTexture - - @class RenderTexture - @extends Texture - @constructor - @param width {Number} The width of the render texture - @param height {Number} The height of the render texture - */ -PIXI.RenderTexture = function(width, height) -{ - PIXI.EventTarget.call( this ); - - this.width = width || 100; - this.height = height || 100; - - this.indetityMatrix = PIXI.mat3.create(); - - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); - - if(PIXI.gl) - { - this.initWebGL(); - } - else - { - this.initCanvas(); - } -} - -PIXI.RenderTexture.prototype = Object.create( PIXI.Texture.prototype ); -PIXI.RenderTexture.prototype.constructor = PIXI.RenderTexture; - -/** - * Initializes the webgl data for this texture - * - * @method initWebGL - * @private - */ -PIXI.RenderTexture.prototype.initWebGL = function() -{ - var gl = PIXI.gl; - this.glFramebuffer = gl.createFramebuffer(); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - - this.glFramebuffer.width = this.width; - this.glFramebuffer.height = this.height; - - this.baseTexture = new PIXI.BaseTexture(); - - this.baseTexture.width = this.width; - this.baseTexture.height = this.height; - - this.baseTexture._glTexture = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - - this.baseTexture.isRender = true; - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.baseTexture._glTexture, 0); - - // create a projection matrix.. - this.projection = new PIXI.Point(this.width/2 , this.height/2); - - // set the correct render function.. - this.render = this.renderWebGL; - - -} - - -PIXI.RenderTexture.prototype.resize = function(width, height) -{ - - this.width = width; - this.height = height; - - if(PIXI.gl) - { - this.projection.x = this.width/2 - this.projection.y = this.height/2; - - var gl = PIXI.gl; - gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - } - else - { - - this.frame.width = this.width - this.frame.height = this.height; - this.renderer.resize(this.width, this.height); - } -} - -/** - * Initializes the canvas data for this texture - * - * @method initCanvas - * @private - */ -PIXI.RenderTexture.prototype.initCanvas = function() -{ - this.renderer = new PIXI.CanvasRenderer(this.width, this.height, null, 0); - - this.baseTexture = new PIXI.BaseTexture(this.renderer.view); - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); - - this.render = this.renderCanvas; -} - -/** - * This function will draw the display object to the texture. - * - * @method renderWebGL - * @param displayObject {DisplayObject} The display object to render this texture on - * @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn - * @private - */ -PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, clear) -{ - var gl = PIXI.gl; - - // enable the alpha color mask.. - gl.colorMask(true, true, true, true); - - gl.viewport(0, 0, this.width, this.height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - - if(clear) - { - gl.clearColor(0,0,0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - } - - // THIS WILL MESS WITH HIT TESTING! - var children = displayObject.children; - - //TODO -? create a new one??? dont think so! - var originalWorldTransform = displayObject.worldTransform; - displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; - // modify to flip... - displayObject.worldTransform[4] = -1; - displayObject.worldTransform[5] = this.projection.y * 2; - - - if(position) - { - displayObject.worldTransform[2] = position.x; - displayObject.worldTransform[5] -= position.y; - } - - PIXI.visibleCount++; - displayObject.vcount = PIXI.visibleCount; - - for(var i=0,j=children.length; i} assetURLs an array of image/sprite sheet urls that you would like loaded - * supported. Supported image formats include "jpeg", "jpg", "png", "gif". Supported - * sprite sheet data formats only include "JSON" at this time. Supported bitmap font - * data formats include "xml" and "fnt". - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.AssetLoader = function(assetURLs, crossorigin) -{ - PIXI.EventTarget.call(this); - - /** - * The array of asset URLs that are going to be loaded - * - * @property assetURLs - * @type Array - */ - this.assetURLs = assetURLs; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * Maps file extension to loader types - * - * @property loadersByType - * @type Object - */ - this.loadersByType = { - "jpg": PIXI.ImageLoader, - "jpeg": PIXI.ImageLoader, - "png": PIXI.ImageLoader, - "gif": PIXI.ImageLoader, - "json": PIXI.JsonLoader, - "anim": PIXI.SpineLoader, - "xml": PIXI.BitmapFontLoader, - "fnt": PIXI.BitmapFontLoader - }; - - -}; - -/** - * Fired when an item has loaded - * @event onProgress - */ - -/** - * Fired when all the assets have loaded - * @event onComplete - */ - -// constructor -PIXI.AssetLoader.prototype.constructor = PIXI.AssetLoader; - -/** - * Starts loading the assets sequentially - * - * @method load - */ -PIXI.AssetLoader.prototype.load = function() -{ - var scope = this; - - this.loadCount = this.assetURLs.length; - - for (var i=0; i < this.assetURLs.length; i++) - { - var fileName = this.assetURLs[i]; - var fileType = fileName.split(".").pop().toLowerCase(); - - var loaderClass = this.loadersByType[fileType]; - if(!loaderClass) - throw new Error(fileType + " is an unsupported file type"); - - var loader = new loaderClass(fileName, this.crossorigin); - - loader.addEventListener("loaded", function() - { - scope.onAssetLoaded(); - }); - loader.load(); - } -}; - -/** - * Invoked after each file is loaded - * - * @method onAssetLoaded - * @private - */ -PIXI.AssetLoader.prototype.onAssetLoaded = function() -{ - this.loadCount--; - this.dispatchEvent({type: "onProgress", content: this}); - if(this.onProgress) this.onProgress(); - - if(this.loadCount == 0) - { - this.dispatchEvent({type: "onComplete", content: this}); - if(this.onComplete) this.onComplete(); - } -}; - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The json file loader is used to load in JSON data and parsing it - * When loaded this class will dispatch a "loaded" event - * If load failed this class will dispatch a "error" event - * - * @class JsonLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the JSON file - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.JsonLoader = function (url, crossorigin) { - PIXI.EventTarget.call(this); - - /** - * The url of the bitmap font data - * - * @property url - * @type String - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * [read-only] The base url of the bitmap font data - * - * @property baseUrl - * @type String - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ""); - - /** - * [read-only] Whether the data has loaded yet - * - * @property loaded - * @type Boolean - * @readOnly - */ - this.loaded = false; - -}; - -// constructor -PIXI.JsonLoader.prototype.constructor = PIXI.JsonLoader; - -/** - * Loads the JSON data - * - * @method load - */ -PIXI.JsonLoader.prototype.load = function () { - this.ajaxRequest = new AjaxRequest(); - var scope = this; - this.ajaxRequest.onreadystatechange = function () { - scope.onJSONLoaded(); - }; - - this.ajaxRequest.open("GET", this.url, true); - if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/json"); - this.ajaxRequest.send(null); -}; - -/** - * Invoke when JSON file is loaded - * - * @method onJSONLoaded - * @private - */ -PIXI.JsonLoader.prototype.onJSONLoaded = function () { - if (this.ajaxRequest.readyState == 4) { - if (this.ajaxRequest.status == 200 || window.location.href.indexOf("http") == -1) { - this.json = JSON.parse(this.ajaxRequest.responseText); - - if(this.json.frames) - { - // sprite sheet - var scope = this; - var textureUrl = this.baseUrl + this.json.meta.image; - var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); - var frameData = this.json.frames; - - this.texture = image.texture.baseTexture; - image.addEventListener("loaded", function (event) { - scope.onLoaded(); - }); - - for (var i in frameData) { - var rect = frameData[i].frame; - if (rect) { - PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) { - //var realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) - // calculate the offset! - } - } - } - - image.load(); - - } - else if(this.json.bones) - { - // spine animation - var spineJsonParser = new spine.SkeletonJson(); - var skeletonData = spineJsonParser.readSkeletonData(this.json); - PIXI.AnimCache[this.url] = skeletonData; - this.onLoaded(); - } - else - { - this.onLoaded(); - } - } - else - { - this.onError(); - } - } -}; - -/** - * Invoke when json file loaded - * - * @method onLoaded - * @private - */ -PIXI.JsonLoader.prototype.onLoaded = function () { - this.loaded = true; - this.dispatchEvent({ - type: "loaded", - content: this - }); -}; - -/** - * Invoke when error occured - * - * @method onError - * @private - */ -PIXI.JsonLoader.prototype.onError = function () { - this.dispatchEvent({ - type: "error", - content: this - }); -}; -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The sprite sheet loader is used to load in JSON sprite sheet data - * To generate the data you can use http://www.codeandweb.com/texturepacker and publish the "JSON" format - * There is a free version so thats nice, although the paid version is great value for money. - * It is highly recommended to use Sprite sheets (also know as texture atlas") as it means sprite"s can be batched and drawn together for highly increased rendering speed. - * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() - * This loader will also load the image file that the Spritesheet points to as well as the data. - * When loaded this class will dispatch a "loaded" event - * - * @class SpriteSheetLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the sprite sheet JSON file - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ - -PIXI.SpriteSheetLoader = function (url, crossorigin) { - /* - * i use texture packer to load the assets.. - * http://www.codeandweb.com/texturepacker - * make sure to set the format as "JSON" - */ - PIXI.EventTarget.call(this); - - /** - * The url of the bitmap font data - * - * @property url - * @type String - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * [read-only] The base url of the bitmap font data - * - * @property baseUrl - * @type String - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ""); - - /** - * The texture being loaded - * - * @property texture - * @type Texture - */ - this.texture = null; - - /** - * The frames of the sprite sheet - * - * @property frames - * @type Object - */ - this.frames = {}; -}; - -// constructor -PIXI.SpriteSheetLoader.prototype.constructor = PIXI.SpriteSheetLoader; - -/** - * This will begin loading the JSON file - * - * @method load - */ -PIXI.SpriteSheetLoader.prototype.load = function () { - var scope = this; - var jsonLoader = new PIXI.JsonLoader(this.url, this.crossorigin); - jsonLoader.addEventListener("loaded", function (event) { - scope.json = event.content.json; - scope.onJSONLoaded(); - }); - jsonLoader.load(); -}; - -/** - * Invoke when JSON file is loaded - * - * @method onJSONLoaded - * @private - */ -PIXI.SpriteSheetLoader.prototype.onJSONLoaded = function () { - var scope = this; - var textureUrl = this.baseUrl + this.json.meta.image; - var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); - var frameData = this.json.frames; - - this.texture = image.texture.baseTexture; - image.addEventListener("loaded", function (event) { - scope.onLoaded(); - }); - - for (var i in frameData) { - var rect = frameData[i].frame; - if (rect) { - PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) { - //var realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) - // calculate the offset! - } - } - } - - image.load(); -}; -/** - * Invoke when all files are loaded (json and texture) - * - * @method onLoaded - * @private - */ -PIXI.SpriteSheetLoader.prototype.onLoaded = function () { - this.dispatchEvent({ - type: "loaded", - content: this - }); -}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The image loader class is responsible for loading images file formats ("jpeg", "jpg", "png" and "gif") - * Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() - * When loaded this class will dispatch a 'loaded' event - * - * @class ImageLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the image - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.ImageLoader = function(url, crossorigin) -{ - PIXI.EventTarget.call(this); - - /** - * The texture being loaded - * - * @property texture - * @type Texture - */ - this.texture = PIXI.Texture.fromImage(url, crossorigin); - - /** - * if the image is loaded with loadFramedSpriteSheet - * frames will contain the sprite sheet frames - * - */ - this.frames = []; -}; - -// constructor -PIXI.ImageLoader.prototype.constructor = PIXI.ImageLoader; - -/** - * Loads image or takes it from cache - * - * @method load - */ -PIXI.ImageLoader.prototype.load = function() -{ - if(!this.texture.baseTexture.hasLoaded) - { - var scope = this; - this.texture.baseTexture.addEventListener("loaded", function() - { - scope.onLoaded(); - }); - } - else - { - this.onLoaded(); - } -}; - -/** - * Invoked when image file is loaded or it is already cached and ready to use - * - * @method onLoaded - * @private - */ -PIXI.ImageLoader.prototype.onLoaded = function() -{ - this.dispatchEvent({type: "loaded", content: this}); -}; - -/** - * Loads image and split it to uniform sized frames - * - * - * @method loadFramedSpriteSheet - * @param frameWidth {Number} with of each frame - * @param frameHeight {Number} height of each frame - * @param textureName {String} if given, the frames will be cached in - format - */ -PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) -{ - this.frames = []; - var cols = Math.floor(this.texture.width / frameWidth); - var rows = Math.floor(this.texture.height / frameHeight); - - var i=0; - for (var y=0; y - + + + + + diff --git a/examples/example 16 - Displacement/pixi.js b/examples/example 16 - Displacement/pixi.js deleted file mode 100644 index 9cd1b34..0000000 --- a/examples/example 16 - Displacement/pixi.js +++ /dev/null @@ -1,10773 +0,0 @@ -/** - * @license - * Pixi.JS - v1.3.0 - * Copyright (c) 2012, Mat Groves - * http://goodboydigital.com/ - * - * Compiled: 2013-10-20 - * - * Pixi.JS is licensed under the MIT License. - * http://www.opensource.org/licenses/mit-license.php - */ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -(function(){ - - var root = this; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * @module PIXI - */ -var PIXI = PIXI || {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The Point object represents a location in a two-dimensional coordinate system, where x represents the horizontal axis and y represents the vertical axis. - * - * @class Point - * @constructor - * @param x {Number} position of the point - * @param y {Number} position of the point - */ -PIXI.Point = function(x, y) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; -} - -/** - * Creates a clone of this point - * - * @method clone - * @return {Point} a copy of the point - */ -PIXI.Point.prototype.clone = function() -{ - return new PIXI.Point(this.x, this.y); -} - -// constructor -PIXI.Point.prototype.constructor = PIXI.Point; - - -/** - * @author Mat Groves http://matgroves.com/ - */ - -/** - * the Rectangle object is an area defined by its position, as indicated by its top-left corner point (x, y) and by its width and its height. - * - * @class Rectangle - * @constructor - * @param x {Number} The X coord of the upper-left corner of the rectangle - * @param y {Number} The Y coord of the upper-left corner of the rectangle - * @param width {Number} The overall width of this rectangle - * @param height {Number} The overall height of this rectangle - */ -PIXI.Rectangle = function(x, y, width, height) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property width - * @type Number - * @default 0 - */ - this.width = width || 0; - - /** - * @property height - * @type Number - * @default 0 - */ - this.height = height || 0; -} - -/** - * Creates a clone of this Rectangle - * - * @method clone - * @return {Rectangle} a copy of the rectangle - */ -PIXI.Rectangle.prototype.clone = function() -{ - return new PIXI.Rectangle(this.x, this.y, this.width, this.height); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this Rectangle - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this Rectangle - */ -PIXI.Rectangle.prototype.contains = function(x, y) -{ - if(this.width <= 0 || this.height <= 0) - return false; - - var x1 = this.x; - if(x >= x1 && x <= x1 + this.width) - { - var y1 = this.y; - - if(y >= y1 && y <= y1 + this.height) - { - return true; - } - } - - return false; -} - -// constructor -PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; - - -/** - * @author Adrien Brault - */ - -/** - * @class Polygon - * @constructor - * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, - * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be - * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the - * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are - * Numbers. - */ -PIXI.Polygon = function(points) -{ - //if points isn't an array, use arguments as the array - if(!(points instanceof Array)) - points = Array.prototype.slice.call(arguments); - - //if this is a flat array of numbers, convert it to points - if(typeof points[0] === 'number') { - var p = []; - for(var i = 0, il = points.length; i < il; i+=2) { - p.push( - new PIXI.Point(points[i], points[i + 1]) - ); - } - - points = p; - } - - this.points = points; -} - -/** - * Creates a clone of this polygon - * - * @method clone - * @return {Polygon} a copy of the polygon - */ -PIXI.Polygon.prototype.clone = function() -{ - var points = []; - for (var i=0; i y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); - - if(intersect) inside = !inside; - } - - return inside; -} - -// constructor -PIXI.Polygon.prototype.constructor = PIXI.Polygon; - -/** - * @author Chad Engler - */ - -/** - * The Circle object can be used to specify a hit area for displayobjects - * - * @class Circle - * @constructor - * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle - * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle - * @param radius {Number} The radius of the circle - */ -PIXI.Circle = function(x, y, radius) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property radius - * @type Number - * @default 0 - */ - this.radius = radius || 0; -} - -/** - * Creates a clone of this Circle instance - * - * @method clone - * @return {Circle} a copy of the polygon - */ -PIXI.Circle.prototype.clone = function() -{ - return new PIXI.Circle(this.x, this.y, this.radius); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this circle - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this polygon - */ -PIXI.Circle.prototype.contains = function(x, y) -{ - if(this.radius <= 0) - return false; - - var dx = (this.x - x), - dy = (this.y - y), - r2 = this.radius * this.radius; - - dx *= dx; - dy *= dy; - - return (dx + dy <= r2); -} - -// constructor -PIXI.Circle.prototype.constructor = PIXI.Circle; - - -/** - * @author Chad Engler - */ - -/** - * The Ellipse object can be used to specify a hit area for displayobjects - * - * @class Ellipse - * @constructor - * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse - * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse - * @param width {Number} The overall width of this ellipse - * @param height {Number} The overall height of this ellipse - */ -PIXI.Ellipse = function(x, y, width, height) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property width - * @type Number - * @default 0 - */ - this.width = width || 0; - - /** - * @property height - * @type Number - * @default 0 - */ - this.height = height || 0; -} - -/** - * Creates a clone of this Ellipse instance - * - * @method clone - * @return {Ellipse} a copy of the ellipse - */ -PIXI.Ellipse.prototype.clone = function() -{ - return new PIXI.Ellipse(this.x, this.y, this.width, this.height); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this ellipse - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this ellipse - */ -PIXI.Ellipse.prototype.contains = function(x, y) -{ - if(this.width <= 0 || this.height <= 0) - return false; - - //normalize the coords to an ellipse with center 0,0 - //and a radius of 0.5 - var normx = ((x - this.x) / this.width) - 0.5, - normy = ((y - this.y) / this.height) - 0.5; - - normx *= normx; - normy *= normy; - - return (normx + normy < 0.25); -} - -PIXI.Ellipse.getBounds = function() -{ - return new PIXI.Rectangle(this.x, this.y, this.width, this.height); -} - -// constructor -PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; - - - -/* - * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV - * you both rock! - */ - -function determineMatrixArrayType() { - PIXI.Matrix = (typeof Float32Array !== 'undefined') ? Float32Array : Array; - return PIXI.Matrix; -} - -determineMatrixArrayType(); - -PIXI.mat3 = {}; - -PIXI.mat3.create = function() -{ - var matrix = new PIXI.Matrix(9); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 1; - matrix[5] = 0; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 1; - - return matrix; -} - - -PIXI.mat3.identity = function(matrix) -{ - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 1; - matrix[5] = 0; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 1; - - return matrix; -} - - -PIXI.mat4 = {}; - -PIXI.mat4.create = function() -{ - var matrix = new PIXI.Matrix(16); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 0; - matrix[5] = 1; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = 1; - matrix[11] = 0; - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; - - return matrix; -} - -PIXI.mat3.multiply = function (mat, mat2, dest) -{ - if (!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[0], a01 = mat[1], a02 = mat[2], - a10 = mat[3], a11 = mat[4], a12 = mat[5], - a20 = mat[6], a21 = mat[7], a22 = mat[8], - - b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], - b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], - b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; - - dest[0] = b00 * a00 + b01 * a10 + b02 * a20; - dest[1] = b00 * a01 + b01 * a11 + b02 * a21; - dest[2] = b00 * a02 + b01 * a12 + b02 * a22; - - dest[3] = b10 * a00 + b11 * a10 + b12 * a20; - dest[4] = b10 * a01 + b11 * a11 + b12 * a21; - dest[5] = b10 * a02 + b11 * a12 + b12 * a22; - - dest[6] = b20 * a00 + b21 * a10 + b22 * a20; - dest[7] = b20 * a01 + b21 * a11 + b22 * a21; - dest[8] = b20 * a02 + b21 * a12 + b22 * a22; - - return dest; -} - -PIXI.mat3.clone = function(mat) -{ - var matrix = new PIXI.Matrix(9); - - matrix[0] = mat[0]; - matrix[1] = mat[1]; - matrix[2] = mat[2]; - matrix[3] = mat[3]; - matrix[4] = mat[4]; - matrix[5] = mat[5]; - matrix[6] = mat[6]; - matrix[7] = mat[7]; - matrix[8] = mat[8]; - - return matrix; -} - -PIXI.mat3.transpose = function (mat, dest) -{ - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) { - var a01 = mat[1], a02 = mat[2], - a12 = mat[5]; - - mat[1] = mat[3]; - mat[2] = mat[6]; - mat[3] = a01; - mat[5] = mat[7]; - mat[6] = a02; - mat[7] = a12; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[3]; - dest[2] = mat[6]; - dest[3] = mat[1]; - dest[4] = mat[4]; - dest[5] = mat[7]; - dest[6] = mat[2]; - dest[7] = mat[5]; - dest[8] = mat[8]; - return dest; -} - -PIXI.mat3.toMat4 = function (mat, dest) -{ - if (!dest) { dest = PIXI.mat4.create(); } - - dest[15] = 1; - dest[14] = 0; - dest[13] = 0; - dest[12] = 0; - - dest[11] = 0; - dest[10] = mat[8]; - dest[9] = mat[7]; - dest[8] = mat[6]; - - dest[7] = 0; - dest[6] = mat[5]; - dest[5] = mat[4]; - dest[4] = mat[3]; - - dest[3] = 0; - dest[2] = mat[2]; - dest[1] = mat[1]; - dest[0] = mat[0]; - - return dest; -} - - -///// - - -PIXI.mat4.create = function() -{ - var matrix = new PIXI.Matrix(16); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 0; - matrix[5] = 1; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = 1; - matrix[11] = 0; - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; - - return matrix; -} - -PIXI.mat4.transpose = function (mat, dest) -{ - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) - { - var a01 = mat[1], a02 = mat[2], a03 = mat[3], - a12 = mat[6], a13 = mat[7], - a23 = mat[11]; - - mat[1] = mat[4]; - mat[2] = mat[8]; - mat[3] = mat[12]; - mat[4] = a01; - mat[6] = mat[9]; - mat[7] = mat[13]; - mat[8] = a02; - mat[9] = a12; - mat[11] = mat[14]; - mat[12] = a03; - mat[13] = a13; - mat[14] = a23; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[4]; - dest[2] = mat[8]; - dest[3] = mat[12]; - dest[4] = mat[1]; - dest[5] = mat[5]; - dest[6] = mat[9]; - dest[7] = mat[13]; - dest[8] = mat[2]; - dest[9] = mat[6]; - dest[10] = mat[10]; - dest[11] = mat[14]; - dest[12] = mat[3]; - dest[13] = mat[7]; - dest[14] = mat[11]; - dest[15] = mat[15]; - return dest; -} - -PIXI.mat4.multiply = function (mat, mat2, dest) -{ - if (!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; - var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; - var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; - var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - - // Cache only the current line of the second matrix - var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; - dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[4]; - b1 = mat2[5]; - b2 = mat2[6]; - b3 = mat2[7]; - dest[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[8]; - b1 = mat2[9]; - b2 = mat2[10]; - b3 = mat2[11]; - dest[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[12]; - b1 = mat2[13]; - b2 = mat2[14]; - b3 = mat2[15]; - dest[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - return dest; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The base class for all objects that are rendered on the screen. - * - * @class DisplayObject - * @constructor - */ -PIXI.DisplayObject = function() -{ - this.last = this; - this.first = this; - /** - * The coordinate of the object relative to the local coordinates of the parent. - * - * @property position - * @type Point - */ - this.position = new PIXI.Point(); - - /** - * The scale factor of the object. - * - * @property scale - * @type Point - */ - this.scale = new PIXI.Point(1,1);//{x:1, y:1}; - - /** - * The pivot point of the displayObject that it rotates around - * - * @property pivot - * @type Point - */ - this.pivot = new PIXI.Point(0,0); - - /** - * The rotation of the object in radians. - * - * @property rotation - * @type Number - */ - this.rotation = 0; - - /** - * The opacity of the object. - * - * @property alpha - * @type Number - */ - this.alpha = 1; - - /** - * The visibility of the object. - * - * @property visible - * @type Boolean - */ - this.visible = true; - - /** - * This is the defined area that will pick up mouse / touch events. It is null by default. - * Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children) - * - * @property hitArea - * @type Rectangle|Circle|Ellipse|Polygon - */ - this.hitArea = null; - - /** - * This is used to indicate if the displayObject should display a mouse hand cursor on rollover - * - * @property buttonMode - * @type Boolean - */ - this.buttonMode = false; - - /** - * Can this object be rendered - * - * @property renderable - * @type Boolean - */ - this.renderable = false; - - /** - * [read-only] The display object container that contains this display object. - * - * @property parent - * @type DisplayObjectContainer - * @readOnly - */ - this.parent = null; - - /** - * [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage. - * - * @property stage - * @type Stage - * @readOnly - */ - this.stage = null; - - /** - * [read-only] The multiplied alpha of the displayobject - * - * @property worldAlpha - * @type Number - * @readOnly - */ - this.worldAlpha = 1; - - /** - * [read-only] Whether or not the object is interactive, do not toggle directly! use the `interactive` property - * - * @property _interactive - * @type Boolean - * @readOnly - * @private - */ - this._interactive = false; - - /** - * [read-only] Current transform of the object based on world (parent) factors - * - * @property worldTransform - * @type Mat3 - * @readOnly - * @private - */ - this.worldTransform = PIXI.mat3.create()//mat3.identity(); - - /** - * [read-only] Current transform of the object locally - * - * @property localTransform - * @type Mat3 - * @readOnly - * @private - */ - this.localTransform = PIXI.mat3.create()//mat3.identity(); - - /** - * [NYI] Unkown - * - * @property color - * @type Array<> - * @private - */ - this.color = []; - - /** - * [NYI] Holds whether or not this object is dynamic, for rendering optimization - * - * @property dynamic - * @type Boolean - * @private - */ - this.dynamic = true; - - // chach that puppy! - this._sr = 0; - this._cr = 1; - - /* - * MOUSE Callbacks - */ - - /** - * A callback that is used when the users clicks on the displayObject with their mouse - * @method click - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user clicks the mouse down over the sprite - * @method mousedown - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject - * for this callback to be fired the mouse must have been pressed down over the displayObject - * @method mouseup - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject - * for this callback to be fired, The touch must have started over the displayObject - * @method mouseupoutside - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the users mouse rolls over the displayObject - * @method mouseover - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the users mouse leaves the displayObject - * @method mouseout - * @param interactionData {InteractionData} - */ - - - /* - * TOUCH Callbacks - */ - - /** - * A callback that is used when the users taps on the sprite with their finger - * basically a touch version of click - * @method tap - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user touch's over the displayObject - * @method touchstart - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases a touch over the displayObject - * @method touchend - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the touch that was over the displayObject - * for this callback to be fired, The touch must have started over the sprite - * @method touchendoutside - * @param interactionData {InteractionData} - */ -} - -// constructor -PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; - -/** - * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default - * Instead of using this function you can now simply set the interactive property to true or false - * - * @method setInteractive - * @param interactive {Boolean} - * @deprecated Simply set the `interactive` property directly - */ -PIXI.DisplayObject.prototype.setInteractive = function(interactive) -{ - this.interactive = interactive; -} - -/** - * Indicates if the sprite will have touch and mouse interactivity. It is false by default - * - * @property interactive - * @type Boolean - * @default false - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'interactive', { - get: function() { - return this._interactive; - }, - set: function(value) { - this._interactive = value; - - // TODO more to be done here.. - // need to sort out a re-crawl! - if(this.stage)this.stage.dirty = true; - } -}); - -/** - * Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. - * In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. - * To remove a mask, set this property to null. - * - * @property mask - * @type Graphics - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { - get: function() { - return this._mask; - }, - set: function(value) { - - - if(value) - { - if(this._mask) - { - value.start = this._mask.start; - value.end = this._mask.end; - } - else - { - this.addFilter(value); - value.renderable = false; - } - } - else - { - this.removeFilter(this._mask); - this._mask.renderable = true; - } - - this._mask = value; - } -}); - -/** - * Sets the filters for the displayObject. Currently there's a few limitations. - * 1: At the moment only one filter can be applied at a time.. - * 2: They cannot be nested. - * 3: There's no padding yet. - * 4: this is a webGL only feature. - * @property filters - * @type Array - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { - get: function() { - return this._filters; - }, - set: function(value) { - - //if(value == ) - if(value) - { - if(this._filters)this.removeFilter(this._filters); - this.addFilter(value) - } - else - { - if(this._filters)this.removeFilter(this._filters); - } - - this._filters = value; - } -}); - -/* - * Adds a filter to this displayObject - * - * @method addFilter - * @param mask {Graphics} the graphics object to use as a filter - * @private - */ -PIXI.DisplayObject.prototype.addFilter = function(data) -{ - //if(this.filter)return; - //this.filter = true; - - // insert a filter block.. - // TODO Onject pool thease bad boys.. - var start = new PIXI.FilterBlock(); - var end = new PIXI.FilterBlock(); - - data.start = start; - data.end = end; - - start.data = data; - end.data = data; - - start.first = start.last = this; - end.first = end.last = this; - - start.open = true; - - /* - * insert start - */ - - var childFirst = start - var childLast = start - var nextObject; - var previousObject; - - previousObject = this.first._iPrev; - - if(previousObject) - { - nextObject = previousObject._iNext; - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - } - else - { - nextObject = this; - } - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - - // now insert the end filter block.. - - /* - * insert end filter - */ - var childFirst = end - var childLast = end - var nextObject = null; - var previousObject = null; - - previousObject = this.last; - nextObject = previousObject._iNext; - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - var updateLast = this; - - var prevLast = this.last; - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = end; - } - updateLast = updateLast.parent; - } - - this.first = start; - - // if webGL... - if(this.__renderGroup) - { - this.__renderGroup.addFilterBlocks(start, end); - } - -} - -/* - * Removes the filter to this displayObject - * - * @method removeFilter - * @private - */ -PIXI.DisplayObject.prototype.removeFilter = function(data) -{ - //if(!this.filter)return; - //this.filter = false; - console.log("YUOIO") - // modify the list.. - var startBlock = data.start; - - - var nextObject = startBlock._iNext; - var previousObject = startBlock._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - if(previousObject)previousObject._iNext = nextObject; - - this.first = startBlock._iNext; - - // remove the end filter - var lastBlock = data.end; - - var nextObject = lastBlock._iNext; - var previousObject = lastBlock._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - - // this is always true too! - var tempLast = lastBlock._iPrev; - // need to make sure the parents last is updated too - var updateLast = this; - while(updateLast.last == lastBlock) - { - updateLast.last = tempLast; - updateLast = updateLast.parent; - if(!updateLast)break; - } - - // if webGL... - if(this.__renderGroup) - { - this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); - } -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.DisplayObject.prototype.updateTransform = function() -{ - // TODO OPTIMIZE THIS!! with dirty - if(this.rotation !== this.rotationCache) - { - this.rotationCache = this.rotation; - this._sr = Math.sin(this.rotation); - this._cr = Math.cos(this.rotation); - } - - var localTransform = this.localTransform; - var parentTransform = this.parent.worldTransform; - var worldTransform = this.worldTransform; - //console.log(localTransform) - localTransform[0] = this._cr * this.scale.x; - localTransform[1] = -this._sr * this.scale.y - localTransform[3] = this._sr * this.scale.x; - localTransform[4] = this._cr * this.scale.y; - - // TODO --> do we even need a local matrix??? - - var px = this.pivot.x; - var py = this.pivot.y; - - // Cache the matrix values (makes for huge speed increases!) - var a00 = localTransform[0], a01 = localTransform[1], a02 = this.position.x - localTransform[0] * px - py * localTransform[1], - a10 = localTransform[3], a11 = localTransform[4], a12 = this.position.y - localTransform[4] * py - px * localTransform[3], - - b00 = parentTransform[0], b01 = parentTransform[1], b02 = parentTransform[2], - b10 = parentTransform[3], b11 = parentTransform[4], b12 = parentTransform[5]; - - localTransform[2] = a02 - localTransform[5] = a12 - - worldTransform[0] = b00 * a00 + b01 * a10; - worldTransform[1] = b00 * a01 + b01 * a11; - worldTransform[2] = b00 * a02 + b01 * a12 + b02; - - worldTransform[3] = b10 * a00 + b11 * a10; - worldTransform[4] = b10 * a01 + b11 * a11; - worldTransform[5] = b10 * a02 + b11 * a12 + b12; - - // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! - // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); - this.worldAlpha = this.alpha * this.parent.worldAlpha; - - this.vcount = PIXI.visibleCount; - -} - -PIXI.visibleCount = 0; -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * A DisplayObjectContainer represents a collection of display objects. - * It is the base class of all display objects that act as a container for other objects. - * - * @class DisplayObjectContainer - * @extends DisplayObject - * @constructor - */ -PIXI.DisplayObjectContainer = function() -{ - PIXI.DisplayObject.call( this ); - - /** - * [read-only] The of children of this container. - * - * @property children - * @type Array - * @readOnly - */ - this.children = []; -} - -// constructor -PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); -PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; - -/** - * Adds a child to the container. - * - * @method addChild - * @param child {DisplayObject} The DisplayObject to add to the container - */ -PIXI.DisplayObjectContainer.prototype.addChild = function(child) -{ - if(child.parent != undefined) - { - - //// COULD BE THIS??? - child.parent.removeChild(child); - // return; - } - - child.parent = this; - - this.children.push(child); - - // update the stage refference.. - - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = this.stage; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // LINKED LIST // - - // modify the list.. - var childFirst = child.first - var childLast = child.last; - var nextObject; - var previousObject; - - // this could be wrong if there is a filter?? - if(this._filters || this._mask) - { - previousObject = this.last._iPrev; - } - else - { - previousObject = this.last; - } - - nextObject = previousObject._iNext; - - // always true in this case - // need to make sure the parents last is updated too - var updateLast = this; - var prevLast = previousObject; - - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = child.last; - } - updateLast = updateLast.parent; - } - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - // need to remove any render groups.. - if(this.__renderGroup) - { - // being used by a renderTexture.. if it exists then it must be from a render texture; - if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); - // add them to the new render group.. - this.__renderGroup.addDisplayObjectAndChildren(child); - } - -} - -/** - * Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown - * - * @method addChildAt - * @param child {DisplayObject} The child to add - * @param index {Number} The index to place the child in - */ -PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) -{ - if(index >= 0 && index <= this.children.length) - { - if(child.parent != undefined) - { - child.parent.removeChild(child); - } - child.parent = this; - - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = this.stage; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // modify the list.. - var childFirst = child.first; - var childLast = child.last; - var nextObject; - var previousObject; - - if(index == this.children.length) - { - previousObject = this.last; - var updateLast = this; - var prevLast = this.last; - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = child.last; - } - updateLast = updateLast.parent; - } - } - else if(index == 0) - { - previousObject = this; - } - else - { - previousObject = this.children[index-1].last; - } - - nextObject = previousObject._iNext; - - // always true in this case - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - this.children.splice(index, 0, child); - // need to remove any render groups.. - if(this.__renderGroup) - { - // being used by a renderTexture.. if it exists then it must be from a render texture; - if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); - // add them to the new render group.. - this.__renderGroup.addDisplayObjectAndChildren(child); - } - - } - else - { - throw new Error(child + " The index "+ index +" supplied is out of bounds " + this.children.length); - } -} - -/** - * [NYI] Swaps the depth of 2 displayObjects - * - * @method swapChildren - * @param child {DisplayObject} - * @param child2 {DisplayObject} - * @private - */ -PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2) -{ - /* - * this funtion needs to be recoded.. - * can be done a lot faster.. - */ - return; - - // need to fix this function :/ - /* - // TODO I already know this?? - var index = this.children.indexOf( child ); - var index2 = this.children.indexOf( child2 ); - - if ( index !== -1 && index2 !== -1 ) - { - // cool - - /* - if(this.stage) - { - // this is to satisfy the webGL batching.. - // TODO sure there is a nicer way to achieve this! - this.stage.__removeChild(child); - this.stage.__removeChild(child2); - - this.stage.__addChild(child); - this.stage.__addChild(child2); - } - - // swap the positions.. - this.children[index] = child2; - this.children[index2] = child; - - } - else - { - throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); - }*/ -} - -/** - * Returns the Child at the specified index - * - * @method getChildAt - * @param index {Number} The index to get the child from - */ -PIXI.DisplayObjectContainer.prototype.getChildAt = function(index) -{ - if(index >= 0 && index < this.children.length) - { - return this.children[index]; - } - else - { - throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); - } -} - -/** - * Removes a child from the container. - * - * @method removeChild - * @param child {DisplayObject} The DisplayObject to remove - */ -PIXI.DisplayObjectContainer.prototype.removeChild = function(child) -{ - var index = this.children.indexOf( child ); - if ( index !== -1 ) - { - // unlink // - // modify the list.. - var childFirst = child.first; - var childLast = child.last; - - var nextObject = childLast._iNext; - var previousObject = childFirst._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - - if(this.last == childLast) - { - var tempLast = childFirst._iPrev; - // need to make sure the parents last is updated too - var updateLast = this; - while(updateLast.last == childLast.last) - { - updateLast.last = tempLast; - updateLast = updateLast.parent; - if(!updateLast)break; - } - } - - childLast._iNext = null; - childFirst._iPrev = null; - - // update the stage reference.. - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = null; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // webGL trim - if(child.__renderGroup) - { - child.__renderGroup.removeDisplayObjectAndChildren(child); - } - - child.parent = undefined; - this.children.splice( index, 1 ); - } - else - { - throw new Error(child + " The supplied DisplayObject must be a child of the caller " + this); - } -} - -/* - * Updates the container's children's transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.DisplayObjectContainer.prototype.updateTransform = function() -{ - if(!this.visible)return; - - PIXI.DisplayObject.prototype.updateTransform.call( this ); - - for(var i=0,j=this.children.length; i} an array of {Texture} objects that make up the animation - */ -PIXI.MovieClip = function(textures) -{ - PIXI.Sprite.call(this, textures[0]); - - /** - * The array of textures that make up the animation - * - * @property textures - * @type Array - */ - this.textures = textures; - - /** - * The speed that the MovieClip will play at. Higher is faster, lower is slower - * - * @property animationSpeed - * @type Number - * @default 1 - */ - this.animationSpeed = 1; - - /** - * Whether or not the movie clip repeats after playing. - * - * @property loop - * @type Boolean - * @default true - */ - this.loop = true; - - /** - * Function to call when a MovieClip finishes playing - * - * @property onComplete - * @type Function - */ - this.onComplete = null; - - /** - * [read-only] The index MovieClips current frame (this may not have to be a whole number) - * - * @property currentFrame - * @type Number - * @default 0 - * @readOnly - */ - this.currentFrame = 0; - - /** - * [read-only] Indicates if the MovieClip is currently playing - * - * @property playing - * @type Boolean - * @readOnly - */ - this.playing = false; -} - -// constructor -PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); -PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; - -/** -* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures -* assigned to the MovieClip. -* -* @property totalFrames -* @type Number -* @default 0 -* @readOnly -*/ -Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { - get: function() { - - return this.textures.length; - } -}); - - -/** - * Stops the MovieClip - * - * @method stop - */ -PIXI.MovieClip.prototype.stop = function() -{ - this.playing = false; -} - -/** - * Plays the MovieClip - * - * @method play - */ -PIXI.MovieClip.prototype.play = function() -{ - this.playing = true; -} - -/** - * Stops the MovieClip and goes to a specific frame - * - * @method gotoAndStop - * @param frameNumber {Number} frame index to stop at - */ -PIXI.MovieClip.prototype.gotoAndStop = function(frameNumber) -{ - this.playing = false; - this.currentFrame = frameNumber; - var round = (this.currentFrame + 0.5) | 0; - this.setTexture(this.textures[round % this.textures.length]); -} - -/** - * Goes to a specific frame and begins playing the MovieClip - * - * @method gotoAndPlay - * @param frameNumber {Number} frame index to start at - */ -PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) -{ - this.currentFrame = frameNumber; - this.playing = true; -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.MovieClip.prototype.updateTransform = function() -{ - PIXI.Sprite.prototype.updateTransform.call(this); - - if(!this.playing)return; - - this.currentFrame += this.animationSpeed; - - var round = (this.currentFrame + 0.5) | 0; - - if(this.loop || round < this.textures.length) - { - this.setTexture(this.textures[round % this.textures.length]); - } - else if(round >= this.textures.length) - { - this.gotoAndStop(this.textures.length - 1); - if(this.onComplete) - { - this.onComplete(); - } - } -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - - -PIXI.FilterBlock = function() -{ - this.visible = true; - this.renderable = true; -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.ColorMatrixFilter = function() -{ - // set the uniforms - this.uniforms = { - matrix: {type: 'mat4', value: [1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1]}, - }; - - this.fragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform float invert;", - "uniform mat4 matrix;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", - "gl_FragColor = gl_FragColor * vColor;", - "}" - ]; - -} - - -Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { - get: function() { - return this.uniforms.matrix.value; - }, - set: function(value) { - this.uniforms.matrix.value = value; - } -}); -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - - -PIXI.GreyFilter = function() -{ - // set the uniforms - this.uniforms = { - grey: {type: 'f', value: 1}, - }; - - this.fragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D uSampler;", - "uniform float grey;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vTextureCoord);", - "gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), grey);", - "gl_FragColor = gl_FragColor * vColor;", - "}" - ]; - - this.primitiveFragmentSrc = [ - "precision mediump float;", - "varying vec4 vColor;", - "uniform float grey;", - "void main(void) {", - "gl_FragColor = vColor;", - "gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), grey);", - "gl_FragColor = gl_FragColor * vColor;", - "}" - ]; - -} - -Object.defineProperty(PIXI.GreyFilter.prototype, 'grey', { - get: function() { - return this.uniforms.grey.value; - }, - set: function(value) { - this.uniforms.grey.value = value; - } -}); - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - - -PIXI.DisplacementFilter = function(texture) -{ - // set the uniforms - - this.uniforms = { - displacementMap: {type: 'sampler2D', value:texture}, - scale: {type: 'f2', value:{x:30, y:30}}, - mapDimensions: {type: 'f2', value:{x:texture.width, y:texture.height}} - }; - - this.fragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D displacementMap;", - "uniform sampler2D uSampler;", - "uniform vec2 scale;", - "uniform vec2 mapDimensions;",// = vec2(256.0, 256.0);", - "const vec2 textureDimensions = vec2(245.0, 263.0);", - - "void main(void) {", - - "vec2 matSample = texture2D(displacementMap, vTextureCoord * (textureDimensions/mapDimensions)).xy;", - "matSample -= 0.5;", - "matSample *= scale;", - "matSample /= textureDimensions;", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x + matSample.x, vTextureCoord.y + matSample.y));", - "gl_FragColor.rgb = mix( gl_FragColor.rgb, gl_FragColor.rgb, 1.0);", - "gl_FragColor = gl_FragColor * vColor;", - - "}" - ]; - -} - -Object.defineProperty(PIXI.DisplacementFilter.prototype, 'map', { - get: function() { - return this.uniforms.displacementMap.value; - }, - set: function(value) { - this.uniforms.displacementMap.value = value; - } -}); - -Object.defineProperty(PIXI.DisplacementFilter.prototype, 'scale', { - get: function() { - return this.uniforms.scale.value; - }, - set: function(value) { - this.uniforms.scale.value = value; - } -}); -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Text Object will create a line(s) of text to split a line you can use "\n" - * - * @class Text - * @extends Sprite - * @constructor - * @param text {String} The copy that you would like the text to display - * @param [style] {Object} The style parameters - * @param [style.font] {String} default "bold 20pt Arial" The style and size of the font - * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - * @param [style.stroke] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" - * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) - * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used - * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap - */ -PIXI.Text = function(text, style) -{ - this.canvas = document.createElement("canvas"); - this.context = this.canvas.getContext("2d"); - PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas)); - - this.setText(text); - this.setStyle(style); - - this.updateText(); - this.dirty = false; -}; - -// constructor -PIXI.Text.prototype = Object.create(PIXI.Sprite.prototype); -PIXI.Text.prototype.constructor = PIXI.Text; - -/** - * Set the style of the text - * - * @method setStyle - * @param [style] {Object} The style parameters - * @param [style.font="bold 20pt Arial"] {String} The style and size of the font - * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - * @param [style.stroke="black"] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" - * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) - * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used - * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap - */ -PIXI.Text.prototype.setStyle = function(style) -{ - style = style || {}; - style.font = style.font || "bold 20pt Arial"; - style.fill = style.fill || "black"; - style.align = style.align || "left"; - style.stroke = style.stroke || "black"; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136 - style.strokeThickness = style.strokeThickness || 0; - style.wordWrap = style.wordWrap || false; - style.wordWrapWidth = style.wordWrapWidth || 100; - this.style = style; - this.dirty = true; -}; - -/** - * Set the copy for the text object. To split a line you can use "\n" - * - * @methos setText - * @param {String} text The copy that you would like the text to display - */ -PIXI.Text.prototype.setText = function(text) -{ - this.text = text.toString() || " "; - this.dirty = true; -}; - -/** - * Renders text - * - * @method updateText - * @private - */ -PIXI.Text.prototype.updateText = function() -{ - this.context.font = this.style.font; - - var outputText = this.text; - - // word wrap - // preserve original text - if(this.style.wordWrap)outputText = this.wordWrap(this.text); - - //split text into lines - var lines = outputText.split(/(?:\r\n|\r|\n)/); - - //calculate text width - var lineWidths = []; - var maxLineWidth = 0; - for (var i = 0; i < lines.length; i++) - { - var lineWidth = this.context.measureText(lines[i]).width; - lineWidths[i] = lineWidth; - maxLineWidth = Math.max(maxLineWidth, lineWidth); - } - this.canvas.width = maxLineWidth + this.style.strokeThickness; - - //calculate text height - var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; - this.canvas.height = lineHeight * lines.length; - - //set canvas text styles - this.context.fillStyle = this.style.fill; - this.context.font = this.style.font; - - this.context.strokeStyle = this.style.stroke; - this.context.lineWidth = this.style.strokeThickness; - - this.context.textBaseline = "top"; - - //draw lines line by line - for (i = 0; i < lines.length; i++) - { - var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); - - if(this.style.align == "right") - { - linePosition.x += maxLineWidth - lineWidths[i]; - } - else if(this.style.align == "center") - { - linePosition.x += (maxLineWidth - lineWidths[i]) / 2; - } - - if(this.style.stroke && this.style.strokeThickness) - { - this.context.strokeText(lines[i], linePosition.x, linePosition.y); - } - - if(this.style.fill) - { - this.context.fillText(lines[i], linePosition.x, linePosition.y); - } - } - - this.updateTexture(); -}; - -/** - * Updates texture size based on canvas size - * - * @method updateTexture - * @private - */ -PIXI.Text.prototype.updateTexture = function() -{ - this.texture.baseTexture.width = this.canvas.width; - this.texture.baseTexture.height = this.canvas.height; - this.texture.frame.width = this.canvas.width; - this.texture.frame.height = this.canvas.height; - - this._width = this.canvas.width; - this._height = this.canvas.height; - - PIXI.texturesToUpdate.push(this.texture.baseTexture); -}; - -/** - * Updates the transfor of this object - * - * @method updateTransform - * @private - */ -PIXI.Text.prototype.updateTransform = function() -{ - if(this.dirty) - { - this.updateText(); - this.dirty = false; - } - - PIXI.Sprite.prototype.updateTransform.call(this); -}; - -/* - * http://stackoverflow.com/users/34441/ellisbben - * great solution to the problem! - * - * @method determineFontHeight - * @param fontStyle {Object} - * @private - */ -PIXI.Text.prototype.determineFontHeight = function(fontStyle) -{ - // build a little reference dictionary so if the font style has been used return a - // cached version... - var result = PIXI.Text.heightCache[fontStyle]; - - if(!result) - { - var body = document.getElementsByTagName("body")[0]; - var dummy = document.createElement("div"); - var dummyText = document.createTextNode("M"); - dummy.appendChild(dummyText); - dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); - body.appendChild(dummy); - - result = dummy.offsetHeight; - PIXI.Text.heightCache[fontStyle] = result; - - body.removeChild(dummy); - } - - return result; -}; - -/** - * A Text Object will apply wordwrap - * - * @method wordWrap - * @param text {String} - * @private - */ -PIXI.Text.prototype.wordWrap = function(text) -{ - // search good wrap position - var searchWrapPos = function(ctx, text, start, end, wrapWidth) - { - var p = Math.floor((end-start) / 2) + start; - if(p == start) { - return 1; - } - - if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) - { - if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) - { - return p; - } - else - { - return arguments.callee(ctx, text, p, end, wrapWidth); - } - } - else - { - return arguments.callee(ctx, text, start, p, wrapWidth); - } - }; - - var lineWrap = function(ctx, text, wrapWidth) - { - if(ctx.measureText(text).width <= wrapWidth || text.length < 1) - { - return text; - } - var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); - return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); - }; - - var result = ""; - var lines = text.split("\n"); - for (var i = 0; i < lines.length; i++) - { - result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; - } - - return result; -}; - -/** - * Destroys this text object - * - * @method destroy - * @param destroyTexture {Boolean} - */ -PIXI.Text.prototype.destroy = function(destroyTexture) -{ - if(destroyTexture) - { - this.texture.destroy(); - } - -}; - -PIXI.Text.heightCache = {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" - * You can generate the fnt files using - * http://www.angelcode.com/products/bmfont/ for windows or - * http://www.bmglyph.com/ for mac. - * - * @class BitmapText - * @extends DisplayObjectContainer - * @constructor - * @param text {String} The copy that you would like the text to display - * @param style {Object} The style parameters - * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - */ -PIXI.BitmapText = function(text, style) -{ - PIXI.DisplayObjectContainer.call(this); - - this.setText(text); - this.setStyle(style); - this.updateText(); - this.dirty = false - -}; - -// constructor -PIXI.BitmapText.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); -PIXI.BitmapText.prototype.constructor = PIXI.BitmapText; - -/** - * Set the copy for the text object - * - * @method setText - * @param text {String} The copy that you would like the text to display - */ -PIXI.BitmapText.prototype.setText = function(text) -{ - this.text = text || " "; - this.dirty = true; -}; - -/** - * Set the style of the text - * - * @method setStyle - * @param style {Object} The style parameters - * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - */ -PIXI.BitmapText.prototype.setStyle = function(style) -{ - style = style || {}; - style.align = style.align || "left"; - this.style = style; - - var font = style.font.split(" "); - this.fontName = font[font.length - 1]; - this.fontSize = font.length >= 2 ? parseInt(font[font.length - 2], 10) : PIXI.BitmapText.fonts[this.fontName].size; - - this.dirty = true; -}; - -/** - * Renders text - * - * @method updateText - * @private - */ -PIXI.BitmapText.prototype.updateText = function() -{ - var data = PIXI.BitmapText.fonts[this.fontName]; - var pos = new PIXI.Point(); - var prevCharCode = null; - var chars = []; - var maxLineWidth = 0; - var lineWidths = []; - var line = 0; - var scale = this.fontSize / data.size; - for(var i = 0; i < this.text.length; i++) - { - var charCode = this.text.charCodeAt(i); - if(/(?:\r\n|\r|\n)/.test(this.text.charAt(i))) - { - lineWidths.push(pos.x); - maxLineWidth = Math.max(maxLineWidth, pos.x); - line++; - - pos.x = 0; - pos.y += data.lineHeight; - prevCharCode = null; - continue; - } - - var charData = data.chars[charCode]; - if(!charData) continue; - - if(prevCharCode && charData[prevCharCode]) - { - pos.x += charData.kerning[prevCharCode]; - } - chars.push({texture:charData.texture, line: line, charCode: charCode, position: new PIXI.Point(pos.x + charData.xOffset, pos.y + charData.yOffset)}); - pos.x += charData.xAdvance; - - prevCharCode = charCode; - } - - lineWidths.push(pos.x); - maxLineWidth = Math.max(maxLineWidth, pos.x); - - var lineAlignOffsets = []; - for(i = 0; i <= line; i++) - { - var alignOffset = 0; - if(this.style.align == "right") - { - alignOffset = maxLineWidth - lineWidths[i]; - } - else if(this.style.align == "center") - { - alignOffset = (maxLineWidth - lineWidths[i]) / 2; - } - lineAlignOffsets.push(alignOffset); - } - - for(i = 0; i < chars.length; i++) - { - var c = new PIXI.Sprite(chars[i].texture)//PIXI.Sprite.fromFrame(chars[i].charCode); - c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale; - c.position.y = chars[i].position.y * scale; - c.scale.x = c.scale.y = scale; - this.addChild(c); - } - - this.width = pos.x * scale; - this.height = (pos.y + data.lineHeight) * scale; -}; - -/** - * Updates the transfor of this object - * - * @method updateTransform - * @private - */ -PIXI.BitmapText.prototype.updateTransform = function() -{ - if(this.dirty) - { - while(this.children.length > 0) - { - this.removeChild(this.getChildAt(0)); - } - this.updateText(); - - this.dirty = false; - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -}; - -PIXI.BitmapText.fonts = {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - /** - * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive - * This manager also supports multitouch. - * - * @class InteractionManager - * @constructor - * @param stage {Stage} The stage to handle interactions - */ -PIXI.InteractionManager = function(stage) -{ - /** - * a refference to the stage - * - * @property stage - * @type Stage - */ - this.stage = stage; - - /** - * the mouse data - * - * @property mouse - * @type InteractionData - */ - this.mouse = new PIXI.InteractionData(); - - /** - * an object that stores current touches (InteractionData) by id reference - * - * @property touchs - * @type Object - */ - this.touchs = {}; - - - - // helpers - this.tempPoint = new PIXI.Point(); - //this.tempMatrix = mat3.create(); - - this.mouseoverEnabled = true; - - //tiny little interactiveData pool! - this.pool = []; - - this.interactiveItems = []; - this.interactionDOMElement = null; - - //this will make it so that you dont have to call bind all the time - this.onMouseMove = this.onMouseMove.bind( this ); - this.onMouseDown = this.onMouseDown.bind(this); - this.onMouseOut = this.onMouseOut.bind(this); - this.onMouseUp = this.onMouseUp.bind(this); - - this.onTouchStart = this.onTouchStart.bind(this); - this.onTouchEnd = this.onTouchEnd.bind(this); - this.onTouchMove = this.onTouchMove.bind(this); - - - this.last = 0; -} - -// constructor -PIXI.InteractionManager.prototype.constructor = PIXI.InteractionManager; - -/** - * Collects an interactive sprite recursively to have their interactions managed - * - * @method collectInteractiveSprite - * @param displayObject {DisplayObject} the displayObject to collect - * @param iParent {DisplayObject} - * @private - */ -PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObject, iParent) -{ - var children = displayObject.children; - var length = children.length; - - /// make an interaction tree... {item.__interactiveParent} - for (var i = length-1; i >= 0; i--) - { - var child = children[i]; - -// if(child.visible) { - // push all interactive bits - if(child.interactive) - { - iParent.interactiveChildren = true; - //child.__iParent = iParent; - this.interactiveItems.push(child); - - if(child.children.length > 0) - { - this.collectInteractiveSprite(child, child); - } - } - else - { - child.__iParent = null; - - if(child.children.length > 0) - { - this.collectInteractiveSprite(child, iParent); - } - } -// } - } -} - -/** - * Sets the target for event delegation - * - * @method setTarget - * @param target {WebGLRenderer|CanvasRenderer} the renderer to bind events to - * @private - */ -PIXI.InteractionManager.prototype.setTarget = function(target) -{ - this.target = target; - - //check if the dom element has been set. If it has don't do anything - if( this.interactionDOMElement === null ) { - - this.setTargetDomElement( target.view ); - } - - document.body.addEventListener('mouseup', this.onMouseUp, true); -} - - -/** - * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM - * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element - * to receive those events - * - * @method setTargetDomElement - * @param domElement {DOMElement} the dom element which will receive mouse and touch events - * @private - */ -PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) -{ - //remove previouse listeners - if( this.interactionDOMElement !== null ) - { - this.interactionDOMElement.style['-ms-content-zooming'] = ''; - this.interactionDOMElement.style['-ms-touch-action'] = ''; - - this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); - this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); - this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); - - // aint no multi touch just yet! - this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); - this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); - this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); - } - - - if (window.navigator.msPointerEnabled) - { - // time to remove some of that zoom in ja.. - domElement.style['-ms-content-zooming'] = 'none'; - domElement.style['-ms-touch-action'] = 'none'; - - // DO some window specific touch! - } - - this.interactionDOMElement = domElement; - - domElement.addEventListener('mousemove', this.onMouseMove, true); - domElement.addEventListener('mousedown', this.onMouseDown, true); - domElement.addEventListener('mouseout', this.onMouseOut, true); - - // aint no multi touch just yet! - domElement.addEventListener('touchstart', this.onTouchStart, true); - domElement.addEventListener('touchend', this.onTouchEnd, true); - domElement.addEventListener('touchmove', this.onTouchMove, true); -} - - -/** - * updates the state of interactive objects - * - * @method update - * @private - */ -PIXI.InteractionManager.prototype.update = function() -{ - if(!this.target)return; - - // frequency of 30fps?? - var now = Date.now(); - var diff = now - this.last; - diff = (diff * 30) / 1000; - if(diff < 1)return; - this.last = now; - // - - // ok.. so mouse events?? - // yes for now :) - // OPTIMSE - how often to check?? - if(this.dirty) - { - this.dirty = false; - - var len = this.interactiveItems.length; - - for (var i=0; i < len; i++) { - this.interactiveItems[i].interactiveChildren = false; - } - - this.interactiveItems = []; - - if(this.stage.interactive)this.interactiveItems.push(this.stage); - // go through and collect all the objects that are interactive.. - this.collectInteractiveSprite(this.stage, this.stage); - } - - // loop through interactive objects! - var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - - //if(!item.visible)continue; - - // OPTIMISATION - only calculate every time if the mousemove function exists.. - // OK so.. does the object have any other interactive functions? - // hit-test the clip! - - - if(item.mouseover || item.mouseout || item.buttonMode) - { - // ok so there are some functions so lets hit test it.. - item.__hit = this.hitTest(item, this.mouse); - this.mouse.target = item; - // ok so deal with interactions.. - // loks like there was a hit! - if(item.__hit) - { - if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; - - if(!item.__isOver) - { - - if(item.mouseover)item.mouseover(this.mouse); - item.__isOver = true; - } - } - else - { - if(item.__isOver) - { - // roll out! - if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; - } - } - } - - // ---> - } -} - -/** - * Is called when the mouse moves accross the renderer element - * - * @method onMouseMove - * @param event {Event} The DOM event of the mouse moving - * @private - */ -PIXI.InteractionManager.prototype.onMouseMove = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - // TODO optimize by not check EVERY TIME! maybe half as often? // - var rect = this.interactionDOMElement.getBoundingClientRect(); - - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); - - var length = this.interactiveItems.length; - var global = this.mouse.global; - - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mousemove) - { - //call the function! - item.mousemove(this.mouse); - } - } -} - -/** - * Is called when the mouse button is pressed down on the renderer element - * - * @method onMouseDown - * @param event {Event} The DOM event of a mouse button being pressed down - * @private - */ -PIXI.InteractionManager.prototype.onMouseDown = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - - // loop through inteaction tree... - // hit test each item! -> - // get interactive items under point?? - //stage.__i - var length = this.interactiveItems.length; - var global = this.mouse.global; - - var index = 0; - var parent = this.stage; - - // while - // hit test - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mousedown || item.click) - { - item.__mouseIsDown = true; - item.__hit = this.hitTest(item, this.mouse); - - if(item.__hit) - { - //call the function! - if(item.mousedown)item.mousedown(this.mouse); - item.__isDown = true; - - // just the one! - if(!item.interactiveChildren)break; - } - } - } -} - - -PIXI.InteractionManager.prototype.onMouseOut = function(event) -{ - var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.__isOver) - { - this.mouse.target = item; - if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; - } - } -} - -/** - * Is called when the mouse button is released on the renderer element - * - * @method onMouseUp - * @param event {Event} The DOM event of a mouse button being released - * @private - */ -PIXI.InteractionManager.prototype.onMouseUp = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - - var global = this.mouse.global; - - - var length = this.interactiveItems.length; - var up = false; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mouseup || item.mouseupoutside || item.click) - { - item.__hit = this.hitTest(item, this.mouse); - - if(item.__hit && !up) - { - //call the function! - if(item.mouseup) - { - item.mouseup(this.mouse); - } - if(item.__isDown) - { - if(item.click)item.click(this.mouse); - } - - if(!item.interactiveChildren)up = true; - } - else - { - if(item.__isDown) - { - if(item.mouseupoutside)item.mouseupoutside(this.mouse); - } - } - - item.__isDown = false; - } - } -} - -/** - * Tests if the current mouse coords hit a sprite - * - * @method hitTest - * @param item {DisplayObject} The displayObject to test for a hit - * @param interactionData {InteractionData} The interactiondata object to update in the case of a hit - * @private - */ -PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) -{ - var global = interactionData.global; - - if(item.vcount !== PIXI.visibleCount)return false; - - var isSprite = (item instanceof PIXI.Sprite), - worldTransform = item.worldTransform, - a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10), - x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, - y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - interactionData.target = item; - - //a sprite or display object with a hit area defined - if(item.hitArea && item.hitArea.contains) { - if(item.hitArea.contains(x, y)) { - //if(isSprite) - interactionData.target = item; - - return true; - } - - return false; - } - // a sprite with no hitarea defined - else if(isSprite) - { - var width = item.texture.frame.width, - height = item.texture.frame.height, - x1 = -width * item.anchor.x, - y1; - - if(x > x1 && x < x1 + width) - { - y1 = -height * item.anchor.y; - - if(y > y1 && y < y1 + height) - { - // set the target property if a hit is true! - interactionData.target = item - return true; - } - } - } - - var length = item.children.length; - - for (var i = 0; i < length; i++) - { - var tempItem = item.children[i]; - var hit = this.hitTest(tempItem, interactionData); - if(hit) - { - // hmm.. TODO SET CORRECT TARGET? - interactionData.target = item - return true; - } - } - - return false; -} - -/** - * Is called when a touch is moved accross the renderer element - * - * @method onTouchMove - * @param event {Event} The DOM event of a touch moving accross the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchMove = function(event) -{ - var rect = this.interactionDOMElement.getBoundingClientRect(); - var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - var touchData = this.touchs[touchEvent.identifier]; - touchData.originalEvent = event || window.event; - - // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - } - - var length = this.interactiveItems.length; - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - if(item.touchmove)item.touchmove(touchData); - } -} - -/** - * Is called when a touch is started on the renderer element - * - * @method onTouchStart - * @param event {Event} The DOM event of a touch starting on the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchStart = function(event) -{ - var rect = this.interactionDOMElement.getBoundingClientRect(); - - var changedTouches = event.changedTouches; - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - - var touchData = this.pool.pop(); - if(!touchData)touchData = new PIXI.InteractionData(); - - touchData.originalEvent = event || window.event; - - this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - - var length = this.interactiveItems.length; - - for (var j = 0; j < length; j++) - { - var item = this.interactiveItems[j]; - - if(item.touchstart || item.tap) - { - item.__hit = this.hitTest(item, touchData); - - if(item.__hit) - { - //call the function! - if(item.touchstart)item.touchstart(touchData); - item.__isDown = true; - item.__touchData = touchData; - - if(!item.interactiveChildren)break; - } - } - } - } -} - -/** - * Is called when a touch is ended on the renderer element - * - * @method onTouchEnd - * @param event {Event} The DOM event of a touch ending on the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchEnd = function(event) -{ - //this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.interactionDOMElement.getBoundingClientRect(); - var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - var touchData = this.touchs[touchEvent.identifier]; - var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - - var length = this.interactiveItems.length; - for (var j = 0; j < length; j++) - { - var item = this.interactiveItems[j]; - var itemTouchData = item.__touchData; // <-- Here! - item.__hit = this.hitTest(item, touchData); - - if(itemTouchData == touchData) - { - // so this one WAS down... - touchData.originalEvent = event || window.event; - // hitTest?? - - if(item.touchend || item.tap) - { - if(item.__hit && !up) - { - if(item.touchend)item.touchend(touchData); - if(item.__isDown) - { - if(item.tap)item.tap(touchData); - } - - if(!item.interactiveChildren)up = true; - } - else - { - if(item.__isDown) - { - if(item.touchendoutside)item.touchendoutside(touchData); - } - } - - item.__isDown = false; - } - - item.__touchData = null; - - } - else - { - - } - } - // remove the touch.. - this.pool.push(touchData); - this.touchs[touchEvent.identifier] = null; - } -} - -/** - * Holds all information related to an Interaction event - * - * @class InteractionData - * @constructor - */ -PIXI.InteractionData = function() -{ - /** - * This point stores the global coords of where the touch/mouse event happened - * - * @property global - * @type Point - */ - this.global = new PIXI.Point(); - - // this is here for legacy... but will remove - this.local = new PIXI.Point(); - - /** - * The target Sprite that was interacted with - * - * @property target - * @type Sprite - */ - this.target; - - /** - * When passed to an event handler, this will be the original DOM Event that was captured - * - * @property originalEvent - * @type Event - */ - this.originalEvent; -} - -/** - * This will return the local coords of the specified displayObject for this InteractionData - * - * @method getLocalPosition - * @param displayObject {DisplayObject} The DisplayObject that you would like the local coords off - * @return {Point} A point containing the coords of the InteractionData position relative to the DisplayObject - */ -PIXI.InteractionData.prototype.getLocalPosition = function(displayObject) -{ - var worldTransform = displayObject.worldTransform; - var global = this.global; - - // do a cheeky transform to get the mouse coords; - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - // set the mouse coords... - return new PIXI.Point(a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, - a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id) -} - -// constructor -PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Stage represents the root of the display tree. Everything connected to the stage is rendered - * - * @class Stage - * @extends DisplayObjectContainer - * @constructor - * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format - * like: 0xFFFFFF for white - */ -PIXI.Stage = function(backgroundColor) -{ - PIXI.DisplayObjectContainer.call( this ); - - /** - * [read-only] Current transform of the object based on world (parent) factors - * - * @property worldTransform - * @type Mat3 - * @readOnly - * @private - */ - this.worldTransform = PIXI.mat3.create(); - - /** - * Whether or not the stage is interactive - * - * @property interactive - * @type Boolean - */ - this.interactive = true; - - /** - * The interaction manage for this stage, manages all interactive activity on the stage - * - * @property interactive - * @type InteractionManager - */ - this.interactionManager = new PIXI.InteractionManager(this); - - /** - * Whether the stage is dirty and needs to have interactions updated - * - * @property dirty - * @type Boolean - * @private - */ - this.dirty = true; - - this.__childrenAdded = []; - this.__childrenRemoved = []; - - //the stage is it's own stage - this.stage = this; - - //optimize hit detection a bit - this.stage.hitArea = new PIXI.Rectangle(0,0,100000, 100000); - - this.setBackgroundColor(backgroundColor); - this.worldVisible = true; -} - -// constructor -PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Stage.prototype.constructor = PIXI.Stage; - -/** - * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. - * This is useful for when you have other DOM elements ontop of the Canvas element. - * - * @method setInteractionDelegate - * @param domElement {DOMElement} This new domElement which will receive mouse/touch events - */ -PIXI.Stage.prototype.setInteractionDelegate = function(domElement) -{ - this.interactionManager.setTargetDomElement( domElement ); -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.Stage.prototype.updateTransform = function() -{ - this.worldAlpha = 1; - this.vcount = PIXI.visibleCount; - - for(var i=0,j=this.children.length; i> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; -} - -/** - * A polyfill for Function.prototype.bind - * - * @method bind - */ -if (typeof Function.prototype.bind != 'function') { - Function.prototype.bind = (function () { - var slice = Array.prototype.slice; - return function (thisArg) { - var target = this, boundArgs = slice.call(arguments, 1); - - if (typeof target != 'function') throw new TypeError(); - - function bound() { - var args = boundArgs.concat(slice.call(arguments)); - target.apply(this instanceof bound ? this : thisArg, args); - } - - bound.prototype = (function F(proto) { - proto && (F.prototype = proto); - if (!(this instanceof F)) return new F; - })(target.prototype); - - return bound; - }; - })(); -} - -/** - * A wrapper for ajax requests to be handled cross browser - * - * @class AjaxRequest - * @constructor - */ -var AjaxRequest = PIXI.AjaxRequest = function() -{ - var activexmodes = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Microsoft.XMLHTTP"] //activeX versions to check for in IE - - if (window.ActiveXObject) - { //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken) - for (var i=0; i>>>>>>>>") - console.log("_") - var safe = 0; - var tmp = item.first; - console.log(tmp); - - while(tmp._iNext) - { - safe++; - tmp = tmp._iNext; - console.log(tmp); - // console.log(tmp); - - if(safe > 100) - { - console.log("BREAK") - break - } - } -} - - - - - - -/** - * https://github.com/mrdoob/eventtarget.js/ - * THankS mr DOob! - */ - -/** - * Adds event emitter functionality to a class - * - * @class EventTarget - * @example - * function MyEmitter() { - * PIXI.EventTarget.call(this); //mixes in event target stuff - * } - * - * var em = new MyEmitter(); - * em.emit({ type: 'eventName', data: 'some data' }); - */ -PIXI.EventTarget = function () { - - var listeners = {}; - - this.addEventListener = this.on = function ( type, listener ) { - - - if ( listeners[ type ] === undefined ) { - - listeners[ type ] = []; - - } - - if ( listeners[ type ].indexOf( listener ) === - 1 ) { - - listeners[ type ].push( listener ); - } - - }; - - this.dispatchEvent = this.emit = function ( event ) { - - if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { - - return; - - } - - for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { - - listeners[ event.type ][ i ]( event ); - - } - - }; - - this.removeEventListener = this.off = function ( type, listener ) { - - var index = listeners[ type ].indexOf( listener ); - - if ( index !== - 1 ) { - - listeners[ type ].splice( index, 1 ); - - } - - }; - -}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * This helper function will automatically detect which renderer you should be using. - * WebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by - * the browser then this function will return a canvas renderer - * - * @method autoDetectRenderer - * @static - * @param width {Number} the width of the renderers view - * @param height {Number} the height of the renderers view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) - * - * antialias - */ -PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) -{ - if(!width)width = 800; - if(!height)height = 600; - - // BORROWED from Mr Doob (mrdoob.com) - var webgl = ( function () { try { var canvas = document.createElement( 'canvas' ); return !! window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ); } catch( e ) { return false; } } )(); - - if(webgl) - { - var ie = (navigator.userAgent.toLowerCase().indexOf('msie') != -1); - webgl = !ie; - } - - //console.log(webgl); - if( webgl ) - { - return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); - } - - return new PIXI.CanvasRenderer(width, height, view, transparent); -}; - - - -/* - PolyK library - url: http://polyk.ivank.net - Released under MIT licence. - - Copyright (c) 2012 Ivan Kuckir - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - - This is an amazing lib! - - slightly modified by mat groves (matgroves.com); -*/ - -PIXI.PolyK = {}; - -/** - * Triangulates shapes for webGL graphic fills - * - * @method Triangulate - * @namespace PolyK - * @constructor - */ -PIXI.PolyK.Triangulate = function(p) -{ - var sign = true; - - var n = p.length>>1; - if(n<3) return []; - var tgs = []; - var avl = []; - for(var i=0; i 3) - { - var i0 = avl[(i+0)%al]; - var i1 = avl[(i+1)%al]; - var i2 = avl[(i+2)%al]; - - var ax = p[2*i0], ay = p[2*i0+1]; - var bx = p[2*i1], by = p[2*i1+1]; - var cx = p[2*i2], cy = p[2*i2+1]; - - var earFound = false; - if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) - { - earFound = true; - for(var j=0; j 3*al) - { - // need to flip flip reverse it! - // reset! - if(sign) - { - var tgs = []; - avl = []; - for(var i=0; i= 0) && (v >= 0) && (u + v < 1); -} - -/** - * Checks if a shape is convex - * - * @class _convex - * @namespace PolyK - * @private - */ -PIXI.PolyK._convex = function(ax, ay, bx, by, cx, cy, sign) -{ - return ((ay-by)*(cx-bx) + (bx-ax)*(cy-by) >= 0) == sign; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/* - * the default suoer fast shader! - */ - -PIXI.shaderFragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", - "gl_FragColor = gl_FragColor * vColor;", - "}" -]; - -PIXI.shaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - - "uniform vec2 projectionVector;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "void main(void) {", - "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" -]; - -/* - * the triangle strip shader.. - */ - -PIXI.stripShaderFragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform float alpha;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", - "gl_FragColor = gl_FragColor * alpha;", - "}" -]; - - -PIXI.stripShaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" -]; - -/* - * primitive shader.. - */ - -PIXI.primitiveShaderFragmentSrc = [ - "precision mediump float;", - "varying vec4 vColor;", - "void main(void) {", - "gl_FragColor = vColor;", - "}" -]; - -PIXI.primitiveShaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec4 aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "uniform float alpha;", - "varying vec4 vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vColor = aColor * alpha;", - "}" -]; - -PIXI.shaderStack = []; - -PIXI.initPrimitiveShader = function() -{ - var gl = PIXI.gl; - - var shaderProgram = PIXI.compileProgram(PIXI.primitiveShaderVertexSrc, PIXI.primitiveShaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); - - - //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - //gl.enableVertexAttribArray(shaderProgram.colorAttribute); -//gl.enableVertexAttribArray(program.textureCoordAttribute); - - shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); - - PIXI.primitiveProgram = shaderProgram; - - -} - -PIXI.initDefaultShader = function() -{ - PIXI.defaultShader = new PIXI.PixiShader(); - PIXI.defaultShader.init(); - PIXI.pushShader(PIXI.defaultShader); - /* - PIXI.shaderStack.push(PIXI.defaultShader); - PIXI.current*/ -} - -PIXI.initDefaultStripShader = function() -{ - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.stripShaderVertexSrc, PIXI.stripShaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); - shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); - - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.stripShaderProgram = shaderProgram; -} - -PIXI.CompileVertexShader = function(gl, shaderSrc) -{ - return PIXI._CompileShader(gl, shaderSrc, gl.VERTEX_SHADER); -} - -PIXI.CompileFragmentShader = function(gl, shaderSrc) -{ - return PIXI._CompileShader(gl, shaderSrc, gl.FRAGMENT_SHADER); -} - -PIXI._CompileShader = function(gl, shaderSrc, shaderType) -{ - var src = shaderSrc.join("\n"); - var shader = gl.createShader(shaderType); - gl.shaderSource(shader, src); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - alert(gl.getShaderInfoLog(shader)); - return null; - } - - return shader; -} - - -PIXI.compileProgram = function(vertexSrc, fragmentSrc) -{ - var gl = PIXI.gl; - var fragmentShader = PIXI.CompileFragmentShader(gl, fragmentSrc); - var vertexShader = PIXI.CompileVertexShader(gl, vertexSrc); - - var shaderProgram = gl.createProgram(); - - gl.attachShader(shaderProgram, vertexShader); - gl.attachShader(shaderProgram, fragmentShader); - gl.linkProgram(shaderProgram); - - if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { - alert("Could not initialise shaders"); - } - - return shaderProgram; -} - -PIXI.pushShader = function(shader) -{ - PIXI.shaderStack.push(shader); - - var gl = PIXI.gl; - - var shaderProgram = shader.program; - - - // map uniforms.. - gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - - shader.syncUniforms(); - - PIXI.currentShader = shaderProgram; -} - - -PIXI.popShader = function() -{ - var gl = PIXI.gl; - var lastProgram = PIXI.shaderStack.pop(); - - var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; - - gl.useProgram(shaderProgram); - - PIXI.currentShader = shaderProgram; -} - -PIXI.activatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.primitiveProgram); - gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); -} - -PIXI.deactivatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.currentShader); - gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -PIXI.PixiShader = function() -{ - // the webGL program.. - this.program; - - this.fragmentSrc = [ - "precision lowp float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", - "}" - ]; - -} - -PIXI.PixiShader.prototype.init = function() -{ - var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) - - var gl = PIXI.gl; - - gl.useProgram(program); - - // get the default shader bits! - program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); - program.colorAttribute = gl.getAttribLocation(program, "aColor"); - program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); - - program.projectionVector = gl.getUniformLocation(program, "projectionVector"); - program.samplerUniform = gl.getUniformLocation(program, "uSampler"); - - // add those custom shaders! - for (var key in this.uniforms) - { - // get the uniform locations.. - program[key] = gl.getUniformLocation(program, key); - } - - this.program = program; -} - -PIXI.PixiShader.prototype.syncUniforms = function() -{ - var gl = PIXI.gl; - - for (var key in this.uniforms) - { - //var - var type = this.uniforms[key].type; - - // need to grow this! - if(type == "f") - { - gl.uniform1f(this.program[key], this.uniforms[key].value); - } - if(type == "f2") - { - gl.uniform2f(this.program[key], this.uniforms[key].value.x, this.uniforms[key].value.y); - } - else if(type == "mat4") - { - gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); - } - else if(type == "sampler2D") - { - // first texture... - var texture = this.uniforms[key].value; - - gl.activeTexture(gl.TEXTURE1); - gl.bindTexture(gl.TEXTURE_2D, texture.baseTexture._glTexture); - - gl.uniform1i(this.program[key], 1); - - - // activate texture.. - // gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); - // gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); - } - } - -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A set of functions used by the webGL renderer to draw the primitive graphics data - * - * @class CanvasGraphics - */ -PIXI.WebGLGraphics = function() -{ - -} - -/** - * Renders the graphics object - * - * @static - * @private - * @method renderGraphics - * @param graphics {Graphics} - * @param projection {Object} - */ -PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) -{ - var gl = PIXI.gl; - - if(!graphics._webGL)graphics._webGL = {points:[], indices:[], lastIndex:0, - buffer:gl.createBuffer(), - indexBuffer:gl.createBuffer()}; - - if(graphics.dirty) - { - graphics.dirty = false; - - if(graphics.clearDirty) - { - graphics.clearDirty = false; - - graphics._webGL.lastIndex = 0; - graphics._webGL.points = []; - graphics._webGL.indices = []; - - } - - PIXI.WebGLGraphics.updateGraphics(graphics); - } - - - PIXI.activatePrimitiveShader(); - - // This could be speeded up fo sure! - var m = PIXI.mat3.clone(graphics.worldTransform); - - PIXI.mat3.transpose(m); - - // set the matrix transform for the - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - gl.uniformMatrix3fv(PIXI.primitiveProgram.translationMatrix, false, m); - - gl.uniform2f(PIXI.primitiveProgram.projectionVector, projection.x, projection.y); - - gl.uniform1f(PIXI.primitiveProgram.alpha, graphics.worldAlpha); - - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - - // WHY DOES THIS LINE NEED TO BE THERE??? - //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - // its not even used.. but need to be set or it breaks? - // only on pc though.. - - gl.vertexAttribPointer(PIXI.primitiveProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 4 * 6, 0); - gl.vertexAttribPointer(PIXI.primitiveProgram.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4); - - // set the index buffer! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); - - gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); - - PIXI.deactivatePrimitiveShader(); - - // return to default shader... -// PIXI.activateShader(PIXI.defaultShader); -} - -/** - * Updates the graphics object - * - * @static - * @private - * @method updateGraphics - * @param graphics {Graphics} - */ -PIXI.WebGLGraphics.updateGraphics = function(graphics) -{ - for (var i=graphics._webGL.lastIndex; i < graphics.graphicsData.length; i++) - { - var data = graphics.graphicsData[i]; - - if(data.type == PIXI.Graphics.POLY) - { - if(data.fill) - { - if(data.points.length>3) - PIXI.WebGLGraphics.buildPoly(data, graphics._webGL); - } - - if(data.lineWidth > 0) - { - PIXI.WebGLGraphics.buildLine(data, graphics._webGL); - } - } - else if(data.type == PIXI.Graphics.RECT) - { - PIXI.WebGLGraphics.buildRectangle(data, graphics._webGL); - } - else if(data.type == PIXI.Graphics.CIRC || data.type == PIXI.Graphics.ELIP) - { - PIXI.WebGLGraphics.buildCircle(data, graphics._webGL); - } - }; - - graphics._webGL.lastIndex = graphics.graphicsData.length; - - var gl = PIXI.gl; - - graphics._webGL.glPoints = new Float32Array(graphics._webGL.points); - - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - gl.bufferData(gl.ARRAY_BUFFER, graphics._webGL.glPoints, gl.STATIC_DRAW); - - graphics._webGL.glIndicies = new Uint16Array(graphics._webGL.indices); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.glIndicies, gl.STATIC_DRAW); -} - -/** - * Builds a rectangle to draw - * - * @static - * @private - * @method buildRectangle - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData) -{ - // --- // - // need to convert points to a nice regular data - // - var rectData = graphicsData.points; - var x = rectData[0]; - var y = rectData[1]; - var width = rectData[2]; - var height = rectData[3]; - - - if(graphicsData.fill) - { - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var verts = webGLData.points; - var indices = webGLData.indices; - - var vertPos = verts.length/6; - - // start - verts.push(x, y); - verts.push(r, g, b, alpha); - - verts.push(x + width, y); - verts.push(r, g, b, alpha); - - verts.push(x , y + height); - verts.push(r, g, b, alpha); - - verts.push(x + width, y + height); - verts.push(r, g, b, alpha); - - // insert 2 dead triangles.. - indices.push(vertPos, vertPos, vertPos+1, vertPos+2, vertPos+3, vertPos+3) - } - - if(graphicsData.lineWidth) - { - graphicsData.points = [x, y, - x + width, y, - x + width, y + height, - x, y + height, - x, y]; - - PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); - } - -} - -/** - * Builds a circle to draw - * - * @static - * @private - * @method buildCircle - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData) -{ - // --- // - // need to convert points to a nice regular data - // - var rectData = graphicsData.points; - var x = rectData[0]; - var y = rectData[1]; - var width = rectData[2]; - var height = rectData[3]; - - var totalSegs = 40; - var seg = (Math.PI * 2) / totalSegs ; - - if(graphicsData.fill) - { - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var verts = webGLData.points; - var indices = webGLData.indices; - - var vecPos = verts.length/6; - - indices.push(vecPos); - - for (var i=0; i < totalSegs + 1 ; i++) - { - verts.push(x,y, r, g, b, alpha); - - verts.push(x + Math.sin(seg * i) * width, - y + Math.cos(seg * i) * height, - r, g, b, alpha); - - indices.push(vecPos++, vecPos++); - }; - - indices.push(vecPos-1); - } - - if(graphicsData.lineWidth) - { - graphicsData.points = []; - - for (var i=0; i < totalSegs + 1; i++) - { - graphicsData.points.push(x + Math.sin(seg * i) * width, - y + Math.cos(seg * i) * height) - }; - - PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); - } - -} - -/** - * Builds a line to draw - * - * @static - * @private - * @method buildLine - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) -{ - // TODO OPTIMISE! - - var wrap = true; - var points = graphicsData.points; - if(points.length == 0)return; - - // get first and last point.. figure out the middle! - var firstPoint = new PIXI.Point( points[0], points[1] ); - var lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - - // if the first point is the last point - goona have issues :) - if(firstPoint.x == lastPoint.x && firstPoint.y == lastPoint.y) - { - points.pop(); - points.pop(); - - lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - - var midPointX = lastPoint.x + (firstPoint.x - lastPoint.x) *0.5; - var midPointY = lastPoint.y + (firstPoint.y - lastPoint.y) *0.5; - - points.unshift(midPointX, midPointY); - points.push(midPointX, midPointY) - } - - var verts = webGLData.points; - var indices = webGLData.indices; - var length = points.length / 2; - var indexCount = points.length; - var indexStart = verts.length/6; - - // DRAW the Line - var width = graphicsData.lineWidth / 2; - - // sort color - var color = HEXtoRGB(graphicsData.lineColor); - var alpha = graphicsData.lineAlpha; - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var p1x, p1y, p2x, p2y, p3x, p3y; - var perpx, perpy, perp2x, perp2y, perp3x, perp3y; - var ipx, ipy; - var a1, b1, c1, a2, b2, c2; - var denom, pdist, dist; - - p1x = points[0]; - p1y = points[1]; - - p2x = points[2]; - p2y = points[3]; - - perpx = -(p1y - p2y); - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - // start - verts.push(p1x - perpx , p1y - perpy, - r, g, b, alpha); - - verts.push(p1x + perpx , p1y + perpy, - r, g, b, alpha); - - for (var i = 1; i < length-1; i++) - { - p1x = points[(i-1)*2]; - p1y = points[(i-1)*2 + 1]; - - p2x = points[(i)*2] - p2y = points[(i)*2 + 1] - - p3x = points[(i+1)*2]; - p3y = points[(i+1)*2 + 1]; - - perpx = -(p1y - p2y); - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - perp2x = -(p2y - p3y); - perp2y = p2x - p3x; - - dist = Math.sqrt(perp2x*perp2x + perp2y*perp2y); - perp2x /= dist; - perp2y /= dist; - perp2x *= width; - perp2y *= width; - - a1 = (-perpy + p1y) - (-perpy + p2y); - b1 = (-perpx + p2x) - (-perpx + p1x); - c1 = (-perpx + p1x) * (-perpy + p2y) - (-perpx + p2x) * (-perpy + p1y); - a2 = (-perp2y + p3y) - (-perp2y + p2y); - b2 = (-perp2x + p2x) - (-perp2x + p3x); - c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y); - - denom = a1*b2 - a2*b1; - - if (denom == 0) { - denom+=1; - } - - px = (b1*c2 - b2*c1)/denom; - py = (a2*c1 - a1*c2)/denom; - - pdist = (px -p2x) * (px -p2x) + (py -p2y) + (py -p2y); - - if(pdist > 140 * 140) - { - perp3x = perpx - perp2x; - perp3y = perpy - perp2y; - - dist = Math.sqrt(perp3x*perp3x + perp3y*perp3y); - perp3x /= dist; - perp3y /= dist; - perp3x *= width; - perp3y *= width; - - verts.push(p2x - perp3x, p2y -perp3y); - verts.push(r, g, b, alpha); - - verts.push(p2x + perp3x, p2y +perp3y); - verts.push(r, g, b, alpha); - - verts.push(p2x - perp3x, p2y -perp3y); - verts.push(r, g, b, alpha); - - indexCount++; - } - else - { - verts.push(px , py); - verts.push(r, g, b, alpha); - - verts.push(p2x - (px-p2x), p2y - (py - p2y)); - verts.push(r, g, b, alpha); - } - } - - p1x = points[(length-2)*2] - p1y = points[(length-2)*2 + 1] - - p2x = points[(length-1)*2] - p2y = points[(length-1)*2 + 1] - - perpx = -(p1y - p2y) - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - verts.push(p2x - perpx , p2y - perpy) - verts.push(r, g, b, alpha); - - verts.push(p2x + perpx , p2y + perpy) - verts.push(r, g, b, alpha); - - indices.push(indexStart); - - for (var i=0; i < indexCount; i++) - { - indices.push(indexStart++); - }; - - indices.push(indexStart-1); -} - -/** - * Builds a polygon to draw - * - * @static - * @private - * @method buildPoly - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData) -{ - var points = graphicsData.points; - if(points.length < 6)return; - - // get first and last point.. figure out the middle! - var verts = webGLData.points; - var indices = webGLData.indices; - - var length = points.length / 2; - - // sort color - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var triangles = PIXI.PolyK.Triangulate(points); - - var vertPos = verts.length / 6; - - for (var i=0; i < triangles.length; i+=3) - { - indices.push(triangles[i] + vertPos); - indices.push(triangles[i] + vertPos); - indices.push(triangles[i+1] + vertPos); - indices.push(triangles[i+2] +vertPos); - indices.push(triangles[i+2] + vertPos); - }; - - for (var i = 0; i < length; i++) - { - verts.push(points[i * 2], points[i * 2 + 1], - r, g, b, alpha); - }; -} - -function HEXtoRGB(hex) { - return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; -} - - - - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI._defaultFrame = new PIXI.Rectangle(0,0,1,1); - -// an instance of the gl context.. -// only one at the moment :/ -PIXI.gl; - -/** - * the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer - * should be used for browsers support webGL. This Render works by automatically managing webGLBatchs. - * So no need for Sprite Batch's or Sprite Cloud's - * Dont forget to add the view to your DOM or you will not see anything :) - * - * @class WebGLRenderer - * @constructor - * @param width=0 {Number} the width of the canvas view - * @param height=0 {Number} the height of the canvas view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) - * - */ -PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) -{ - // do a catch.. only 1 webGL renderer.. - - this.transparent = !!transparent; - - this.width = width || 800; - this.height = height || 600; - - this.view = view || document.createElement( 'canvas' ); - this.view.width = this.width; - this.view.height = this.height; - - // deal with losing context.. - var scope = this; - this.view.addEventListener('webglcontextlost', function(event) { scope.handleContextLost(event); }, false) - this.view.addEventListener('webglcontextrestored', function(event) { scope.handleContextRestored(event); }, false) - - this.batchs = []; - - var options = { - alpha: this.transparent, - antialias:!!antialias, // SPEED UP?? - premultipliedAlpha:false, - stencil:true - } - - //try 'experimental-webgl' - try { - PIXI.gl = this.gl = this.view.getContext("experimental-webgl", options); - } catch (e) { - //try 'webgl' - try { - PIXI.gl = this.gl = this.view.getContext("webgl", options); - } catch (e) { - // fail, not able to get a context - throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); - } - } - - PIXI.initDefaultShader(); - PIXI.initPrimitiveShader(); - PIXI.initDefaultStripShader(); - - -// PIXI.activateDefaultShader(); - - var gl = this.gl; - PIXI.WebGLRenderer.gl = gl; - - this.batch = new PIXI.WebGLBatch(gl); - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - - gl.enable(gl.BLEND); - gl.colorMask(true, true, true, this.transparent); - - PIXI.projection = new PIXI.Point(400, 300); - - this.resize(this.width, this.height); - this.contextLost = false; - - PIXI.pushShader(PIXI.defaultShader); - - this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); - -} - -// constructor -PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; - -/** - * Gets a new WebGLBatch from the pool - * - * @static - * @method getBatch - * @return {WebGLBatch} - * @private - */ -PIXI.WebGLRenderer.getBatch = function() -{ - if(PIXI._batchs.length == 0) - { - return new PIXI.WebGLBatch(PIXI.WebGLRenderer.gl); - } - else - { - return PIXI._batchs.pop(); - } -} - -/** - * Puts a batch back into the pool - * - * @static - * @method returnBatch - * @param batch {WebGLBatch} The batch to return - * @private - */ -PIXI.WebGLRenderer.returnBatch = function(batch) -{ - batch.clean(); - PIXI._batchs.push(batch); -} - -/** - * Renders the stage to its webGL view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.WebGLRenderer.prototype.render = function(stage) -{ - if(this.contextLost)return; - - - // if rendering a new stage clear the batchs.. - if(this.__stage !== stage) - { - // TODO make this work - // dont think this is needed any more? - this.__stage = stage; - this.stageRenderGroup.setRenderable(stage); - } - - // TODO not needed now... - // update children if need be - // best to remove first! - /*for (var i=0; i < stage.__childrenRemoved.length; i++) - { - var group = stage.__childrenRemoved[i].__renderGroup - if(group)group.removeDisplayObject(stage.__childrenRemoved[i]); - }*/ - - // update any textures - PIXI.WebGLRenderer.updateTextures(); - - // update the scene graph - PIXI.visibleCount++; - stage.updateTransform(); - - var gl = this.gl; - - // -- Does this need to be set every frame? -- // - gl.colorMask(true, true, true, this.transparent); - gl.viewport(0, 0, this.width, this.height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); - gl.clear(gl.COLOR_BUFFER_BIT); - - // HACK TO TEST - - this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; - this.stageRenderGroup.render(PIXI.projection); - - // interaction - // run interaction! - if(stage.interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - - // after rendering lets confirm all frames that have been uodated.. - if(PIXI.Texture.frameUpdates.length > 0) - { - for (var i=0; i < PIXI.Texture.frameUpdates.length; i++) - { - PIXI.Texture.frameUpdates[i].updateFrame = false; - }; - - PIXI.Texture.frameUpdates = []; - } -} - -/** - * Updates the textures loaded into this webgl renderer - * - * @static - * @method updateTextures - * @private - */ -PIXI.WebGLRenderer.updateTextures = function() -{ - //TODO break this out into a texture manager... - for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); - PIXI.texturesToUpdate = []; - PIXI.texturesToDestroy = []; -} - -/** - * Updates a loaded webgl texture - * - * @static - * @method updateTexture - * @param texture {Texture} The texture to update - * @private - */ -PIXI.WebGLRenderer.updateTexture = function(texture) -{ - //TODO break this out into a texture manager... - var gl = PIXI.gl; - - if(!texture._glTexture) - { - texture._glTexture = gl.createTexture(); - } - - if(texture.hasLoaded) - { - gl.bindTexture(gl.TEXTURE_2D, texture._glTexture); - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - - // reguler... - - if(!texture._powerOf2) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - } - - gl.bindTexture(gl.TEXTURE_2D, null); - } -} - -/** - * Destroys a loaded webgl texture - * - * @method destroyTexture - * @param texture {Texture} The texture to update - * @private - */ -PIXI.WebGLRenderer.destroyTexture = function(texture) -{ - //TODO break this out into a texture manager... - var gl = PIXI.gl; - - if(texture._glTexture) - { - texture._glTexture = gl.createTexture(); - gl.deleteTexture(gl.TEXTURE_2D, texture._glTexture); - } -} - -/** - * resizes the webGL view to the specified width and height - * - * @method resize - * @param width {Number} the new width of the webGL view - * @param height {Number} the new height of the webGL view - */ -PIXI.WebGLRenderer.prototype.resize = function(width, height) -{ - this.width = width; - this.height = height; - - this.view.width = width; - this.view.height = height; - - this.gl.viewport(0, 0, this.width, this.height); - - //var projectionMatrix = this.projectionMatrix; - - PIXI.projection.x = this.width/2; - PIXI.projection.y = this.height/2; - -// projectionMatrix[0] = 2/this.width; -// projectionMatrix[5] = -2/this.height; -// projectionMatrix[12] = -1; -// projectionMatrix[13] = 1; -} - -/** - * Handles a lost webgl context - * - * @method handleContextLost - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextLost = function(event) -{ - event.preventDefault(); - this.contextLost = true; -} - -/** - * Handles a restored webgl context - * - * @method handleContextRestored - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextRestored = function(event) -{ - this.gl = this.view.getContext("experimental-webgl", { - alpha: true - }); - - this.initShaders(); - - for(var key in PIXI.TextureCache) - { - var texture = PIXI.TextureCache[key].baseTexture; - texture._glTexture = null; - PIXI.WebGLRenderer.updateTexture(texture); - }; - - for (var i=0; i < this.batchs.length; i++) - { - this.batchs[i].restoreLostContext(this.gl)// - this.batchs[i].dirty = true; - }; - - PIXI._restoreBatchs(this.gl); - - this.contextLost = false; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI._batchs = []; - -/** - * @private - */ -PIXI._getBatch = function(gl) -{ - if(PIXI._batchs.length == 0) - { - return new PIXI.WebGLBatch(gl); - } - else - { - return PIXI._batchs.pop(); - } -} - -/** - * @private - */ -PIXI._returnBatch = function(batch) -{ - batch.clean(); - PIXI._batchs.push(batch); -} - -/** - * @private - */ -PIXI._restoreBatchs = function(gl) -{ - for (var i=0; i < PIXI._batchs.length; i++) - { - PIXI._batchs[i].restoreLostContext(gl); - }; -} - -/** - * A WebGLBatch Enables a group of sprites to be drawn using the same settings. - * if a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch. - * All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites - * in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled - * automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster - * the webGL renderer will run. - * - * @class WebGLBatch - * @constructor - * @param gl {WebGLContext} an instance of the webGL context - */ -PIXI.WebGLBatch = function(gl) -{ - this.gl = gl; - - this.size = 0; - - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); - this.blendMode = PIXI.blendModes.NORMAL; - this.dynamicSize = 1; -} - -// constructor -PIXI.WebGLBatch.prototype.constructor = PIXI.WebGLBatch; - -/** - * Cleans the batch so that is can be returned to an object pool and reused - * - * @method clean - */ -PIXI.WebGLBatch.prototype.clean = function() -{ - this.verticies = []; - this.uvs = []; - this.indices = []; - this.colors = []; - this.dynamicSize = 1; - this.texture = null; - this.last = null; - this.size = 0; - this.head; - this.tail; -} - -/** - * Recreates the buffers in the event of a context loss - * - * @method restoreLostContext - * @param gl {WebGLContext} - */ -PIXI.WebGLBatch.prototype.restoreLostContext = function(gl) -{ - this.gl = gl; - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); -} - -/** - * inits the batch's texture and blend mode based if the supplied sprite - * - * @method init - * @param sprite {Sprite} the first sprite to be added to the batch. Only sprites with - * the same base texture and blend mode will be allowed to be added to this batch - */ -PIXI.WebGLBatch.prototype.init = function(sprite) -{ - sprite.batch = this; - this.dirty = true; - this.blendMode = sprite.blendMode; - this.texture = sprite.texture.baseTexture; - this.head = sprite; - this.tail = sprite; - this.size = 1; - - this.growBatch(); -} - -/** - * inserts a sprite before the specified sprite - * - * @method insertBefore - * @param sprite {Sprite} the sprite to be added - * @param nextSprite {nextSprite} the first sprite will be inserted before this sprite - */ -PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) -{ - this.size++; - - sprite.batch = this; - this.dirty = true; - var tempPrev = nextSprite.__prev; - nextSprite.__prev = sprite; - sprite.__next = nextSprite; - - if(tempPrev) - { - sprite.__prev = tempPrev; - tempPrev.__next = sprite; - } - else - { - this.head = sprite; - } -} - -/** - * inserts a sprite after the specified sprite - * - * @method insertAfter - * @param sprite {Sprite} the sprite to be added - * @param previousSprite {Sprite} the first sprite will be inserted after this sprite - */ -PIXI.WebGLBatch.prototype.insertAfter = function(sprite, previousSprite) -{ - this.size++; - - sprite.batch = this; - this.dirty = true; - - var tempNext = previousSprite.__next; - previousSprite.__next = sprite; - sprite.__prev = previousSprite; - - if(tempNext) - { - sprite.__next = tempNext; - tempNext.__prev = sprite; - } - else - { - this.tail = sprite - } -} - -/** - * removes a sprite from the batch - * - * @method remove - * @param sprite {Sprite} the sprite to be removed - */ -PIXI.WebGLBatch.prototype.remove = function(sprite) -{ - this.size--; - - if(this.size == 0) - { - sprite.batch = null; - sprite.__prev = null; - sprite.__next = null; - return; - } - - if(sprite.__prev) - { - sprite.__prev.__next = sprite.__next; - } - else - { - this.head = sprite.__next; - this.head.__prev = null; - } - - if(sprite.__next) - { - sprite.__next.__prev = sprite.__prev; - } - else - { - this.tail = sprite.__prev; - this.tail.__next = null - } - - sprite.batch = null; - sprite.__next = null; - sprite.__prev = null; - this.dirty = true; -} - -/** - * Splits the batch into two with the specified sprite being the start of the new batch. - * - * @method split - * @param sprite {Sprite} the sprite that indicates where the batch should be split - * @return {WebGLBatch} the new batch - */ -PIXI.WebGLBatch.prototype.split = function(sprite) -{ - this.dirty = true; - - var batch = new PIXI.WebGLBatch(this.gl); - batch.init(sprite); - batch.texture = this.texture; - batch.tail = this.tail; - - this.tail = sprite.__prev; - this.tail.__next = null; - - sprite.__prev = null; - // return a splite batch! - - // TODO this size is wrong! - // need to recalculate :/ problem with a linked list! - // unless it gets calculated in the "clean"? - - // need to loop through items as there is no way to know the length on a linked list :/ - var tempSize = 0; - while(sprite) - { - tempSize++; - sprite.batch = batch; - sprite = sprite.__next; - } - - batch.size = tempSize; - this.size -= tempSize; - - return batch; -} - -/** - * Merges two batchs together - * - * @method merge - * @param batch {WebGLBatch} the batch that will be merged - */ -PIXI.WebGLBatch.prototype.merge = function(batch) -{ - this.dirty = true; - - this.tail.__next = batch.head; - batch.head.__prev = this.tail; - - this.size += batch.size; - - this.tail = batch.tail; - - var sprite = batch.head; - while(sprite) - { - sprite.batch = this; - sprite = sprite.__next; - } -} - -/** - * Grows the size of the batch. As the elements in the batch cannot have a dynamic size this - * function is used to increase the size of the batch. It also creates a little extra room so - * that the batch does not need to be resized every time a sprite is added - * - * @method growBatch - */ -PIXI.WebGLBatch.prototype.growBatch = function() -{ - var gl = this.gl; - if( this.size == 1) - { - this.dynamicSize = 1; - } - else - { - this.dynamicSize = this.size * 1.5 - } - // grow verts - this.verticies = new Float32Array(this.dynamicSize * 8); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); - - this.uvs = new Float32Array( this.dynamicSize * 8 ); - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); - - this.dirtyUVS = true; - - this.colors = new Float32Array( this.dynamicSize * 4 ); - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); - - this.dirtyColors = true; - - this.indices = new Uint16Array(this.dynamicSize * 6); - var length = this.indices.length/6; - - for (var i=0; i < length; i++) - { - var index2 = i * 6; - var index3 = i * 4; - this.indices[index2 + 0] = index3 + 0; - this.indices[index2 + 1] = index3 + 1; - this.indices[index2 + 2] = index3 + 2; - this.indices[index2 + 3] = index3 + 0; - this.indices[index2 + 4] = index3 + 2; - this.indices[index2 + 5] = index3 + 3; - }; - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); -} - -/** - * Refresh's all the data in the batch and sync's it with the webGL buffers - * - * @method refresh - */ -PIXI.WebGLBatch.prototype.refresh = function() -{ - var gl = this.gl; - - if (this.dynamicSize < this.size) - { - this.growBatch(); - } - - var indexRun = 0; - var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index; - var a, b, c, d, tx, ty; - - var displayObject = this.head; - - while(displayObject) - { - index = indexRun * 8; - - var texture = displayObject.texture; - - var frame = texture.frame; - var tw = texture.baseTexture.width; - var th = texture.baseTexture.height; - - this.uvs[index + 0] = frame.x / tw; - this.uvs[index +1] = frame.y / th; - - this.uvs[index +2] = (frame.x + frame.width) / tw; - this.uvs[index +3] = frame.y / th; - - this.uvs[index +4] = (frame.x + frame.width) / tw; - this.uvs[index +5] = (frame.y + frame.height) / th; - - this.uvs[index +6] = frame.x / tw; - this.uvs[index +7] = (frame.y + frame.height) / th; - - displayObject.updateFrame = false; - - colorIndex = indexRun * 4; - this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; - - displayObject = displayObject.__next; - - indexRun ++; - } - - this.dirtyUVS = true; - this.dirtyColors = true; -} - -/** - * Updates all the relevant geometry and uploads the data to the GPU - * - * @method update - */ -PIXI.WebGLBatch.prototype.update = function() -{ - var gl = this.gl; - var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index, index2, index3 - - var a, b, c, d, tx, ty; - - var indexRun = 0; - - var displayObject = this.head; - var verticies = this.verticies; - var uvs = this.uvs; - var colors = this.colors; - - while(displayObject) - { - if(displayObject.vcount === PIXI.visibleCount) - { - width = displayObject.texture.frame.width; - height = displayObject.texture.frame.height; - - // TODO trim?? - aX = displayObject.anchor.x;// - displayObject.texture.trim.x - aY = displayObject.anchor.y; //- displayObject.texture.trim.y - w0 = width * (1-aX); - w1 = width * -aX; - - h0 = height * (1-aY); - h1 = height * -aY; - - index = indexRun * 8; - - worldTransform = displayObject.worldTransform; - - a = worldTransform[0]; - b = worldTransform[3]; - c = worldTransform[1]; - d = worldTransform[4]; - tx = worldTransform[2]; - ty = worldTransform[5]; - - verticies[index + 0 ] = a * w1 + c * h1 + tx; - verticies[index + 1 ] = d * h1 + b * w1 + ty; - - verticies[index + 2 ] = a * w0 + c * h1 + tx; - verticies[index + 3 ] = d * h1 + b * w0 + ty; - - verticies[index + 4 ] = a * w0 + c * h0 + tx; - verticies[index + 5 ] = d * h0 + b * w0 + ty; - - verticies[index + 6] = a * w1 + c * h0 + tx; - verticies[index + 7] = d * h0 + b * w1 + ty; - - if(displayObject.updateFrame || displayObject.texture.updateFrame) - { - this.dirtyUVS = true; - - var texture = displayObject.texture; - - var frame = texture.frame; - var tw = texture.baseTexture.width; - var th = texture.baseTexture.height; - - uvs[index + 0] = frame.x / tw; - uvs[index +1] = frame.y / th; - - uvs[index +2] = (frame.x + frame.width) / tw; - uvs[index +3] = frame.y / th; - - uvs[index +4] = (frame.x + frame.width) / tw; - uvs[index +5] = (frame.y + frame.height) / th; - - uvs[index +6] = frame.x / tw; - uvs[index +7] = (frame.y + frame.height) / th; - - displayObject.updateFrame = false; - } - - // TODO this probably could do with some optimisation.... - if(displayObject.cacheAlpha != displayObject.worldAlpha) - { - displayObject.cacheAlpha = displayObject.worldAlpha; - - var colorIndex = indexRun * 4; - colors[colorIndex] = colors[colorIndex + 1] = colors[colorIndex + 2] = colors[colorIndex + 3] = displayObject.worldAlpha; - this.dirtyColors = true; - } - } - else - { - index = indexRun * 8; - - verticies[index + 0 ] = verticies[index + 1 ] = verticies[index + 2 ] = verticies[index + 3 ] = verticies[index + 4 ] = verticies[index + 5 ] = verticies[index + 6] = verticies[index + 7] = 0; - } - - indexRun++; - displayObject = displayObject.__next; - } -} - -/** - * Draws the batch to the frame buffer - * - * @method render - */ -PIXI.WebGLBatch.prototype.render = function(start, end) -{ - start = start || 0; - - if(end == undefined)end = this.size; - - if(this.dirty) - { - this.refresh(); - this.dirty = false; - } - - if (this.size == 0)return; - - this.update(); - var gl = this.gl; - - //TODO optimize this! - - var shaderProgram = PIXI.currentShader; - - //gl.useProgram(shaderProgram); - - // update the verts.. - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - // ok.. - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - // update the uvs - //var isDefault = (shaderProgram == PIXI.shaderProgram) - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - - if(this.dirtyUVS) - { - this.dirtyUVS = false; - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvs); - } - - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this.texture._glTexture); - - // update color! - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - - if(this.dirtyColors) - { - this.dirtyColors = false; - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.colors); - } - - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - var len = end - start; - - // DRAW THAT this! - gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A WebGLBatch Enables a group of sprites to be drawn using the same settings. - * if a group of sprites all have the same baseTexture and blendMode then they can be - * grouped into a batch. All the sprites in a batch can then be drawn in one go by the - * GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch - * even if the batch only contains one sprite. Batching is handled automatically by the - * webGL renderer. A good tip is: the smaller the number of batchs there are, the faster - * the webGL renderer will run. - * - * @class WebGLBatch - * @contructor - * @param gl {WebGLContext} An instance of the webGL context - */ -PIXI.WebGLRenderGroup = function(gl) -{ - this.gl = gl; - this.root; - - this.backgroundColor; - this.batchs = []; - this.toRemove = []; -} - -// constructor -PIXI.WebGLRenderGroup.prototype.constructor = PIXI.WebGLRenderGroup; - -/** - * Add a display object to the webgl renderer - * - * @method setRenderable - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.setRenderable = function(displayObject) -{ - // has this changed?? - if(this.root)this.removeDisplayObjectAndChildren(this.root); - - displayObject.worldVisible = displayObject.visible; - - // soooooo // - // to check if any batchs exist already?? - - // TODO what if its already has an object? should remove it - this.root = displayObject; - this.addDisplayObjectAndChildren(displayObject); -} - -/** - * Renders the stage to its webgl view - * - * @method render - * @param projection {Object} - */ -PIXI.WebGLRenderGroup.prototype.render = function(projection) -{ - PIXI.WebGLRenderer.updateTextures(); - - var gl = this.gl; - - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - // will render all the elements in the group - var renderable; - for (var i=0; i < this.batchs.length; i++) - { - - renderable = this.batchs[i]; - if(renderable instanceof PIXI.WebGLBatch) - { - this.batchs[i].render(); - continue; - } - - // non sprite batch.. - var worldVisible = renderable.vcount === PIXI.visibleCount; - - if(renderable instanceof PIXI.TilingSprite) - { - if(worldVisible)this.renderTilingSprite(renderable, projection); - } - else if(renderable instanceof PIXI.Strip) - { - if(worldVisible)this.renderStrip(renderable, projection); - } - else if(renderable instanceof PIXI.Graphics) - { - if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); - } - else if(renderable instanceof PIXI.FilterBlock) - { - this.handleFilterBlock(renderable, projection); - } - } - -} - -/** - * Renders a specific displayObject - * - * @method renderSpecific - * @param displayObject {DisplayObject} - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection) -{ - PIXI.WebGLRenderer.updateTextures(); - - var gl = this.gl; - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - - // to do! - // render part of the scene... - - var startIndex; - var startBatchIndex; - - var endIndex; - var endBatchIndex; - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.first; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - var startBatch = nextRenderable.batch; - - if(nextRenderable instanceof PIXI.Sprite) - { - startBatch = nextRenderable.batch; - - var head = startBatch.head; - var next = head; - - // ok now we have the batch.. need to find the start index! - if(head == nextRenderable) - { - startIndex = 0; - } - else - { - startIndex = 1; - - while(head.__next != nextRenderable) - { - startIndex++; - head = head.__next; - } - } - } - else - { - startBatch = nextRenderable; - } - - // Get the LAST renderable object - var lastRenderable = displayObject; - var endBatch; - var lastItem = displayObject; - while(lastItem.children.length > 0) - { - lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem.last; - } - - if(lastRenderable instanceof PIXI.Sprite) - { - endBatch = lastRenderable.batch; - - var head = endBatch.head; - - if(head == lastRenderable) - { - endIndex = 0; - } - else - { - endIndex = 1; - - while(head.__next != lastRenderable) - { - endIndex++; - head = head.__next; - } - } - } - else - { - endBatch = lastRenderable; - } - - // TODO - need to fold this up a bit! - - if(startBatch == endBatch) - { - if(startBatch instanceof PIXI.WebGLBatch) - { - startBatch.render(startIndex, endIndex+1); - } - else - { - this.renderSpecial(startBatch, projection); - } - return; - } - - // now we have first and last! - startBatchIndex = this.batchs.indexOf(startBatch); - endBatchIndex = this.batchs.indexOf(endBatch); - - // DO the first batch - if(startBatch instanceof PIXI.WebGLBatch) - { - startBatch.render(startIndex); - } - else - { - this.renderSpecial(startBatch, projection); - } - - // DO the middle batchs.. - for (var i=startBatchIndex+1; i < endBatchIndex; i++) - { - renderable = this.batchs[i]; - - if(renderable instanceof PIXI.WebGLBatch) - { - this.batchs[i].render(); - } - else - { - this.renderSpecial(renderable, projection); - } - } - - // DO the last batch.. - if(endBatch instanceof PIXI.WebGLBatch) - { - endBatch.render(0, endIndex+1); - } - else - { - this.renderSpecial(endBatch, projection); - } -} - -/** - * Renders a specific renderable - * - * @method renderSpecial - * @param renderable {DisplayObject} - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) -{ - var sta = PIXI.shaderStack.length; - - var worldVisible = renderable.vcount === PIXI.visibleCount - - if(renderable instanceof PIXI.TilingSprite) - { - if(worldVisible)this.renderTilingSprite(renderable, projection); - } - else if(renderable instanceof PIXI.Strip) - { - if(worldVisible)this.renderStrip(renderable, projection); - } - else if(renderable instanceof PIXI.CustomRenderable) - { - if(worldVisible) renderable.renderWebGL(this, projection); - } - else if(renderable instanceof PIXI.Graphics) - { - if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); - } - else if(renderable instanceof PIXI.FilterBlock) - { - this.handleFilterBlock(renderable, projection); - } -} - -PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) -{ - /* - * for now only masks are supported.. - */ - var gl = PIXI.gl; - - if(renderable.open) - { - if(renderable.data instanceof Array) - { - var filter = renderable.data[0]; - - if(!filter.shader) - { - var shader = new PIXI.PixiShader(); - - shader.fragmentSrc = filter.fragmentSrc; - shader.uniforms = filter.uniforms; - shader.init(); - - filter.shader = shader - } - - PIXI.pushShader(filter.shader); - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - } - else - { - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); - - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - } - else - { - if(renderable.data instanceof Array) - { - PIXI.popShader(); - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - } - else - { - gl.disable(gl.STENCIL_TEST); - } - } -} - -/** - * Updates a webgl texture - * - * @method updateTexture - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject) -{ - - // TODO definitely can optimse this function.. - - this.removeObject(displayObject); - - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - var previousRenderable = displayObject.first; - while(previousRenderable != this.root) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.last; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - - this.insertObject(displayObject, previousRenderable, nextRenderable); -} - -/** - * Adds filter blocks - * - * @method addFilterBlocks - * @param start {FilterBlock} - * @param end {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) -{ - start.__renderGroup = this; - end.__renderGroup = this; - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - var previousRenderable = start; - while(previousRenderable != this.root.first) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - this.insertAfter(start, previousRenderable); - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var previousRenderable2 = end; - while(previousRenderable2 != this.root.first) - { - previousRenderable2 = previousRenderable2._iPrev; - if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; - } - this.insertAfter(end, previousRenderable2); -} - -/** - * Remove filter blocks - * - * @method removeFilterBlocks - * @param start {FilterBlock} - * @param end {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeFilterBlocks = function(start, end) -{ - this.removeObject(start); - this.removeObject(end); -} - -/** - * Adds a display object and children to the webgl context - * - * @method addDisplayObjectAndChildren - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayObject) -{ - if(displayObject.__renderGroup)displayObject.__renderGroup.removeDisplayObjectAndChildren(displayObject); - - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - - var previousRenderable = displayObject.first; - while(previousRenderable != this.root.first) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.last; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - - // one the display object hits this. we can break the loop - - var tempObject = displayObject.first; - var testObject = displayObject.last._iNext; - do - { - tempObject.__renderGroup = this; - - if(tempObject.renderable) - { - - this.insertObject(tempObject, previousRenderable, nextRenderable); - previousRenderable = tempObject; - } - - tempObject = tempObject._iNext; - } - while(tempObject != testObject) -} - -/** - * Removes a display object and children to the webgl context - * - * @method removeDisplayObjectAndChildren - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren = function(displayObject) -{ - if(displayObject.__renderGroup != this)return; - -// var displayObject = displayObject.first; - var lastObject = displayObject.last; - do - { - displayObject.__renderGroup = null; - if(displayObject.renderable)this.removeObject(displayObject); - displayObject = displayObject._iNext; - } - while(displayObject) -} - -/** - * Inserts a displayObject into the linked list - * - * @method insertObject - * @param displayObject {DisplayObject} - * @param previousObject {DisplayObject} - * @param nextObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousObject, nextObject) -{ - // while looping below THE OBJECT MAY NOT HAVE BEEN ADDED - var previousSprite = previousObject; - var nextSprite = nextObject; - - /* - * so now we have the next renderable and the previous renderable - * - */ - if(displayObject instanceof PIXI.Sprite) - { - var previousBatch - var nextBatch - - if(previousSprite instanceof PIXI.Sprite) - { - previousBatch = previousSprite.batch; - if(previousBatch) - { - if(previousBatch.texture == displayObject.texture.baseTexture && previousBatch.blendMode == displayObject.blendMode) - { - previousBatch.insertAfter(displayObject, previousSprite); - return; - } - } - } - else - { - // TODO reword! - previousBatch = previousSprite; - } - - if(nextSprite) - { - if(nextSprite instanceof PIXI.Sprite) - { - nextBatch = nextSprite.batch; - - //batch may not exist if item was added to the display list but not to the webGL - if(nextBatch) - { - if(nextBatch.texture == displayObject.texture.baseTexture && nextBatch.blendMode == displayObject.blendMode) - { - nextBatch.insertBefore(displayObject, nextSprite); - return; - } - else - { - if(nextBatch == previousBatch) - { - // THERE IS A SPLIT IN THIS BATCH! // - var splitBatch = previousBatch.split(nextSprite); - // COOL! - // add it back into the array - /* - * OOPS! - * seems the new sprite is in the middle of a batch - * lets split it.. - */ - var batch = PIXI.WebGLRenderer.getBatch(); - - var index = this.batchs.indexOf( previousBatch ); - batch.init(displayObject); - this.batchs.splice(index+1, 0, batch, splitBatch); - - return; - } - } - } - } - else - { - // TODO re-word! - - nextBatch = nextSprite; - } - } - - /* - * looks like it does not belong to any batch! - * but is also not intersecting one.. - * time to create anew one! - */ - - var batch = PIXI.WebGLRenderer.getBatch(); - batch.init(displayObject); - - if(previousBatch) // if this is invalid it means - { - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, batch); - } - else - { - this.batchs.push(batch); - } - - return; - } - else if(displayObject instanceof PIXI.TilingSprite) - { - - // add to a batch!! - this.initTilingSprite(displayObject); - // this.batchs.push(displayObject); - - } - else if(displayObject instanceof PIXI.Strip) - { - // add to a batch!! - this.initStrip(displayObject); - // this.batchs.push(displayObject); - } - else if(displayObject)// instanceof PIXI.Graphics) - { - //displayObject.initWebGL(this); - - // add to a batch!! - //this.initStrip(displayObject); - //this.batchs.push(displayObject); - } - - this.insertAfter(displayObject, previousSprite); - - // insert and SPLIT! - -} - -/** - * Inserts a displayObject into the linked list - * - * @method insertAfter - * @param item {DisplayObject} - * @param displayObject {DisplayObject} The object to insert - * @private - */ -PIXI.WebGLRenderGroup.prototype.insertAfter = function(item, displayObject) -{ - if(displayObject instanceof PIXI.Sprite) - { - var previousBatch = displayObject.batch; - - if(previousBatch) - { - // so this object is in a batch! - - // is it not? need to split the batch - if(previousBatch.tail == displayObject) - { - // is it tail? insert in to batchs - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, item); - } - else - { - // TODO MODIFY ADD / REMOVE CHILD TO ACCOUNT FOR FILTERS (also get prev and next) // - - // THERE IS A SPLIT IN THIS BATCH! // - var splitBatch = previousBatch.split(displayObject.__next); - - // COOL! - // add it back into the array - /* - * OOPS! - * seems the new sprite is in the middle of a batch - * lets split it.. - */ - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, item, splitBatch); - } - } - else - { - this.batchs.push(item); - } - } - else - { - var index = this.batchs.indexOf( displayObject ); - this.batchs.splice(index+1, 0, item); - } -} - -/** - * Removes a displayObject from the linked list - * - * @method removeObject - * @param displayObject {DisplayObject} The object to remove - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) -{ - // loop through children.. - // display object // - - // add a child from the render group.. - // remove it and all its children! - //displayObject.cacheVisible = false;//displayObject.visible; - - /* - * removing is a lot quicker.. - * - */ - var batchToRemove; - - if(displayObject instanceof PIXI.Sprite) - { - // should always have a batch! - var batch = displayObject.batch; - if(!batch)return; // this means the display list has been altered befre rendering - - batch.remove(displayObject); - - if(batch.size==0) - { - batchToRemove = batch; - } - } - else - { - batchToRemove = displayObject; - } - - /* - * Looks like there is somthing that needs removing! - */ - if(batchToRemove) - { - var index = this.batchs.indexOf( batchToRemove ); - if(index == -1)return;// this means it was added then removed before rendered - - // ok so.. check to see if you adjacent batchs should be joined. - // TODO may optimise? - if(index == 0 || index == this.batchs.length-1) - { - // wha - eva! just get of the empty batch! - this.batchs.splice(index, 1); - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - - return; - } - - if(this.batchs[index-1] instanceof PIXI.WebGLBatch && this.batchs[index+1] instanceof PIXI.WebGLBatch) - { - if(this.batchs[index-1].texture == this.batchs[index+1].texture && this.batchs[index-1].blendMode == this.batchs[index+1].blendMode) - { - //console.log("MERGE") - this.batchs[index-1].merge(this.batchs[index+1]); - - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - PIXI.WebGLRenderer.returnBatch(this.batchs[index+1]); - this.batchs.splice(index, 2); - return; - } - } - - this.batchs.splice(index, 1); - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - } -} - - -/** - * Initializes a tiling sprite - * - * @method initTilingSprite - * @param sprite {TilingSprite} The tiling sprite to initialize - * @private - */ -PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) -{ - var gl = this.gl; - - // make the texture tilable.. - - sprite.verticies = new Float32Array([0, 0, - sprite.width, 0, - sprite.width, sprite.height, - 0, sprite.height]); - - sprite.uvs = new Float32Array([0, 0, - 1, 0, - 1, 1, - 0, 1]); - - sprite.colors = new Float32Array([1,1,1,1]); - - sprite.indices = new Uint16Array([0, 1, 3,2])//, 2]); - - sprite._vertexBuffer = gl.createBuffer(); - sprite._indexBuffer = gl.createBuffer(); - sprite._uvBuffer = gl.createBuffer(); - sprite._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.verticies, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.uvs, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.colors, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sprite._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sprite.indices, gl.STATIC_DRAW); - -// return ( (x > 0) && ((x & (x - 1)) == 0) ); - - if(sprite.texture.baseTexture._glTexture) - { - gl.bindTexture(gl.TEXTURE_2D, sprite.texture.baseTexture._glTexture); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - sprite.texture.baseTexture._powerOf2 = true; - } - else - { - sprite.texture.baseTexture._powerOf2 = true; - } -} - -/** - * Renders a Strip - * - * @method renderStrip - * @param strip {Strip} The strip to render - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) -{ - var gl = this.gl; - var shaderProgram = PIXI.stripShaderProgram; - - - gl.useProgram(shaderProgram); - - var m = PIXI.mat3.clone(strip.worldTransform); - - PIXI.mat3.transpose(m); - - // set the matrix transform for the - gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); - gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); - -/* - if(strip.blendMode == PIXI.blendModes.NORMAL) - { - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - } - else - { - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR); - } - */ - - - if(!strip.dirty) - { - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, strip.verticies) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - } - else - { - strip.dirty = false; - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); - - } - - gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - - gl.useProgram(PIXI.currentProgram); -} - -/** - * Renders a TilingSprite - * - * @method renderTilingSprite - * @param sprite {TilingSprite} The tiling sprite to render - * @param projectionMatrix {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderTilingSprite = function(sprite, projectionMatrix) -{ - var gl = this.gl; - var shaderProgram = PIXI.shaderProgram; - - var tilePosition = sprite.tilePosition; - var tileScale = sprite.tileScale; - - var offsetX = tilePosition.x/sprite.texture.baseTexture.width; - var offsetY = tilePosition.y/sprite.texture.baseTexture.height; - - var scaleX = (sprite.width / sprite.texture.baseTexture.width) / tileScale.x; - var scaleY = (sprite.height / sprite.texture.baseTexture.height) / tileScale.y; - - sprite.uvs[0] = 0 - offsetX; - sprite.uvs[1] = 0 - offsetY; - - sprite.uvs[2] = (1 * scaleX) -offsetX; - sprite.uvs[3] = 0 - offsetY; - - sprite.uvs[4] = (1 *scaleX) - offsetX; - sprite.uvs[5] = (1 *scaleY) - offsetY; - - sprite.uvs[6] = 0 - offsetX; - sprite.uvs[7] = (1 *scaleY) - offsetY; - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, sprite.uvs) - - this.renderStrip(sprite, projectionMatrix); -} - -/** - * Initializes a strip to be rendered - * - * @method initStrip - * @param strip {Strip} The strip to initialize - * @private - */ -PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) -{ - // build the strip! - var gl = this.gl; - var shaderProgram = this.shaderProgram; - - strip._vertexBuffer = gl.createBuffer(); - strip._indexBuffer = gl.createBuffer(); - strip._uvBuffer = gl.createBuffer(); - strip._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW); - - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * the CanvasRenderer draws the stage and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. - * Dont forget to add the view to your DOM or you will not see anything :) - * - * @class CanvasRenderer - * @constructor - * @param width=0 {Number} the width of the canvas view - * @param height=0 {Number} the height of the canvas view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - */ -PIXI.CanvasRenderer = function(width, height, view, transparent) -{ - this.transparent = transparent; - - /** - * The width of the canvas view - * - * @property width - * @type Number - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @property height - * @type Number - * @default 600 - */ - this.height = height || 600; - - /** - * The canvas element that the everything is drawn to - * - * @property view - * @type Canvas - */ - this.view = view || document.createElement( 'canvas' ); - - /** - * The canvas context that the everything is drawn to - * @property context - * @type Canvas 2d Context - */ - this.context = this.view.getContext("2d"); - - this.refresh = true; - // hack to enable some hardware acceleration! - //this.view.style["transform"] = "translatez(0)"; - - this.view.width = this.width; - this.view.height = this.height; - this.count = 0; -} - -// constructor -PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; - -/** - * Renders the stage to its canvas view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.CanvasRenderer.prototype.render = function(stage) -{ - - //stage.__childrenAdded = []; - //stage.__childrenRemoved = []; - - // update textures if need be - PIXI.texturesToUpdate = []; - PIXI.texturesToDestroy = []; - - PIXI.visibleCount++; - stage.updateTransform(); - - // update the background color - if(this.view.style.backgroundColor!=stage.backgroundColorString && !this.transparent)this.view.style.backgroundColor = stage.backgroundColorString; - - this.context.setTransform(1,0,0,1,0,0); - this.context.clearRect(0, 0, this.width, this.height) - this.renderDisplayObject(stage); - //as - - // run interaction! - if(stage.interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - - // remove frame updates.. - if(PIXI.Texture.frameUpdates.length > 0) - { - PIXI.Texture.frameUpdates = []; - } - - -} - -/** - * resizes the canvas view to the specified width and height - * - * @method resize - * @param width {Number} the new width of the canvas view - * @param height {Number} the new height of the canvas view - */ -PIXI.CanvasRenderer.prototype.resize = function(width, height) -{ - this.width = width; - this.height = height; - - this.view.width = width; - this.view.height = height; -} - -/** - * Renders a display object - * - * @method renderDisplayObject - * @param displayObject {DisplayObject} The displayObject to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) -{ - // no loger recurrsive! - var transform; - var context = this.context; - - context.globalCompositeOperation = 'source-over'; - - // one the display object hits this. we can break the loop - var testObject = displayObject.last._iNext; - displayObject = displayObject.first; - - do - { - transform = displayObject.worldTransform; - - if(!displayObject.visible) - { - displayObject = displayObject.last._iNext; - continue; - } - - if(!displayObject.renderable) - { - displayObject = displayObject._iNext; - continue; - } - - if(displayObject instanceof PIXI.Sprite) - { - - var frame = displayObject.texture.frame; - - if(frame && frame.width && frame.height) - { - context.globalAlpha = displayObject.worldAlpha; - - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); - - context.drawImage(displayObject.texture.baseTexture.source, - frame.x, - frame.y, - frame.width, - frame.height, - (displayObject.anchor.x) * -frame.width, - (displayObject.anchor.y) * -frame.height, - frame.width, - frame.height); - } - } - else if(displayObject instanceof PIXI.Strip) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - this.renderStrip(displayObject); - } - else if(displayObject instanceof PIXI.TilingSprite) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - this.renderTilingSprite(displayObject); - } - else if(displayObject instanceof PIXI.CustomRenderable) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); - displayObject.renderCanvas(this); - } - else if(displayObject instanceof PIXI.Graphics) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - PIXI.CanvasGraphics.renderGraphics(displayObject, context); - } - else if(displayObject instanceof PIXI.FilterBlock) - { - if(displayObject.data instanceof PIXI.Graphics) - { - var mask = displayObject.data; - - if(displayObject.open) - { - context.save(); - - var cacheAlpha = mask.alpha; - var maskTransform = mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(mask, context); - context.clip(); - - mask.worldAlpha = cacheAlpha; - } - else - { - context.restore(); - } - } - else - { - // only masks supported right now! - } - } - // count++ - displayObject = displayObject._iNext; - - - } - while(displayObject != testObject) - - -} - -/** - * Renders a flat strip - * - * @method renderStripFlat - * @param strip {Strip} The Strip to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip) -{ - var context = this.context; - var verticies = strip.verticies; - var uvs = strip.uvs; - - var length = verticies.length/2; - this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - - // draw some triangles! - var index = i*2; - - var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; - var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - }; - - context.fillStyle = "#FF0000"; - context.fill(); - context.closePath(); -} - -/** - * Renders a tiling sprite - * - * @method renderTilingSprite - * @param sprite {TilingSprite} The tilingsprite to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) -{ - var context = this.context; - - context.globalAlpha = sprite.worldAlpha; - - if(!sprite.__tilePattern) sprite.__tilePattern = context.createPattern(sprite.texture.baseTexture.source, "repeat"); - - context.beginPath(); - - var tilePosition = sprite.tilePosition; - var tileScale = sprite.tileScale; - - // offset - context.scale(tileScale.x,tileScale.y); - context.translate(tilePosition.x, tilePosition.y); - - context.fillStyle = sprite.__tilePattern; - context.fillRect(-tilePosition.x,-tilePosition.y,sprite.width / tileScale.x, sprite.height / tileScale.y); - - context.scale(1/tileScale.x, 1/tileScale.y); - context.translate(-tilePosition.x, -tilePosition.y); - - context.closePath(); -} - -/** - * Renders a strip - * - * @method renderStrip - * @param strip {Strip} The Strip to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderStrip = function(strip) -{ - var context = this.context; - - // draw triangles!! - var verticies = strip.verticies; - var uvs = strip.uvs; - - var length = verticies.length/2; - this.count++; - for (var i=1; i < length-2; i++) - { - - // draw some triangles! - var index = i*2; - - var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; - var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - - var u0 = uvs[index] * strip.texture.width, u1 = uvs[index+2] * strip.texture.width, u2 = uvs[index+4]* strip.texture.width; - var v0 = uvs[index+1]* strip.texture.height, v1 = uvs[index+3] * strip.texture.height, v2 = uvs[index+5]* strip.texture.height; - - - 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 delta_a = x0*v1 + v0*x2 + x1*v2 - v1*x2 - v0*x1 - x0*v2; - var delta_b = u0*x1 + x0*u2 + u1*x2 - x1*u2 - x0*u1 - u0*x2; - var delta_c = u0*v1*x2 + v0*x1*u2 + x0*u1*v2 - x0*v1*u2 - v0*u1*x2 - u0*x1*v2; - var delta_d = y0*v1 + v0*y2 + y1*v2 - v1*y2 - v0*y1 - y0*v2; - var delta_e = u0*y1 + y0*u2 + u1*y2 - y1*u2 - y0*u1 - u0*y2; - var delta_f = u0*v1*y2 + v0*y1*u2 + y0*u1*v2 - y0*v1*u2 - v0*u1*y2 - u0*y1*v2; - - - - - context.transform(delta_a/delta, delta_d/delta, - delta_b/delta, delta_e/delta, - delta_c/delta, delta_f/delta); - - context.drawImage(strip.texture.baseTexture.source, 0, 0); - context.restore(); - }; - -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * A set of functions used by the canvas renderer to draw the primitive graphics data - * - * @class CanvasGraphics - */ -PIXI.CanvasGraphics = function() -{ - -} - - -/* - * Renders the graphics object - * - * @static - * @private - * @method renderGraphics - * @param graphics {Graphics} - * @param context {Context2D} - */ -PIXI.CanvasGraphics.renderGraphics = function(graphics, context) -{ - var worldAlpha = graphics.worldAlpha; - - for (var i=0; i < graphics.graphicsData.length; i++) - { - var data = graphics.graphicsData[i]; - var points = data.points; - - context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); - - context.lineWidth = data.lineWidth; - - if(data.type == PIXI.Graphics.POLY) - { - context.beginPath(); - - context.moveTo(points[0], points[1]); - - for (var j=1; j < points.length/2; j++) - { - context.lineTo(points[j * 2], points[j * 2 + 1]); - } - - // if the first and last point are the same close the path - much neater :) - if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) - { - context.closePath(); - } - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - else if(data.type == PIXI.Graphics.RECT) - { - - if(data.fillColor || data.fillColor === 0) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fillRect(points[0], points[1], points[2], points[3]); - - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.strokeRect(points[0], points[1], points[2], points[3]); - } - - } - else if(data.type == PIXI.Graphics.CIRC) - { - // TODO - need to be Undefined! - context.beginPath(); - context.arc(points[0], points[1], points[2],0,2*Math.PI); - context.closePath(); - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - else if(data.type == PIXI.Graphics.ELIP) - { - - // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - - var elipseData = data.points; - - var w = elipseData[2] * 2; - var h = elipseData[3] * 2; - - var x = elipseData[0] - w/2; - var y = elipseData[1] - h/2; - - context.beginPath(); - - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - - context.moveTo(x, ym); - context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - - context.closePath(); - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - - }; -} - -/* - * Renders a graphics mask - * - * @static - * @private - * @method renderGraphicsMask - * @param graphics {Graphics} - * @param context {Context2D} - */ -PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) -{ - var worldAlpha = graphics.worldAlpha; - - var len = graphics.graphicsData.length; - if(len > 1) - { - len = 1; - console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") - } - - for (var i=0; i < 1; i++) - { - var data = graphics.graphicsData[i]; - var points = data.points; - - if(data.type == PIXI.Graphics.POLY) - { - context.beginPath(); - context.moveTo(points[0], points[1]); - - for (var j=1; j < points.length/2; j++) - { - context.lineTo(points[j * 2], points[j * 2 + 1]); - } - - // if the first and last point are the same close the path - much neater :) - if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) - { - context.closePath(); - } - - } - else if(data.type == PIXI.Graphics.RECT) - { - context.beginPath(); - context.rect(points[0], points[1], points[2], points[3]); - context.closePath(); - } - else if(data.type == PIXI.Graphics.CIRC) - { - // TODO - need to be Undefined! - context.beginPath(); - context.arc(points[0], points[1], points[2],0,2*Math.PI); - context.closePath(); - } - else if(data.type == PIXI.Graphics.ELIP) - { - - // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - var elipseData = data.points; - - var w = elipseData[2] * 2; - var h = elipseData[3] * 2; - - var x = elipseData[0] - w/2; - var y = elipseData[1] - h/2; - - context.beginPath(); - - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - - context.moveTo(x, ym); - context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - context.closePath(); - } - - - }; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. - * It is important to know that with the webGL renderer only simple polys can be filled at this stage - * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png - * - * @class Graphics - * @extends DisplayObjectContainer - * @constructor - */ -PIXI.Graphics = function() -{ - PIXI.DisplayObjectContainer.call( this ); - - this.renderable = true; - - /** - * The alpha of the fill of this graphics object - * - * @property fillAlpha - * @type Number - */ - this.fillAlpha = 1; - - /** - * The width of any lines drawn - * - * @property lineWidth - * @type Number - */ - this.lineWidth = 0; - - /** - * The color of any lines drawn - * - * @property lineColor - * @type String - */ - this.lineColor = "black"; - - /** - * Graphics data - * - * @property graphicsData - * @type Array - * @private - */ - this.graphicsData = []; - - /** - * Current path - * - * @property currentPath - * @type Object - * @private - */ - this.currentPath = {points:[]}; -} - -// constructor -PIXI.Graphics.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Graphics.prototype.constructor = PIXI.Graphics; - -/** - * Specifies a line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method. - * - * @method lineStyle - * @param lineWidth {Number} width of the line to draw, will update the object's stored style - * @param color {Number} color of the line to draw, will update the object's stored style - * @param alpha {Number} alpha of the line to draw, will update the object's stored style - */ -PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.lineWidth = lineWidth || 0; - this.lineColor = color || 0; - this.lineAlpha = (alpha == undefined) ? 1 : alpha; - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - - this.graphicsData.push(this.currentPath); -} - -/** - * Moves the current drawing position to (x, y). - * - * @method moveTo - * @param x {Number} the X coord to move to - * @param y {Number} the Y coord to move to - */ -PIXI.Graphics.prototype.moveTo = function(x, y) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - - this.currentPath.points.push(x, y); - - this.graphicsData.push(this.currentPath); -} - -/** - * Draws a line using the current line style from the current drawing position to (x, y); - * the current drawing position is then set to (x, y). - * - * @method lineTo - * @param x {Number} the X coord to draw to - * @param y {Number} the Y coord to draw to - */ -PIXI.Graphics.prototype.lineTo = function(x, y) -{ - this.currentPath.points.push(x, y); - this.dirty = true; -} - -/** - * Specifies a simple one-color fill that subsequent calls to other Graphics methods - * (such as lineTo() or drawCircle()) use when drawing. - * - * @method beginFill - * @param color {uint} the color of the fill - * @param alpha {Number} the alpha - */ -PIXI.Graphics.prototype.beginFill = function(color, alpha) -{ - this.filling = true; - this.fillColor = color || 0; - this.fillAlpha = (alpha == undefined) ? 1 : alpha; -} - -/** - * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. - * - * @method endFill - */ -PIXI.Graphics.prototype.endFill = function() -{ - this.filling = false; - this.fillColor = null; - this.fillAlpha = 1; -} - -/** - * @method drawRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - */ -PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, width, height], type:PIXI.Graphics.RECT}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Draws a circle. - * - * @method drawCircle - * @param x {Number} The X coord of the center of the circle - * @param y {Number} The Y coord of the center of the circle - * @param radius {Number} The radius of the circle - */ -PIXI.Graphics.prototype.drawCircle = function( x, y, radius) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Draws an elipse. - * - * @method drawElipse - * @param x {Number} - * @param y {Number} - * @param width {Number} - * @param height {Number} - */ -PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, width, height], type:PIXI.Graphics.ELIP}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @method clear - */ -PIXI.Graphics.prototype.clear = function() -{ - this.lineWidth = 0; - this.filling = false; - - this.dirty = true; - this.clearDirty = true; - this.graphicsData = []; -} - -// SOME TYPES: -PIXI.Graphics.POLY = 0; -PIXI.Graphics.RECT = 1; -PIXI.Graphics.CIRC = 2; -PIXI.Graphics.ELIP = 3; - -/** - * @author Mat Groves http://matgroves.com/ - */ - -PIXI.Strip = function(texture, width, height) -{ - PIXI.DisplayObjectContainer.call( this ); - this.texture = texture; - this.blendMode = PIXI.blendModes.NORMAL; - - try - { - this.uvs = new Float32Array([0, 1, - 1, 1, - 1, 0, 0,1]); - - this.verticies = new Float32Array([0, 0, - 0,0, - 0,0, 0, - 0, 0]); - - this.colors = new Float32Array([1, 1, 1, 1]); - - this.indices = new Uint16Array([0, 1, 2, 3]); - } - catch(error) - { - this.uvs = [0, 1, - 1, 1, - 1, 0, 0,1]; - - this.verticies = [0, 0, - 0,0, - 0,0, 0, - 0, 0]; - - this.colors = [1, 1, 1, 1]; - - this.indices = [0, 1, 2, 3]; - } - - - /* - this.uvs = new Float32Array() - this.verticies = new Float32Array() - this.colors = new Float32Array() - this.indices = new Uint16Array() -*/ - this.width = width; - this.height = height; - - // load the texture! - if(texture.baseTexture.hasLoaded) - { - this.width = this.texture.frame.width; - this.height = this.texture.frame.height; - this.updateFrame = true; - } - else - { - this.onTextureUpdateBind = this.onTextureUpdate.bind(this); - this.texture.addEventListener( 'update', this.onTextureUpdateBind ); - } - - this.renderable = true; -} - -// constructor -PIXI.Strip.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Strip.prototype.constructor = PIXI.Strip; - -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; -} - -PIXI.Strip.prototype.onTextureUpdate = function(event) -{ - this.updateFrame = true; -} -// some helper functions.. - - -/** - * @author Mat Groves http://matgroves.com/ - */ - - -PIXI.Rope = function(texture, points) -{ - PIXI.Strip.call( this, texture ); - this.points = points; - - try - { - this.verticies = new Float32Array( points.length * 4); - this.uvs = new Float32Array( points.length * 4); - this.colors = new Float32Array( points.length * 2); - this.indices = new Uint16Array( points.length * 2); - } - catch(error) - { - this.verticies = verticies - - this.uvs = uvs - this.colors = colors - this.indices = indices - } - - this.refresh(); -} - - -// constructor -PIXI.Rope.prototype = Object.create( PIXI.Strip.prototype ); -PIXI.Rope.prototype.constructor = PIXI.Rope; - -PIXI.Rope.prototype.refresh = function() -{ - var points = this.points; - if(points.length < 1)return; - - var uvs = this.uvs - var indices = this.indices; - var colors = this.colors; - - var lastPoint = points[0]; - var nextPoint; - var perp = {x:0, y:0}; - var point = points[0]; - - this.count-=0.2; - - - uvs[0] = 0 - uvs[1] = 1 - uvs[2] = 0 - uvs[3] = 1 - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length; - - for (var i = 1; i < total; i++) - { - - var point = points[i]; - var index = i * 4; - // time to do some smart drawing! - var 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; - } -} - -PIXI.Rope.prototype.updateTransform = function() -{ - - var points = this.points; - if(points.length < 1)return; - - var verticies = this.verticies - - var lastPoint = points[0]; - var nextPoint; - var perp = {x:0, y:0}; - var point = points[0]; - - this.count-=0.2; - - verticies[0] = point.x + perp.x - verticies[1] = point.y + perp.y //+ 200 - verticies[2] = point.x - perp.x - verticies[3] = point.y - perp.y//+200 - // time to do some smart drawing! - - var total = points.length; - - for (var i = 1; i < total; i++) - { - - var point = points[i]; - var 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; - - var ratio = (1 - (i / (total-1))) * 10; - if(ratio > 1)ratio = 1; - - var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); - var 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; - - verticies[index] = point.x + perp.x - verticies[index+1] = point.y + perp.y - verticies[index+2] = point.x - perp.x - verticies[index+3] = point.y - perp.y - - lastPoint = point; - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); -} - -PIXI.Rope.prototype.setTexture = function(texture) -{ - // stop current texture - this.texture = texture; - this.updateFrame = true; -} - - - - - -/** - * @author Mat Groves http://matgroves.com/ - */ - -/** - * A tiling sprite is a fast way of rendering a tiling image - * - * @class TilingSprite - * @extends DisplayObjectContainer - * @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.DisplayObjectContainer.call( this ); - - /** - * The texture that the sprite is using - * - * @property texture - * @type Texture - */ - this.texture = texture; - - /** - * The width of the tiling sprite - * - * @property width - * @type Number - */ - this.width = width; - - /** - * The height of the tiling sprite - * - * @property height - * @type Number - */ - this.height = height; - - /** - * The scaling of the image that is being tiled - * - * @property tileScale - * @type Point - */ - this.tileScale = 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); - - this.renderable = true; - - this.blendMode = PIXI.blendModes.NORMAL -} - -// constructor -PIXI.TilingSprite.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite; - -/** - * Sets the texture of the tiling sprite - * - * @method setTexture - * @param texture {Texture} The PIXI texture that is displayed by the sprite - */ -PIXI.TilingSprite.prototype.setTexture = function(texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - - // stop current texture - this.texture = texture; - this.updateFrame = true; -} - -/** - * When the texture is updated, this event will fire to update the frame - * - * @method onTextureUpdate - * @param event - * @private - */ -PIXI.TilingSprite.prototype.onTextureUpdate = function(event) -{ - this.updateFrame = true; -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * - * Awesome JS run time provided by EsotericSoftware - * https://github.com/EsotericSoftware/spine-runtimes - * - */ - -/** - * 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)) { - continue; - } - var spriteName = attachment.rendererObject.name; - var sprite = this.createSprite(slot, attachment.rendererObject); - slot.currentSprite = sprite; - slot.currentSpriteName = spriteName; - slotContainer.addChild(sprite); - } -}; - -PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); -PIXI.Spine.prototype.constructor = PIXI.Spine; - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.Spine.prototype.updateTransform = function () { - this.lastTime = this.lastTime || Date.now(); - var timeDelta = (Date.now() - this.lastTime) * 0.001; - this.lastTime = Date.now(); - this.state.update(timeDelta); - 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 instanceof spine.RegionAttachment)) { - slotContainer.visible = false; - continue; - } - - 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.rendererObject); - slotContainer.addChild(sprite); - } - slot.currentSprite = slot.sprites[spriteName]; - slot.currentSpriteName = spriteName; - } - } - slotContainer.visible = true; - - 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 * Math.PI / 180); - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -}; - - -PIXI.Spine.prototype.createSprite = function (slot, descriptor) { - var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); - sprite.scale = descriptor.scale; - sprite.rotation = descriptor.rotation; - sprite.anchor.x = sprite.anchor.y = 0.5; - - slot.sprites = slot.sprites || {}; - slot.sprites[descriptor.name] = sprite; - return sprite; -}; - -/* - * Awesome JS run time provided by EsotericSoftware - * - * https://github.com/EsotericSoftware/spine-runtimes - * - */ - -var spine = {}; - -spine.BoneData = function (name, parent) { - this.name = name; - this.parent = parent; -}; -spine.BoneData.prototype = { - length: 0, - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1 -}; - -spine.SlotData = function (name, boneData) { - this.name = name; - this.boneData = boneData; -}; -spine.SlotData.prototype = { - r: 1, g: 1, b: 1, a: 1, - attachmentName: null -}; - -spine.Bone = function (boneData, parent) { - this.data = boneData; - this.parent = parent; - this.setToSetupPose(); -}; -spine.Bone.yDown = false; -spine.Bone.prototype = { - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1, - m00: 0, m01: 0, worldX: 0, // a b x - m10: 0, m11: 0, worldY: 0, // c d y - worldRotation: 0, - worldScaleX: 1, worldScaleY: 1, - updateWorldTransform: function (flipX, flipY) { - var parent = this.parent; - if (parent != null) { - this.worldX = this.x * parent.m00 + this.y * parent.m01 + parent.worldX; - this.worldY = this.x * parent.m10 + this.y * parent.m11 + parent.worldY; - this.worldScaleX = parent.worldScaleX * this.scaleX; - this.worldScaleY = parent.worldScaleY * this.scaleY; - this.worldRotation = parent.worldRotation + this.rotation; - } else { - this.worldX = this.x; - this.worldY = this.y; - this.worldScaleX = this.scaleX; - this.worldScaleY = this.scaleY; - this.worldRotation = this.rotation; - } - var radians = this.worldRotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - this.m00 = cos * this.worldScaleX; - this.m10 = sin * this.worldScaleX; - this.m01 = -sin * this.worldScaleY; - this.m11 = cos * this.worldScaleY; - if (flipX) { - this.m00 = -this.m00; - this.m01 = -this.m01; - } - if (flipY) { - this.m10 = -this.m10; - this.m11 = -this.m11; - } - if (spine.Bone.yDown) { - this.m10 = -this.m10; - this.m11 = -this.m11; - } - }, - setToSetupPose: function () { - var data = this.data; - this.x = data.x; - this.y = data.y; - this.rotation = data.rotation; - this.scaleX = data.scaleX; - this.scaleY = data.scaleY; - } -}; - -spine.Slot = function (slotData, skeleton, bone) { - this.data = slotData; - this.skeleton = skeleton; - this.bone = bone; - this.setToSetupPose(); -}; -spine.Slot.prototype = { - r: 1, g: 1, b: 1, a: 1, - _attachmentTime: 0, - attachment: null, - setAttachment: function (attachment) { - this.attachment = attachment; - this._attachmentTime = this.skeleton.time; - }, - setAttachmentTime: function (time) { - this._attachmentTime = this.skeleton.time - time; - }, - getAttachmentTime: function () { - return this.skeleton.time - this._attachmentTime; - }, - setToSetupPose: function () { - var data = this.data; - this.r = data.r; - this.g = data.g; - this.b = data.b; - this.a = data.a; - - var slotDatas = this.skeleton.data.slots; - for (var i = 0, n = slotDatas.length; i < n; i++) { - if (slotDatas[i] == data) { - this.setAttachment(!data.attachmentName ? null : this.skeleton.getAttachmentBySlotIndex(i, data.attachmentName)); - break; - } - } - } -}; - -spine.Skin = function (name) { - this.name = name; - this.attachments = {}; -}; -spine.Skin.prototype = { - addAttachment: function (slotIndex, name, attachment) { - this.attachments[slotIndex + ":" + name] = attachment; - }, - getAttachment: function (slotIndex, name) { - return this.attachments[slotIndex + ":" + name]; - }, - _attachAll: function (skeleton, oldSkin) { - for (var key in oldSkin.attachments) { - var colon = key.indexOf(":"); - var slotIndex = parseInt(key.substring(0, colon)); - var name = key.substring(colon + 1); - var slot = skeleton.slots[slotIndex]; - if (slot.attachment && slot.attachment.name == name) { - var attachment = this.getAttachment(slotIndex, name); - if (attachment) slot.setAttachment(attachment); - } - } - } -}; - -spine.Animation = function (name, timelines, duration) { - this.name = name; - this.timelines = timelines; - this.duration = duration; -}; -spine.Animation.prototype = { - apply: function (skeleton, time, loop) { - if (loop && this.duration != 0) time %= this.duration; - var timelines = this.timelines; - for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, time, 1); - }, - mix: function (skeleton, time, loop, alpha) { - if (loop && this.duration != 0) time %= this.duration; - var timelines = this.timelines; - for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, time, alpha); - } -}; - -spine.binarySearch = function (values, target, step) { - var low = 0; - var high = Math.floor(values.length / step) - 2; - if (high == 0) return step; - var current = high >>> 1; - while (true) { - if (values[(current + 1) * step] <= target) - low = current + 1; - else - high = current; - if (low == high) return (low + 1) * step; - current = (low + high) >>> 1; - } -}; -spine.linearSearch = function (values, target, step) { - for (var i = 0, last = values.length - step; i <= last; i += step) - if (values[i] > target) return i; - return -1; -}; - -spine.Curves = function (frameCount) { - this.curves = []; // dfx, dfy, ddfx, ddfy, dddfx, dddfy, ... - this.curves.length = (frameCount - 1) * 6; -}; -spine.Curves.prototype = { - setLinear: function (frameIndex) { - this.curves[frameIndex * 6] = 0/*LINEAR*/; - }, - setStepped: function (frameIndex) { - this.curves[frameIndex * 6] = -1/*STEPPED*/; - }, - /** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next. - * cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of - * the difference between the keyframe's values. */ - setCurve: function (frameIndex, cx1, cy1, cx2, cy2) { - var subdiv_step = 1 / 10/*BEZIER_SEGMENTS*/; - var subdiv_step2 = subdiv_step * subdiv_step; - var subdiv_step3 = subdiv_step2 * subdiv_step; - var pre1 = 3 * subdiv_step; - var pre2 = 3 * subdiv_step2; - var pre4 = 6 * subdiv_step2; - var pre5 = 6 * subdiv_step3; - var tmp1x = -cx1 * 2 + cx2; - var tmp1y = -cy1 * 2 + cy2; - var tmp2x = (cx1 - cx2) * 3 + 1; - var tmp2y = (cy1 - cy2) * 3 + 1; - var i = frameIndex * 6; - var curves = this.curves; - curves[i] = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; - curves[i + 1] = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; - curves[i + 2] = tmp1x * pre4 + tmp2x * pre5; - curves[i + 3] = tmp1y * pre4 + tmp2y * pre5; - curves[i + 4] = tmp2x * pre5; - curves[i + 5] = tmp2y * pre5; - }, - getCurvePercent: function (frameIndex, percent) { - percent = percent < 0 ? 0 : (percent > 1 ? 1 : percent); - var curveIndex = frameIndex * 6; - var curves = this.curves; - var dfx = curves[curveIndex]; - if (!dfx/*LINEAR*/) return percent; - if (dfx == -1/*STEPPED*/) return 0; - var dfy = curves[curveIndex + 1]; - var ddfx = curves[curveIndex + 2]; - var ddfy = curves[curveIndex + 3]; - var dddfx = curves[curveIndex + 4]; - var dddfy = curves[curveIndex + 5]; - var x = dfx, y = dfy; - var i = 10/*BEZIER_SEGMENTS*/ - 2; - while (true) { - if (x >= percent) { - var lastX = x - dfx; - var lastY = y - dfy; - return lastY + (y - lastY) * (percent - lastX) / (x - lastX); - } - if (i == 0) break; - i--; - dfx += ddfx; - dfy += ddfy; - ddfx += dddfx; - ddfy += dddfy; - x += dfx; - y += dfy; - } - return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1. - } -}; - -spine.RotateTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, angle, ... - this.frames.length = frameCount * 2; -}; -spine.RotateTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 2; - }, - setFrame: function (frameIndex, time, angle) { - frameIndex *= 2; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = angle; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 2]) { // Time is after last frame. - var amount = bone.data.rotation + frames[frames.length - 1] - bone.rotation; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - bone.rotation += amount * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 2); - var lastFrameValue = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex - 2/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent); - - var amount = frames[frameIndex + 1/*FRAME_VALUE*/] - lastFrameValue; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - amount = bone.data.rotation + (lastFrameValue + amount * percent) - bone.rotation; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - bone.rotation += amount * alpha; - } -}; - -spine.TranslateTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, x, y, ... - this.frames.length = frameCount * 3; -}; -spine.TranslateTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 3; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 3; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = x; - this.frames[frameIndex + 2] = y; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 3]) { // Time is after last frame. - bone.x += (bone.data.x + frames[frames.length - 2] - bone.x) * alpha; - bone.y += (bone.data.y + frames[frames.length - 1] - bone.y) * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 3); - var lastFrameX = frames[frameIndex - 2]; - var lastFrameY = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); - - bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; - bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; - } -}; - -spine.ScaleTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, x, y, ... - this.frames.length = frameCount * 3; -}; -spine.ScaleTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 3; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 3; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = x; - this.frames[frameIndex + 2] = y; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 3]) { // Time is after last frame. - bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 3); - var lastFrameX = frames[frameIndex - 2]; - var lastFrameY = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); - - bone.scaleX += (bone.data.scaleX - 1 + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - 1 + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.scaleY) * alpha; - } -}; - -spine.ColorTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, r, g, b, a, ... - this.frames.length = frameCount * 5; -}; -spine.ColorTimeline.prototype = { - slotIndex: 0, - getFrameCount: function () { - return this.frames.length / 2; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 5; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = r; - this.frames[frameIndex + 2] = g; - this.frames[frameIndex + 3] = b; - this.frames[frameIndex + 4] = a; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var slot = skeleton.slots[this.slotIndex]; - - if (time >= frames[frames.length - 5]) { // Time is after last frame. - var i = frames.length - 1; - slot.r = frames[i - 3]; - slot.g = frames[i - 2]; - slot.b = frames[i - 1]; - slot.a = frames[i]; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 5); - var lastFrameR = frames[frameIndex - 4]; - var lastFrameG = frames[frameIndex - 3]; - var lastFrameB = frames[frameIndex - 2]; - var lastFrameA = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex - 5/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent); - - var r = lastFrameR + (frames[frameIndex + 1/*FRAME_R*/] - lastFrameR) * percent; - var g = lastFrameG + (frames[frameIndex + 2/*FRAME_G*/] - lastFrameG) * percent; - var b = lastFrameB + (frames[frameIndex + 3/*FRAME_B*/] - lastFrameB) * percent; - var a = lastFrameA + (frames[frameIndex + 4/*FRAME_A*/] - lastFrameA) * percent; - if (alpha < 1) { - slot.r += (r - slot.r) * alpha; - slot.g += (g - slot.g) * alpha; - slot.b += (b - slot.b) * alpha; - slot.a += (a - slot.a) * alpha; - } else { - slot.r = r; - slot.g = g; - slot.b = b; - slot.a = a; - } - } -}; - -spine.AttachmentTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, ... - this.frames.length = frameCount; - this.attachmentNames = []; // time, ... - this.attachmentNames.length = frameCount; -}; -spine.AttachmentTimeline.prototype = { - slotIndex: 0, - getFrameCount: function () { - return this.frames.length; - }, - setFrame: function (frameIndex, time, attachmentName) { - this.frames[frameIndex] = time; - this.attachmentNames[frameIndex] = attachmentName; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var frameIndex; - if (time >= frames[frames.length - 1]) // Time is after last frame. - frameIndex = frames.length - 1; - else - frameIndex = spine.binarySearch(frames, time, 1) - 1; - - var attachmentName = this.attachmentNames[frameIndex]; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); - } -}; - -spine.SkeletonData = function () { - this.bones = []; - this.slots = []; - this.skins = []; - this.animations = []; -}; -spine.SkeletonData.prototype = { - defaultSkin: null, - /** @return May be null. */ - findBone: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].name == boneName) return bones[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findBoneIndex: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].name == boneName) return i; - return -1; - }, - /** @return May be null. */ - findSlot: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) { - if (slots[i].name == slotName) return slot[i]; - } - return null; - }, - /** @return -1 if the bone was not found. */ - findSlotIndex: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].name == slotName) return i; - return -1; - }, - /** @return May be null. */ - findSkin: function (skinName) { - var skins = this.skins; - for (var i = 0, n = skins.length; i < n; i++) - if (skins[i].name == skinName) return skins[i]; - return null; - }, - /** @return May be null. */ - findAnimation: function (animationName) { - var animations = this.animations; - for (var i = 0, n = animations.length; i < n; i++) - if (animations[i].name == animationName) return animations[i]; - return null; - } -}; - -spine.Skeleton = function (skeletonData) { - this.data = skeletonData; - - this.bones = []; - for (var i = 0, n = skeletonData.bones.length; i < n; i++) { - var boneData = skeletonData.bones[i]; - var parent = !boneData.parent ? null : this.bones[skeletonData.bones.indexOf(boneData.parent)]; - this.bones.push(new spine.Bone(boneData, parent)); - } - - this.slots = []; - this.drawOrder = []; - for (var i = 0, n = skeletonData.slots.length; i < n; i++) { - var slotData = skeletonData.slots[i]; - var bone = this.bones[skeletonData.bones.indexOf(slotData.boneData)]; - var slot = new spine.Slot(slotData, this, bone); - this.slots.push(slot); - this.drawOrder.push(slot); - } -}; -spine.Skeleton.prototype = { - x: 0, y: 0, - skin: null, - r: 1, g: 1, b: 1, a: 1, - time: 0, - flipX: false, flipY: false, - /** Updates the world transform for each bone. */ - updateWorldTransform: function () { - var flipX = this.flipX; - var flipY = this.flipY; - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - bones[i].updateWorldTransform(flipX, flipY); - }, - /** Sets the bones and slots to their setup pose values. */ - setToSetupPose: function () { - this.setBonesToSetupPose(); - this.setSlotsToSetupPose(); - }, - setBonesToSetupPose: function () { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - bones[i].setToSetupPose(); - }, - setSlotsToSetupPose: function () { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - slots[i].setToSetupPose(i); - }, - /** @return May return null. */ - getRootBone: function () { - return this.bones.length == 0 ? null : this.bones[0]; - }, - /** @return May be null. */ - findBone: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].data.name == boneName) return bones[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findBoneIndex: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].data.name == boneName) return i; - return -1; - }, - /** @return May be null. */ - findSlot: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].data.name == slotName) return slots[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findSlotIndex: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].data.name == slotName) return i; - return -1; - }, - setSkinByName: function (skinName) { - var skin = this.data.findSkin(skinName); - if (!skin) throw "Skin not found: " + skinName; - this.setSkin(skin); - }, - /** Sets the skin used to look up attachments not found in the {@link SkeletonData#getDefaultSkin() default skin}. Attachments - * from the new skin are attached if the corresponding attachment from the old skin was attached. - * @param newSkin May be null. */ - setSkin: function (newSkin) { - if (this.skin && newSkin) newSkin._attachAll(this, this.skin); - this.skin = newSkin; - }, - /** @return May be null. */ - getAttachmentBySlotName: function (slotName, attachmentName) { - return this.getAttachmentBySlotIndex(this.data.findSlotIndex(slotName), attachmentName); - }, - /** @return May be null. */ - getAttachmentBySlotIndex: function (slotIndex, attachmentName) { - if (this.skin) { - var attachment = this.skin.getAttachment(slotIndex, attachmentName); - if (attachment) return attachment; - } - if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); - return null; - }, - /** @param attachmentName May be null. */ - setAttachment: function (slotName, attachmentName) { - var slots = this.slots; - for (var i = 0, n = slots.size; i < n; i++) { - var slot = slots[i]; - if (slot.data.name == slotName) { - var attachment = null; - if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); - if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; - } - slot.setAttachment(attachment); - return; - } - } - throw "Slot not found: " + slotName; - }, - update: function (delta) { - time += delta; - } -}; - -spine.AttachmentType = { - region: 0 -}; - -spine.RegionAttachment = function () { - this.offset = []; - this.offset.length = 8; - this.uvs = []; - this.uvs.length = 8; -}; -spine.RegionAttachment.prototype = { - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1, - width: 0, height: 0, - rendererObject: null, - regionOffsetX: 0, regionOffsetY: 0, - regionWidth: 0, regionHeight: 0, - regionOriginalWidth: 0, regionOriginalHeight: 0, - setUVs: function (u, v, u2, v2, rotate) { - var uvs = this.uvs; - if (rotate) { - uvs[2/*X2*/] = u; - uvs[3/*Y2*/] = v2; - uvs[4/*X3*/] = u; - uvs[5/*Y3*/] = v; - uvs[6/*X4*/] = u2; - uvs[7/*Y4*/] = v; - uvs[0/*X1*/] = u2; - uvs[1/*Y1*/] = v2; - } else { - uvs[0/*X1*/] = u; - uvs[1/*Y1*/] = v2; - uvs[2/*X2*/] = u; - uvs[3/*Y2*/] = v; - uvs[4/*X3*/] = u2; - uvs[5/*Y3*/] = v; - uvs[6/*X4*/] = u2; - uvs[7/*Y4*/] = v2; - } - }, - updateOffset: function () { - var regionScaleX = this.width / this.regionOriginalWidth * this.scaleX; - var regionScaleY = this.height / this.regionOriginalHeight * this.scaleY; - var localX = -this.width / 2 * this.scaleX + this.regionOffsetX * regionScaleX; - var localY = -this.height / 2 * this.scaleY + this.regionOffsetY * regionScaleY; - var localX2 = localX + this.regionWidth * regionScaleX; - var localY2 = localY + this.regionHeight * regionScaleY; - var radians = this.rotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - var localXCos = localX * cos + this.x; - var localXSin = localX * sin; - var localYCos = localY * cos + this.y; - var localYSin = localY * sin; - var localX2Cos = localX2 * cos + this.x; - var localX2Sin = localX2 * sin; - var localY2Cos = localY2 * cos + this.y; - var localY2Sin = localY2 * sin; - var offset = this.offset; - offset[0/*X1*/] = localXCos - localYSin; - offset[1/*Y1*/] = localYCos + localXSin; - offset[2/*X2*/] = localXCos - localY2Sin; - offset[3/*Y2*/] = localY2Cos + localXSin; - offset[4/*X3*/] = localX2Cos - localY2Sin; - offset[5/*Y3*/] = localY2Cos + localX2Sin; - offset[6/*X4*/] = localX2Cos - localYSin; - offset[7/*Y4*/] = localYCos + localX2Sin; - }, - computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; - y += bone.worldY; - var m00 = bone.m00; - var m01 = bone.m01; - var m10 = bone.m10; - var m11 = bone.m11; - var offset = this.offset; - vertices[0/*X1*/] = offset[0/*X1*/] * m00 + offset[1/*Y1*/] * m01 + x; - vertices[1/*Y1*/] = offset[0/*X1*/] * m10 + offset[1/*Y1*/] * m11 + y; - vertices[2/*X2*/] = offset[2/*X2*/] * m00 + offset[3/*Y2*/] * m01 + x; - vertices[3/*Y2*/] = offset[2/*X2*/] * m10 + offset[3/*Y2*/] * m11 + y; - vertices[4/*X3*/] = offset[4/*X3*/] * m00 + offset[5/*X3*/] * m01 + x; - vertices[5/*X3*/] = offset[4/*X3*/] * m10 + offset[5/*X3*/] * m11 + y; - vertices[6/*X4*/] = offset[6/*X4*/] * m00 + offset[7/*Y4*/] * m01 + x; - vertices[7/*Y4*/] = offset[6/*X4*/] * m10 + offset[7/*Y4*/] * m11 + y; - } -} - -spine.AnimationStateData = function (skeletonData) { - this.skeletonData = skeletonData; - this.animationToMixTime = {}; -}; -spine.AnimationStateData.prototype = { - defaultMix: 0, - setMixByName: function (fromName, toName, duration) { - var from = this.skeletonData.findAnimation(fromName); - if (!from) throw "Animation not found: " + fromName; - var to = this.skeletonData.findAnimation(toName); - if (!to) throw "Animation not found: " + toName; - this.setMix(from, to, duration); - }, - setMix: function (from, to, duration) { - this.animationToMixTime[from.name + ":" + to.name] = duration; - }, - getMix: function (from, to) { - var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : this.defaultMix; - } -}; - -spine.AnimationState = function (stateData) { - this.data = stateData; - this.queue = []; -}; -spine.AnimationState.prototype = { - current: null, - previous: null, - currentTime: 0, - previousTime: 0, - currentLoop: false, - previousLoop: false, - mixTime: 0, - mixDuration: 0, - update: function (delta) { - this.currentTime += delta; - this.previousTime += delta; - this.mixTime += delta; - - if (this.queue.length > 0) { - var entry = this.queue[0]; - if (this.currentTime >= entry.delay) { - this._setAnimation(entry.animation, entry.loop); - this.queue.shift(); - } - } - }, - apply: function (skeleton) { - if (!this.current) return; - if (this.previous) { - this.previous.apply(skeleton, this.previousTime, this.previousLoop); - var alpha = this.mixTime / this.mixDuration; - if (alpha >= 1) { - alpha = 1; - this.previous = null; - } - this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else - this.current.apply(skeleton, this.currentTime, this.currentLoop); - }, - clearAnimation: function () { - this.previous = null; - this.current = null; - this.queue.length = 0; - }, - _setAnimation: function (animation, loop) { - this.previous = null; - if (animation && this.current) { - this.mixDuration = this.data.getMix(this.current, animation); - if (this.mixDuration > 0) { - this.mixTime = 0; - this.previous = this.current; - this.previousTime = this.currentTime; - this.previousLoop = this.currentLoop; - } - } - this.current = animation; - this.currentLoop = loop; - this.currentTime = 0; - }, - /** @see #setAnimation(Animation, Boolean) */ - setAnimationByName: function (animationName, loop) { - var animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw "Animation not found: " + animationName; - this.setAnimation(animation, loop); - }, - /** Set the current animation. Any queued animations are cleared and the current animation time is set to 0. - * @param animation May be null. */ - setAnimation: function (animation, loop) { - this.queue.length = 0; - this._setAnimation(animation, loop); - }, - /** @see #addAnimation(Animation, Boolean, Number) */ - addAnimationByName: function (animationName, loop, delay) { - var animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw "Animation not found: " + animationName; - this.addAnimation(animation, loop, delay); - }, - /** Adds an animation to be played delay seconds after the current or last queued animation. - * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */ - addAnimation: function (animation, loop, delay) { - var entry = {}; - entry.animation = animation; - entry.loop = loop; - - if (!delay || delay <= 0) { - var previousAnimation = this.queue.length == 0 ? this.current : this.queue[this.queue.length - 1].animation; - if (previousAnimation != null) - delay = previousAnimation.duration - this.data.getMix(previousAnimation, animation) + (delay || 0); - else - delay = 0; - } - entry.delay = delay; - - this.queue.push(entry); - }, - /** Returns true if no animation is set or if the current time is greater than the animation duration, regardless of looping. */ - isComplete: function () { - return !this.current || this.currentTime >= this.current.duration; - } -}; - -spine.SkeletonJson = function (attachmentLoader) { - this.attachmentLoader = attachmentLoader; -}; -spine.SkeletonJson.prototype = { - scale: 1, - readSkeletonData: function (root) { - var skeletonData = new spine.SkeletonData(); - - // Bones. - var bones = root["bones"]; - for (var i = 0, n = bones.length; i < n; i++) { - var boneMap = bones[i]; - var parent = null; - if (boneMap["parent"]) { - parent = skeletonData.findBone(boneMap["parent"]); - if (!parent) throw "Parent bone not found: " + boneMap["parent"]; - } - var boneData = new spine.BoneData(boneMap["name"], parent); - boneData.length = (boneMap["length"] || 0) * this.scale; - boneData.x = (boneMap["x"] || 0) * this.scale; - boneData.y = (boneMap["y"] || 0) * this.scale; - boneData.rotation = (boneMap["rotation"] || 0); - boneData.scaleX = boneMap["scaleX"] || 1; - boneData.scaleY = boneMap["scaleY"] || 1; - skeletonData.bones.push(boneData); - } - - // Slots. - var slots = root["slots"]; - for (var i = 0, n = slots.length; i < n; i++) { - var slotMap = slots[i]; - var boneData = skeletonData.findBone(slotMap["bone"]); - if (!boneData) throw "Slot bone not found: " + slotMap["bone"]; - var slotData = new spine.SlotData(slotMap["name"], boneData); - - var color = slotMap["color"]; - if (color) { - slotData.r = spine.SkeletonJson.toColor(color, 0); - slotData.g = spine.SkeletonJson.toColor(color, 1); - slotData.b = spine.SkeletonJson.toColor(color, 2); - slotData.a = spine.SkeletonJson.toColor(color, 3); - } - - slotData.attachmentName = slotMap["attachment"]; - - skeletonData.slots.push(slotData); - } - - // Skins. - var skins = root["skins"]; - for (var skinName in skins) { - if (!skins.hasOwnProperty(skinName)) continue; - var skinMap = skins[skinName]; - var skin = new spine.Skin(skinName); - for (var slotName in skinMap) { - if (!skinMap.hasOwnProperty(slotName)) continue; - var slotIndex = skeletonData.findSlotIndex(slotName); - var slotEntry = skinMap[slotName]; - for (var attachmentName in slotEntry) { - if (!slotEntry.hasOwnProperty(attachmentName)) continue; - var attachment = this.readAttachment(skin, attachmentName, slotEntry[attachmentName]); - if (attachment != null) skin.addAttachment(slotIndex, attachmentName, attachment); - } - } - skeletonData.skins.push(skin); - if (skin.name == "default") skeletonData.defaultSkin = skin; - } - - // Animations. - var animations = root["animations"]; - for (var animationName in animations) { - if (!animations.hasOwnProperty(animationName)) continue; - this.readAnimation(animationName, animations[animationName], skeletonData); - } - - return skeletonData; - }, - readAttachment: function (skin, name, map) { - name = map["name"] || name; - - var type = spine.AttachmentType[map["type"] || "region"]; - - if (type == spine.AttachmentType.region) { - var attachment = new spine.RegionAttachment(); - attachment.x = (map["x"] || 0) * this.scale; - attachment.y = (map["y"] || 0) * this.scale; - attachment.scaleX = map["scaleX"] || 1; - attachment.scaleY = map["scaleY"] || 1; - attachment.rotation = map["rotation"] || 0; - attachment.width = (map["width"] || 32) * this.scale; - attachment.height = (map["height"] || 32) * this.scale; - attachment.updateOffset(); - - attachment.rendererObject = {}; - attachment.rendererObject.name = name; - attachment.rendererObject.scale = {}; - attachment.rendererObject.scale.x = attachment.scaleX; - attachment.rendererObject.scale.y = attachment.scaleY; - attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; - return attachment; - } - - throw "Unknown attachment type: " + type; - }, - - readAnimation: function (name, map, skeletonData) { - var timelines = []; - var duration = 0; - - var bones = map["bones"]; - for (var boneName in bones) { - if (!bones.hasOwnProperty(boneName)) continue; - var boneIndex = skeletonData.findBoneIndex(boneName); - if (boneIndex == -1) throw "Bone not found: " + boneName; - var boneMap = bones[boneName]; - - for (var timelineName in boneMap) { - if (!boneMap.hasOwnProperty(timelineName)) continue; - var values = boneMap[timelineName]; - if (timelineName == "rotate") { - var timeline = new spine.RotateTimeline(values.length); - timeline.boneIndex = boneIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - timeline.setFrame(frameIndex, valueMap["time"], valueMap["angle"]); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 2 - 2]); - - } else if (timelineName == "translate" || timelineName == "scale") { - var timeline; - var timelineScale = 1; - if (timelineName == "scale") - timeline = new spine.ScaleTimeline(values.length); - else { - timeline = new spine.TranslateTimeline(values.length); - timelineScale = this.scale; - } - timeline.boneIndex = boneIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - var x = (valueMap["x"] || 0) * timelineScale; - var y = (valueMap["y"] || 0) * timelineScale; - timeline.setFrame(frameIndex, valueMap["time"], x, y); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - - } else - throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; - } - } - var slots = map["slots"]; - for (var slotName in slots) { - if (!slots.hasOwnProperty(slotName)) continue; - var slotMap = slots[slotName]; - var slotIndex = skeletonData.findSlotIndex(slotName); - - for (var timelineName in slotMap) { - if (!slotMap.hasOwnProperty(timelineName)) continue; - var values = slotMap[timelineName]; - if (timelineName == "color") { - var timeline = new spine.ColorTimeline(values.length); - timeline.slotIndex = slotIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - var color = valueMap["color"]; - var r = spine.SkeletonJson.toColor(color, 0); - var g = spine.SkeletonJson.toColor(color, 1); - var b = spine.SkeletonJson.toColor(color, 2); - var a = spine.SkeletonJson.toColor(color, 3); - timeline.setFrame(frameIndex, valueMap["time"], r, g, b, a); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 5 - 5]); - - } else if (timelineName == "attachment") { - var timeline = new spine.AttachmentTimeline(values.length); - timeline.slotIndex = slotIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); - - } else - throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; - } - } - skeletonData.animations.push(new spine.Animation(name, timelines, duration)); - } -}; -spine.SkeletonJson.readCurve = function (timeline, frameIndex, valueMap) { - var curve = valueMap["curve"]; - if (!curve) return; - if (curve == "stepped") - timeline.curves.setStepped(frameIndex); - else if (curve instanceof Array) - timeline.curves.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); -}; -spine.SkeletonJson.toColor = function (hexString, colorIndex) { - if (hexString.length != 8) throw "Color hexidecimal length must be 8, recieved: " + hexString; - return parseInt(hexString.substring(colorIndex * 2, 2), 16) / 255; -}; - -spine.Atlas = function (atlasText, textureLoader) { - this.textureLoader = textureLoader; - this.pages = []; - this.regions = []; - - var reader = new spine.AtlasReader(atlasText); - var tuple = []; - tuple.length = 4; - var page = null; - while (true) { - var line = reader.readLine(); - if (line == null) break; - line = reader.trim(line); - if (line.length == 0) - page = null; - else if (!page) { - page = new spine.AtlasPage(); - page.name = line; - - page.format = spine.Atlas.Format[reader.readValue()]; - - reader.readTuple(tuple); - page.minFilter = spine.Atlas.TextureFilter[tuple[0]]; - page.magFilter = spine.Atlas.TextureFilter[tuple[1]]; - - var direction = reader.readValue(); - page.uWrap = spine.Atlas.TextureWrap.clampToEdge; - page.vWrap = spine.Atlas.TextureWrap.clampToEdge; - if (direction == "x") - page.uWrap = spine.Atlas.TextureWrap.repeat; - else if (direction == "y") - page.vWrap = spine.Atlas.TextureWrap.repeat; - else if (direction == "xy") - page.uWrap = page.vWrap = spine.Atlas.TextureWrap.repeat; - - textureLoader.load(page, line); - - this.pages.push(page); - - } else { - var region = new spine.AtlasRegion(); - region.name = line; - region.page = page; - - region.rotate = reader.readValue() == "true"; - - reader.readTuple(tuple); - var x = parseInt(tuple[0]); - var y = parseInt(tuple[1]); - - reader.readTuple(tuple); - var width = parseInt(tuple[0]); - var height = parseInt(tuple[1]); - - region.u = x / page.width; - region.v = y / page.height; - if (region.rotate) { - region.u2 = (x + height) / page.width; - region.v2 = (y + width) / page.height; - } else { - region.u2 = (x + width) / page.width; - region.v2 = (y + height) / page.height; - } - region.x = x; - region.y = y; - region.width = Math.abs(width); - region.height = Math.abs(height); - - if (reader.readTuple(tuple) == 4) { // split is optional - region.splits = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; - - if (reader.readTuple(tuple) == 4) { // pad is optional, but only present with splits - region.pads = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; - - reader.readTuple(tuple); - } - } - - region.originalWidth = parseInt(tuple[0]); - region.originalHeight = parseInt(tuple[1]); - - reader.readTuple(tuple); - region.offsetX = parseInt(tuple[0]); - region.offsetY = parseInt(tuple[1]); - - region.index = parseInt(reader.readValue()); - - this.regions.push(region); - } - } -}; -spine.Atlas.prototype = { - findRegion: function (name) { - var regions = this.regions; - for (var i = 0, n = regions.length; i < n; i++) - if (regions[i].name == name) return regions[i]; - return null; - }, - dispose: function () { - var pages = this.pages; - for (var i = 0, n = pages.length; i < n; i++) - this.textureLoader.unload(pages[i].rendererObject); - }, - updateUVs: function (page) { - var regions = this.regions; - for (var i = 0, n = regions.length; i < n; i++) { - var region = regions[i]; - if (region.page != page) continue; - region.u = region.x / page.width; - region.v = region.y / page.height; - if (region.rotate) { - region.u2 = (region.x + region.height) / page.width; - region.v2 = (region.y + region.width) / page.height; - } else { - region.u2 = (region.x + region.width) / page.width; - region.v2 = (region.y + region.height) / page.height; - } - } - } -}; - -spine.Atlas.Format = { - alpha: 0, - intensity: 1, - luminanceAlpha: 2, - rgb565: 3, - rgba4444: 4, - rgb888: 5, - rgba8888: 6 -}; - -spine.Atlas.TextureFilter = { - nearest: 0, - linear: 1, - mipMap: 2, - mipMapNearestNearest: 3, - mipMapLinearNearest: 4, - mipMapNearestLinear: 5, - mipMapLinearLinear: 6 -}; - -spine.Atlas.TextureWrap = { - mirroredRepeat: 0, - clampToEdge: 1, - repeat: 2 -}; - -spine.AtlasPage = function () {}; -spine.AtlasPage.prototype = { - name: null, - format: null, - minFilter: null, - magFilter: null, - uWrap: null, - vWrap: null, - rendererObject: null, - width: 0, - height: 0 -}; - -spine.AtlasRegion = function () {}; -spine.AtlasRegion.prototype = { - page: null, - name: null, - x: 0, y: 0, - width: 0, height: 0, - u: 0, v: 0, u2: 0, v2: 0, - offsetX: 0, offsetY: 0, - originalWidth: 0, originalHeight: 0, - index: 0, - rotate: false, - splits: null, - pads: null, -}; - -spine.AtlasReader = function (text) { - this.lines = text.split(/\r\n|\r|\n/); -}; -spine.AtlasReader.prototype = { - index: 0, - trim: function (value) { - return value.replace(/^\s+|\s+$/g, ""); - }, - readLine: function () { - if (this.index >= this.lines.length) return null; - return this.lines[this.index++]; - }, - readValue: function () { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) throw "Invalid line: " + line; - return this.trim(line.substring(colon + 1)); - }, - /** Returns the number of tuple values read (2 or 4). */ - readTuple: function (tuple) { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) throw "Invalid line: " + line; - var i = 0, lastMatch= colon + 1; - for (; i < 3; i++) { - var comma = line.indexOf(",", lastMatch); - if (comma == -1) { - if (i == 0) throw "Invalid line: " + line; - break; - } - tuple[i] = this.trim(line.substr(lastMatch, comma - lastMatch)); - lastMatch = comma + 1; - } - tuple[i] = this.trim(line.substring(lastMatch)); - return i + 1; - } -} - -spine.AtlasAttachmentLoader = function (atlas) { - this.atlas = atlas; -} -spine.AtlasAttachmentLoader.prototype = { - newAttachment: function (skin, type, name) { - switch (type) { - case spine.AttachmentType.region: - var region = this.atlas.findRegion(name); - if (!region) throw "Region not found in atlas: " + name + " (" + type + ")"; - var attachment = new spine.RegionAttachment(name); - attachment.rendererObject = region; - attachment.setUVs(region.u, region.v, region.u2, region.v2, region.rotate); - attachment.regionOffsetX = region.offsetX; - attachment.regionOffsetY = region.offsetY; - attachment.regionWidth = region.width; - attachment.regionHeight = region.height; - attachment.regionOriginalWidth = region.originalWidth; - attachment.regionOriginalHeight = region.originalHeight; - return attachment; - } - throw "Unknown attachment type: " + type; - } -} - -PIXI.AnimCache = {}; -spine.Bone.yDown = true; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * This object is one that will allow you to specify custom rendering functions based on render type - * - * @class CustomRenderable - * @extends DisplayObject - * @constructor - */ -PIXI.CustomRenderable = function() -{ - PIXI.DisplayObject.call( this ); - - this.renderable = true; -} - -// constructor -PIXI.CustomRenderable.prototype = Object.create( PIXI.DisplayObject.prototype ); -PIXI.CustomRenderable.prototype.constructor = PIXI.CustomRenderable; - -/** - * If this object is being rendered by a CanvasRenderer it will call this callback - * - * @method renderCanvas - * @param renderer {CanvasRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.renderCanvas = function(renderer) -{ - // override! -} - -/** - * If this object is being rendered by a WebGLRenderer it will call this callback to initialize - * - * @method initWebGL - * @param renderer {WebGLRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.initWebGL = function(renderer) -{ - // override! -} - -/** - * If this object is being rendered by a WebGLRenderer it will call this callback - * - * @method renderWebGL - * @param renderer {WebGLRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.renderWebGL = function(renderGroup, projectionMatrix) -{ - // not sure if both needed? but ya have for now! - // override! -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.BaseTextureCache = {}; -PIXI.texturesToUpdate = []; -PIXI.texturesToDestroy = []; - -/** - * A texture stores the information that represents an image. All textures have a base texture - * - * @class BaseTexture - * @uses EventTarget - * @constructor - * @param source {String} the source object (image or canvas) - */ -PIXI.BaseTexture = function(source) -{ - PIXI.EventTarget.call( this ); - - /** - * [read-only] The width of the base texture set when the image has loaded - * - * @property width - * @type Number - * @readOnly - */ - this.width = 100; - - /** - * [read-only] The height of the base texture set when the image has loaded - * - * @property height - * @type Number - * @readOnly - */ - this.height = 100; - - /** - * [read-only] Describes if the base texture has loaded or not - * - * @property hasLoaded - * @type Boolean - * @readOnly - */ - this.hasLoaded = false; - - /** - * The source that is loaded to create the texture - * - * @property source - * @type Image - */ - this.source = source; - - if(!source)return; - - if(this.source instanceof Image || this.source instanceof HTMLImageElement) - { - if(this.source.complete) - { - this.hasLoaded = true; - this.width = this.source.width; - this.height = this.source.height; - - PIXI.texturesToUpdate.push(this); - } - else - { - - var scope = this; - this.source.onload = function(){ - - scope.hasLoaded = true; - scope.width = scope.source.width; - scope.height = scope.source.height; - - // add it to somewhere... - PIXI.texturesToUpdate.push(scope); - scope.dispatchEvent( { type: 'loaded', content: scope } ); - } - // this.image.src = imageUrl; - } - } - else - { - this.hasLoaded = true; - this.width = this.source.width; - this.height = this.source.height; - - PIXI.texturesToUpdate.push(this); - } - - this._powerOf2 = false; -} - -PIXI.BaseTexture.prototype.constructor = PIXI.BaseTexture; - -/** - * Destroys this base texture - * - * @method destroy - */ -PIXI.BaseTexture.prototype.destroy = function() -{ - if(this.source instanceof Image) - { - this.source.src = null; - } - this.source = null; - PIXI.texturesToDestroy.push(this); -} - -/** - * Helper function that returns a base texture based on an image url - * If the image is not in the base texture cache it will be created and loaded - * - * @static - * @method fromImage - * @param imageUrl {String} The image url of the texture - * @return BaseTexture - */ -PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) -{ - var baseTexture = PIXI.BaseTextureCache[imageUrl]; - if(!baseTexture) - { - // new Image() breaks tex loading in some versions of Chrome. - // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); - if (crossorigin) - { - image.crossOrigin = ''; - } - image.src = imageUrl; - baseTexture = new PIXI.BaseTexture(image); - PIXI.BaseTextureCache[imageUrl] = baseTexture; - } - - return baseTexture; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.TextureCache = {}; -PIXI.FrameCache = {}; - -/** - * A texture stores the information that represents an image or part of an image. It cannot be added - * to the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used - * - * @class Texture - * @uses EventTarget - * @constructor - * @param baseTexture {BaseTexture} The base texture source to create the texture from - * @param frame {Rectangle} The rectangle frame of the texture to show - */ -PIXI.Texture = function(baseTexture, frame) -{ - PIXI.EventTarget.call( this ); - - if(!frame) - { - this.noFrame = true; - frame = new PIXI.Rectangle(0,0,1,1); - } - - if(baseTexture instanceof PIXI.Texture) - baseTexture = baseTexture.baseTexture; - - /** - * The base texture of this texture - * - * @property baseTexture - * @type BaseTexture - */ - this.baseTexture = baseTexture; - - /** - * The frame specifies the region of the base texture that this texture uses - * - * @property frame - * @type Rectangle - */ - this.frame = frame; - - /** - * The trim point - * - * @property trim - * @type Point - */ - this.trim = new PIXI.Point(); - - this.scope = this; - - if(baseTexture.hasLoaded) - { - if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); - //console.log(frame) - - this.setFrame(frame); - } - else - { - var scope = this; - baseTexture.addEventListener( 'loaded', function(){ scope.onBaseTextureLoaded()} ); - } -} - -PIXI.Texture.prototype.constructor = PIXI.Texture; - -/** - * Called when the base texture is loaded - * - * @method onBaseTextureLoaded - * @param event - * @private - */ -PIXI.Texture.prototype.onBaseTextureLoaded = function(event) -{ - var baseTexture = this.baseTexture; - baseTexture.removeEventListener( 'loaded', this.onLoaded ); - - if(this.noFrame)this.frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); - this.noFrame = false; - this.width = this.frame.width; - this.height = this.frame.height; - - this.scope.dispatchEvent( { type: 'update', content: this } ); -} - -/** - * Destroys this texture - * - * @method destroy - * @param destroyBase {Boolean} Whether to destroy the base texture as well - */ -PIXI.Texture.prototype.destroy = function(destroyBase) -{ - if(destroyBase)this.baseTexture.destroy(); -} - -/** - * Specifies the rectangle region of the baseTexture - * - * @method setFrame - * @param frame {Rectangle} The frame of the texture to set it to - */ -PIXI.Texture.prototype.setFrame = function(frame) -{ - this.frame = frame; - this.width = frame.width; - this.height = frame.height; - - if(frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height) - { - throw new Error("Texture Error: frame does not fit inside the base Texture dimensions " + this); - } - - this.updateFrame = true; - - PIXI.Texture.frameUpdates.push(this); - //this.dispatchEvent( { type: 'update', content: this } ); -} - -/** - * Helper function that returns a texture based on an image url - * If the image is not in the texture cache it will be created and loaded - * - * @static - * @method fromImage - * @param imageUrl {String} The image url of the texture - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - * @return Texture - */ -PIXI.Texture.fromImage = function(imageUrl, crossorigin) -{ - var texture = PIXI.TextureCache[imageUrl]; - - if(!texture) - { - texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); - PIXI.TextureCache[imageUrl] = texture; - } - - return texture; -} - -/** - * Helper function that returns a texture based on a frame id - * If the frame id is not in the texture cache an error will be thrown - * - * @static - * @method fromFrame - * @param frameId {String} The frame id of the texture - * @return Texture - */ -PIXI.Texture.fromFrame = function(frameId) -{ - var texture = PIXI.TextureCache[frameId]; - if(!texture)throw new Error("The frameId '"+ frameId +"' does not exist in the texture cache " + this); - return texture; -} - -/** - * Helper function that returns a texture based on a canvas element - * If the canvas is not in the texture cache it will be created and loaded - * - * @static - * @method fromCanvas - * @param canvas {Canvas} The canvas element source of the texture - * @return Texture - */ -PIXI.Texture.fromCanvas = function(canvas) -{ - var baseTexture = new PIXI.BaseTexture(canvas); - return new PIXI.Texture(baseTexture); -} - - -/** - * Adds a texture to the textureCache. - * - * @static - * @method addTextureToCache - * @param texture {Texture} - * @param id {String} the id that the texture will be stored against. - */ -PIXI.Texture.addTextureToCache = function(texture, id) -{ - PIXI.TextureCache[id] = texture; -} - -/** - * Remove a texture from the textureCache. - * - * @static - * @method removeTextureFromCache - * @param id {String} the id of the texture to be removed - * @return {Texture} the texture that was removed - */ -PIXI.Texture.removeTextureFromCache = function(id) -{ - var texture = PIXI.TextureCache[id] - PIXI.TextureCache[id] = null; - return texture; -} - -// this is more for webGL.. it contains updated frames.. -PIXI.Texture.frameUpdates = []; - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - A RenderTexture is a special texture that allows any pixi displayObject to be rendered to it. - - __Hint__: All DisplayObjects (exmpl. Sprites) that renders on RenderTexture should be preloaded. - Otherwise black rectangles will be drawn instead. - - RenderTexture takes snapshot of DisplayObject passed to render method. If DisplayObject is passed to render method, position and rotation of it will be ignored. For example: - - var renderTexture = new PIXI.RenderTexture(800, 600); - var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - sprite.position.x = 800/2; - sprite.position.y = 600/2; - sprite.anchor.x = 0.5; - sprite.anchor.y = 0.5; - renderTexture.render(sprite); - - Sprite in this case will be rendered to 0,0 position. To render this sprite at center DisplayObjectContainer should be used: - - var doc = new PIXI.DisplayObjectContainer(); - doc.addChild(sprite); - renderTexture.render(doc); // Renders to center of renderTexture - - @class RenderTexture - @extends Texture - @constructor - @param width {Number} The width of the render texture - @param height {Number} The height of the render texture - */ -PIXI.RenderTexture = function(width, height) -{ - PIXI.EventTarget.call( this ); - - this.width = width || 100; - this.height = height || 100; - - this.indetityMatrix = PIXI.mat3.create(); - - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); - - if(PIXI.gl) - { - this.initWebGL(); - } - else - { - this.initCanvas(); - } -} - -PIXI.RenderTexture.prototype = Object.create( PIXI.Texture.prototype ); -PIXI.RenderTexture.prototype.constructor = PIXI.RenderTexture; - -/** - * Initializes the webgl data for this texture - * - * @method initWebGL - * @private - */ -PIXI.RenderTexture.prototype.initWebGL = function() -{ - var gl = PIXI.gl; - this.glFramebuffer = gl.createFramebuffer(); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - - this.glFramebuffer.width = this.width; - this.glFramebuffer.height = this.height; - - this.baseTexture = new PIXI.BaseTexture(); - - this.baseTexture.width = this.width; - this.baseTexture.height = this.height; - - this.baseTexture._glTexture = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - - this.baseTexture.isRender = true; - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.baseTexture._glTexture, 0); - - // create a projection matrix.. - this.projection = new PIXI.Point(this.width/2 , this.height/2); - - // set the correct render function.. - this.render = this.renderWebGL; - - -} - - -PIXI.RenderTexture.prototype.resize = function(width, height) -{ - - this.width = width; - this.height = height; - - if(PIXI.gl) - { - this.projection.x = this.width/2 - this.projection.y = this.height/2; - - var gl = PIXI.gl; - gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - } - else - { - - this.frame.width = this.width - this.frame.height = this.height; - this.renderer.resize(this.width, this.height); - } -} - -/** - * Initializes the canvas data for this texture - * - * @method initCanvas - * @private - */ -PIXI.RenderTexture.prototype.initCanvas = function() -{ - this.renderer = new PIXI.CanvasRenderer(this.width, this.height, null, 0); - - this.baseTexture = new PIXI.BaseTexture(this.renderer.view); - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); - - this.render = this.renderCanvas; -} - -/** - * This function will draw the display object to the texture. - * - * @method renderWebGL - * @param displayObject {DisplayObject} The display object to render this texture on - * @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn - * @private - */ -PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, clear) -{ - var gl = PIXI.gl; - - // enable the alpha color mask.. - gl.colorMask(true, true, true, true); - - gl.viewport(0, 0, this.width, this.height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - - if(clear) - { - gl.clearColor(0,0,0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - } - - // THIS WILL MESS WITH HIT TESTING! - var children = displayObject.children; - - //TODO -? create a new one??? dont think so! - var originalWorldTransform = displayObject.worldTransform; - displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; - // modify to flip... - displayObject.worldTransform[4] = -1; - displayObject.worldTransform[5] = this.projection.y * 2; - - - if(position) - { - displayObject.worldTransform[2] = position.x; - displayObject.worldTransform[5] -= position.y; - } - - PIXI.visibleCount++; - displayObject.vcount = PIXI.visibleCount; - - for(var i=0,j=children.length; i} assetURLs an array of image/sprite sheet urls that you would like loaded - * supported. Supported image formats include "jpeg", "jpg", "png", "gif". Supported - * sprite sheet data formats only include "JSON" at this time. Supported bitmap font - * data formats include "xml" and "fnt". - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.AssetLoader = function(assetURLs, crossorigin) -{ - PIXI.EventTarget.call(this); - - /** - * The array of asset URLs that are going to be loaded - * - * @property assetURLs - * @type Array - */ - this.assetURLs = assetURLs; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * Maps file extension to loader types - * - * @property loadersByType - * @type Object - */ - this.loadersByType = { - "jpg": PIXI.ImageLoader, - "jpeg": PIXI.ImageLoader, - "png": PIXI.ImageLoader, - "gif": PIXI.ImageLoader, - "json": PIXI.JsonLoader, - "anim": PIXI.SpineLoader, - "xml": PIXI.BitmapFontLoader, - "fnt": PIXI.BitmapFontLoader - }; - - -}; - -/** - * Fired when an item has loaded - * @event onProgress - */ - -/** - * Fired when all the assets have loaded - * @event onComplete - */ - -// constructor -PIXI.AssetLoader.prototype.constructor = PIXI.AssetLoader; - -/** - * Starts loading the assets sequentially - * - * @method load - */ -PIXI.AssetLoader.prototype.load = function() -{ - var scope = this; - - this.loadCount = this.assetURLs.length; - - for (var i=0; i < this.assetURLs.length; i++) - { - var fileName = this.assetURLs[i]; - var fileType = fileName.split(".").pop().toLowerCase(); - - var loaderClass = this.loadersByType[fileType]; - if(!loaderClass) - throw new Error(fileType + " is an unsupported file type"); - - var loader = new loaderClass(fileName, this.crossorigin); - - loader.addEventListener("loaded", function() - { - scope.onAssetLoaded(); - }); - loader.load(); - } -}; - -/** - * Invoked after each file is loaded - * - * @method onAssetLoaded - * @private - */ -PIXI.AssetLoader.prototype.onAssetLoaded = function() -{ - this.loadCount--; - this.dispatchEvent({type: "onProgress", content: this}); - if(this.onProgress) this.onProgress(); - - if(this.loadCount == 0) - { - this.dispatchEvent({type: "onComplete", content: this}); - if(this.onComplete) this.onComplete(); - } -}; - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The json file loader is used to load in JSON data and parsing it - * When loaded this class will dispatch a "loaded" event - * If load failed this class will dispatch a "error" event - * - * @class JsonLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the JSON file - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.JsonLoader = function (url, crossorigin) { - PIXI.EventTarget.call(this); - - /** - * The url of the bitmap font data - * - * @property url - * @type String - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * [read-only] The base url of the bitmap font data - * - * @property baseUrl - * @type String - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ""); - - /** - * [read-only] Whether the data has loaded yet - * - * @property loaded - * @type Boolean - * @readOnly - */ - this.loaded = false; - -}; - -// constructor -PIXI.JsonLoader.prototype.constructor = PIXI.JsonLoader; - -/** - * Loads the JSON data - * - * @method load - */ -PIXI.JsonLoader.prototype.load = function () { - this.ajaxRequest = new AjaxRequest(); - var scope = this; - this.ajaxRequest.onreadystatechange = function () { - scope.onJSONLoaded(); - }; - - this.ajaxRequest.open("GET", this.url, true); - if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/json"); - this.ajaxRequest.send(null); -}; - -/** - * Invoke when JSON file is loaded - * - * @method onJSONLoaded - * @private - */ -PIXI.JsonLoader.prototype.onJSONLoaded = function () { - if (this.ajaxRequest.readyState == 4) { - if (this.ajaxRequest.status == 200 || window.location.href.indexOf("http") == -1) { - this.json = JSON.parse(this.ajaxRequest.responseText); - - if(this.json.frames) - { - // sprite sheet - var scope = this; - var textureUrl = this.baseUrl + this.json.meta.image; - var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); - var frameData = this.json.frames; - - this.texture = image.texture.baseTexture; - image.addEventListener("loaded", function (event) { - scope.onLoaded(); - }); - - for (var i in frameData) { - var rect = frameData[i].frame; - if (rect) { - PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) { - //var realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) - // calculate the offset! - } - } - } - - image.load(); - - } - else if(this.json.bones) - { - // spine animation - var spineJsonParser = new spine.SkeletonJson(); - var skeletonData = spineJsonParser.readSkeletonData(this.json); - PIXI.AnimCache[this.url] = skeletonData; - this.onLoaded(); - } - else - { - this.onLoaded(); - } - } - else - { - this.onError(); - } - } -}; - -/** - * Invoke when json file loaded - * - * @method onLoaded - * @private - */ -PIXI.JsonLoader.prototype.onLoaded = function () { - this.loaded = true; - this.dispatchEvent({ - type: "loaded", - content: this - }); -}; - -/** - * Invoke when error occured - * - * @method onError - * @private - */ -PIXI.JsonLoader.prototype.onError = function () { - this.dispatchEvent({ - type: "error", - content: this - }); -}; -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The sprite sheet loader is used to load in JSON sprite sheet data - * To generate the data you can use http://www.codeandweb.com/texturepacker and publish the "JSON" format - * There is a free version so thats nice, although the paid version is great value for money. - * It is highly recommended to use Sprite sheets (also know as texture atlas") as it means sprite"s can be batched and drawn together for highly increased rendering speed. - * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() - * This loader will also load the image file that the Spritesheet points to as well as the data. - * When loaded this class will dispatch a "loaded" event - * - * @class SpriteSheetLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the sprite sheet JSON file - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ - -PIXI.SpriteSheetLoader = function (url, crossorigin) { - /* - * i use texture packer to load the assets.. - * http://www.codeandweb.com/texturepacker - * make sure to set the format as "JSON" - */ - PIXI.EventTarget.call(this); - - /** - * The url of the bitmap font data - * - * @property url - * @type String - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * [read-only] The base url of the bitmap font data - * - * @property baseUrl - * @type String - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ""); - - /** - * The texture being loaded - * - * @property texture - * @type Texture - */ - this.texture = null; - - /** - * The frames of the sprite sheet - * - * @property frames - * @type Object - */ - this.frames = {}; -}; - -// constructor -PIXI.SpriteSheetLoader.prototype.constructor = PIXI.SpriteSheetLoader; - -/** - * This will begin loading the JSON file - * - * @method load - */ -PIXI.SpriteSheetLoader.prototype.load = function () { - var scope = this; - var jsonLoader = new PIXI.JsonLoader(this.url, this.crossorigin); - jsonLoader.addEventListener("loaded", function (event) { - scope.json = event.content.json; - scope.onJSONLoaded(); - }); - jsonLoader.load(); -}; - -/** - * Invoke when JSON file is loaded - * - * @method onJSONLoaded - * @private - */ -PIXI.SpriteSheetLoader.prototype.onJSONLoaded = function () { - var scope = this; - var textureUrl = this.baseUrl + this.json.meta.image; - var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); - var frameData = this.json.frames; - - this.texture = image.texture.baseTexture; - image.addEventListener("loaded", function (event) { - scope.onLoaded(); - }); - - for (var i in frameData) { - var rect = frameData[i].frame; - if (rect) { - PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) { - //var realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) - // calculate the offset! - } - } - } - - image.load(); -}; -/** - * Invoke when all files are loaded (json and texture) - * - * @method onLoaded - * @private - */ -PIXI.SpriteSheetLoader.prototype.onLoaded = function () { - this.dispatchEvent({ - type: "loaded", - content: this - }); -}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The image loader class is responsible for loading images file formats ("jpeg", "jpg", "png" and "gif") - * Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() - * When loaded this class will dispatch a 'loaded' event - * - * @class ImageLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the image - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.ImageLoader = function(url, crossorigin) -{ - PIXI.EventTarget.call(this); - - /** - * The texture being loaded - * - * @property texture - * @type Texture - */ - this.texture = PIXI.Texture.fromImage(url, crossorigin); - - /** - * if the image is loaded with loadFramedSpriteSheet - * frames will contain the sprite sheet frames - * - */ - this.frames = []; -}; - -// constructor -PIXI.ImageLoader.prototype.constructor = PIXI.ImageLoader; - -/** - * Loads image or takes it from cache - * - * @method load - */ -PIXI.ImageLoader.prototype.load = function() -{ - if(!this.texture.baseTexture.hasLoaded) - { - var scope = this; - this.texture.baseTexture.addEventListener("loaded", function() - { - scope.onLoaded(); - }); - } - else - { - this.onLoaded(); - } -}; - -/** - * Invoked when image file is loaded or it is already cached and ready to use - * - * @method onLoaded - * @private - */ -PIXI.ImageLoader.prototype.onLoaded = function() -{ - this.dispatchEvent({type: "loaded", content: this}); -}; - -/** - * Loads image and split it to uniform sized frames - * - * - * @method loadFramedSpriteSheet - * @param frameWidth {Number} with of each frame - * @param frameHeight {Number} height of each frame - * @param textureName {String} if given, the frames will be cached in - format - */ -PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) -{ - this.frames = []; - var cols = Math.floor(this.texture.width / frameWidth); - var rows = Math.floor(this.texture.height / frameHeight); - - var i=0; - for (var y=0; y - + + - + diff --git a/examples/example 4 - Balls/pixi.js b/examples/example 4 - Balls/pixi.js deleted file mode 100644 index 6d567a2..0000000 --- a/examples/example 4 - Balls/pixi.js +++ /dev/null @@ -1,10649 +0,0 @@ -/** - * @license - * Pixi.JS - v1.3.0 - * Copyright (c) 2012, Mat Groves - * http://goodboydigital.com/ - * - * Compiled: 2013-09-30 - * - * Pixi.JS is licensed under the MIT License. - * http://www.opensource.org/licenses/mit-license.php - */ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -(function(){ - - var root = this; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * @module PIXI - */ -var PIXI = PIXI || {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The Point object represents a location in a two-dimensional coordinate system, where x represents the horizontal axis and y represents the vertical axis. - * - * @class Point - * @constructor - * @param x {Number} position of the point - * @param y {Number} position of the point - */ -PIXI.Point = function(x, y) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; -} - -/** - * Creates a clone of this point - * - * @method clone - * @return {Point} a copy of the point - */ -PIXI.Point.prototype.clone = function() -{ - return new PIXI.Point(this.x, this.y); -} - -// constructor -PIXI.Point.prototype.constructor = PIXI.Point; - - -/** - * @author Mat Groves http://matgroves.com/ - */ - -/** - * the Rectangle object is an area defined by its position, as indicated by its top-left corner point (x, y) and by its width and its height. - * - * @class Rectangle - * @constructor - * @param x {Number} The X coord of the upper-left corner of the rectangle - * @param y {Number} The Y coord of the upper-left corner of the rectangle - * @param width {Number} The overall width of this rectangle - * @param height {Number} The overall height of this rectangle - */ -PIXI.Rectangle = function(x, y, width, height) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property width - * @type Number - * @default 0 - */ - this.width = width || 0; - - /** - * @property height - * @type Number - * @default 0 - */ - this.height = height || 0; -} - -/** - * Creates a clone of this Rectangle - * - * @method clone - * @return {Rectangle} a copy of the rectangle - */ -PIXI.Rectangle.prototype.clone = function() -{ - return new PIXI.Rectangle(this.x, this.y, this.width, this.height); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this Rectangle - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this Rectangle - */ -PIXI.Rectangle.prototype.contains = function(x, y) -{ - if(this.width <= 0 || this.height <= 0) - return false; - - var x1 = this.x; - if(x >= x1 && x <= x1 + this.width) - { - var y1 = this.y; - - if(y >= y1 && y <= y1 + this.height) - { - return true; - } - } - - return false; -} - -// constructor -PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; - - -/** - * @author Adrien Brault - */ - -/** - * @class Polygon - * @constructor - * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, - * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be - * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the - * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are - * Numbers. - */ -PIXI.Polygon = function(points) -{ - //if points isn't an array, use arguments as the array - if(!(points instanceof Array)) - points = Array.prototype.slice.call(arguments); - - //if this is a flat array of numbers, convert it to points - if(typeof points[0] === 'number') { - var p = []; - for(var i = 0, il = points.length; i < il; i+=2) { - p.push( - new PIXI.Point(points[i], points[i + 1]) - ); - } - - points = p; - } - - this.points = points; -} - -/** - * Creates a clone of this polygon - * - * @method clone - * @return {Polygon} a copy of the polygon - */ -PIXI.Polygon.prototype.clone = function() -{ - var points = []; - for (var i=0; i y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); - - if(intersect) inside = !inside; - } - - return inside; -} - -// constructor -PIXI.Polygon.prototype.constructor = PIXI.Polygon; - -/** - * @author Chad Engler - */ - -/** - * The Circle object can be used to specify a hit area for displayobjects - * - * @class Circle - * @constructor - * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle - * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle - * @param radius {Number} The radius of the circle - */ -PIXI.Circle = function(x, y, radius) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property radius - * @type Number - * @default 0 - */ - this.radius = radius || 0; -} - -/** - * Creates a clone of this Circle instance - * - * @method clone - * @return {Circle} a copy of the polygon - */ -PIXI.Circle.prototype.clone = function() -{ - return new PIXI.Circle(this.x, this.y, this.radius); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this circle - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this polygon - */ -PIXI.Circle.prototype.contains = function(x, y) -{ - if(this.radius <= 0) - return false; - - var dx = (this.x - x), - dy = (this.y - y), - r2 = this.radius * this.radius; - - dx *= dx; - dy *= dy; - - return (dx + dy <= r2); -} - -// constructor -PIXI.Circle.prototype.constructor = PIXI.Circle; - - -/** - * @author Chad Engler - */ - -/** - * The Ellipse object can be used to specify a hit area for displayobjects - * - * @class Ellipse - * @constructor - * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse - * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse - * @param width {Number} The overall width of this ellipse - * @param height {Number} The overall height of this ellipse - */ -PIXI.Ellipse = function(x, y, width, height) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property width - * @type Number - * @default 0 - */ - this.width = width || 0; - - /** - * @property height - * @type Number - * @default 0 - */ - this.height = height || 0; -} - -/** - * Creates a clone of this Ellipse instance - * - * @method clone - * @return {Ellipse} a copy of the ellipse - */ -PIXI.Ellipse.prototype.clone = function() -{ - return new PIXI.Ellipse(this.x, this.y, this.width, this.height); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this ellipse - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this ellipse - */ -PIXI.Ellipse.prototype.contains = function(x, y) -{ - if(this.width <= 0 || this.height <= 0) - return false; - - //normalize the coords to an ellipse with center 0,0 - //and a radius of 0.5 - var normx = ((x - this.x) / this.width) - 0.5, - normy = ((y - this.y) / this.height) - 0.5; - - normx *= normx; - normy *= normy; - - return (normx + normy < 0.25); -} - -PIXI.Ellipse.getBounds = function() -{ - return new PIXI.Rectangle(this.x, this.y, this.width, this.height); -} - -// constructor -PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; - - - -/* - * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV - * you both rock! - */ - -function determineMatrixArrayType() { - PIXI.Matrix = (typeof Float32Array !== 'undefined') ? Float32Array : Array; - return PIXI.Matrix; -} - -determineMatrixArrayType(); - -PIXI.mat3 = {}; - -PIXI.mat3.create = function() -{ - var matrix = new PIXI.Matrix(9); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 1; - matrix[5] = 0; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 1; - - return matrix; -} - - -PIXI.mat3.identity = function(matrix) -{ - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 1; - matrix[5] = 0; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 1; - - return matrix; -} - - -PIXI.mat4 = {}; - -PIXI.mat4.create = function() -{ - var matrix = new PIXI.Matrix(16); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 0; - matrix[5] = 1; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = 1; - matrix[11] = 0; - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; - - return matrix; -} - -PIXI.mat3.multiply = function (mat, mat2, dest) -{ - if (!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[0], a01 = mat[1], a02 = mat[2], - a10 = mat[3], a11 = mat[4], a12 = mat[5], - a20 = mat[6], a21 = mat[7], a22 = mat[8], - - b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], - b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], - b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; - - dest[0] = b00 * a00 + b01 * a10 + b02 * a20; - dest[1] = b00 * a01 + b01 * a11 + b02 * a21; - dest[2] = b00 * a02 + b01 * a12 + b02 * a22; - - dest[3] = b10 * a00 + b11 * a10 + b12 * a20; - dest[4] = b10 * a01 + b11 * a11 + b12 * a21; - dest[5] = b10 * a02 + b11 * a12 + b12 * a22; - - dest[6] = b20 * a00 + b21 * a10 + b22 * a20; - dest[7] = b20 * a01 + b21 * a11 + b22 * a21; - dest[8] = b20 * a02 + b21 * a12 + b22 * a22; - - return dest; -} - -PIXI.mat3.clone = function(mat) -{ - var matrix = new PIXI.Matrix(9); - - matrix[0] = mat[0]; - matrix[1] = mat[1]; - matrix[2] = mat[2]; - matrix[3] = mat[3]; - matrix[4] = mat[4]; - matrix[5] = mat[5]; - matrix[6] = mat[6]; - matrix[7] = mat[7]; - matrix[8] = mat[8]; - - return matrix; -} - -PIXI.mat3.transpose = function (mat, dest) -{ - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) { - var a01 = mat[1], a02 = mat[2], - a12 = mat[5]; - - mat[1] = mat[3]; - mat[2] = mat[6]; - mat[3] = a01; - mat[5] = mat[7]; - mat[6] = a02; - mat[7] = a12; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[3]; - dest[2] = mat[6]; - dest[3] = mat[1]; - dest[4] = mat[4]; - dest[5] = mat[7]; - dest[6] = mat[2]; - dest[7] = mat[5]; - dest[8] = mat[8]; - return dest; -} - -PIXI.mat3.toMat4 = function (mat, dest) -{ - if (!dest) { dest = PIXI.mat4.create(); } - - dest[15] = 1; - dest[14] = 0; - dest[13] = 0; - dest[12] = 0; - - dest[11] = 0; - dest[10] = mat[8]; - dest[9] = mat[7]; - dest[8] = mat[6]; - - dest[7] = 0; - dest[6] = mat[5]; - dest[5] = mat[4]; - dest[4] = mat[3]; - - dest[3] = 0; - dest[2] = mat[2]; - dest[1] = mat[1]; - dest[0] = mat[0]; - - return dest; -} - - -///// - - -PIXI.mat4.create = function() -{ - var matrix = new PIXI.Matrix(16); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 0; - matrix[5] = 1; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = 1; - matrix[11] = 0; - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; - - return matrix; -} - -PIXI.mat4.transpose = function (mat, dest) -{ - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) - { - var a01 = mat[1], a02 = mat[2], a03 = mat[3], - a12 = mat[6], a13 = mat[7], - a23 = mat[11]; - - mat[1] = mat[4]; - mat[2] = mat[8]; - mat[3] = mat[12]; - mat[4] = a01; - mat[6] = mat[9]; - mat[7] = mat[13]; - mat[8] = a02; - mat[9] = a12; - mat[11] = mat[14]; - mat[12] = a03; - mat[13] = a13; - mat[14] = a23; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[4]; - dest[2] = mat[8]; - dest[3] = mat[12]; - dest[4] = mat[1]; - dest[5] = mat[5]; - dest[6] = mat[9]; - dest[7] = mat[13]; - dest[8] = mat[2]; - dest[9] = mat[6]; - dest[10] = mat[10]; - dest[11] = mat[14]; - dest[12] = mat[3]; - dest[13] = mat[7]; - dest[14] = mat[11]; - dest[15] = mat[15]; - return dest; -} - -PIXI.mat4.multiply = function (mat, mat2, dest) -{ - if (!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; - var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; - var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; - var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - - // Cache only the current line of the second matrix - var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; - dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[4]; - b1 = mat2[5]; - b2 = mat2[6]; - b3 = mat2[7]; - dest[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[8]; - b1 = mat2[9]; - b2 = mat2[10]; - b3 = mat2[11]; - dest[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[12]; - b1 = mat2[13]; - b2 = mat2[14]; - b3 = mat2[15]; - dest[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - return dest; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The base class for all objects that are rendered on the screen. - * - * @class DisplayObject - * @constructor - */ -PIXI.DisplayObject = function() -{ - this.last = this; - this.first = this; - /** - * The coordinate of the object relative to the local coordinates of the parent. - * - * @property position - * @type Point - */ - this.position = new PIXI.Point(); - - /** - * The scale factor of the object. - * - * @property scale - * @type Point - */ - this.scale = new PIXI.Point(1,1);//{x:1, y:1}; - - /** - * The pivot point of the displayObject that it rotates around - * - * @property pivot - * @type Point - */ - this.pivot = new PIXI.Point(0,0); - - /** - * The rotation of the object in radians. - * - * @property rotation - * @type Number - */ - this.rotation = 0; - - /** - * The opacity of the object. - * - * @property alpha - * @type Number - */ - this.alpha = 1; - - /** - * The visibility of the object. - * - * @property visible - * @type Boolean - */ - this.visible = true; - - /** - * This is the defined area that will pick up mouse / touch events. It is null by default. - * Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children) - * - * @property hitArea - * @type Rectangle|Circle|Ellipse|Polygon - */ - this.hitArea = null; - - /** - * This is used to indicate if the displayObject should display a mouse hand cursor on rollover - * - * @property buttonMode - * @type Boolean - */ - this.buttonMode = false; - - /** - * Can this object be rendered - * - * @property renderable - * @type Boolean - */ - this.renderable = false; - - /** - * [read-only] The display object container that contains this display object. - * - * @property parent - * @type DisplayObjectContainer - * @readOnly - */ - this.parent = null; - - /** - * [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage. - * - * @property stage - * @type Stage - * @readOnly - */ - this.stage = null; - - /** - * [read-only] The multiplied alpha of the displayobject - * - * @property worldAlpha - * @type Number - * @readOnly - */ - this.worldAlpha = 1; - - /** - * [read-only] Whether or not the object is interactive, do not toggle directly! use the `interactive` property - * - * @property _interactive - * @type Boolean - * @readOnly - * @private - */ - this._interactive = false; - - /** - * [read-only] Current transform of the object based on world (parent) factors - * - * @property worldTransform - * @type Mat3 - * @readOnly - * @private - */ - this.worldTransform = PIXI.mat3.create()//mat3.identity(); - - /** - * [read-only] Current transform of the object locally - * - * @property localTransform - * @type Mat3 - * @readOnly - * @private - */ - this.localTransform = PIXI.mat3.create()//mat3.identity(); - - /** - * [NYI] Unkown - * - * @property color - * @type Array<> - * @private - */ - this.color = []; - - /** - * [NYI] Holds whether or not this object is dynamic, for rendering optimization - * - * @property dynamic - * @type Boolean - * @private - */ - this.dynamic = true; - - // chach that puppy! - this._sr = 0; - this._cr = 1; - - /* - * MOUSE Callbacks - */ - - /** - * A callback that is used when the users clicks on the displayObject with their mouse - * @method click - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user clicks the mouse down over the sprite - * @method mousedown - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject - * for this callback to be fired the mouse must have been pressed down over the displayObject - * @method mouseup - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject - * for this callback to be fired, The touch must have started over the displayObject - * @method mouseupoutside - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the users mouse rolls over the displayObject - * @method mouseover - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the users mouse leaves the displayObject - * @method mouseout - * @param interactionData {InteractionData} - */ - - - /* - * TOUCH Callbacks - */ - - /** - * A callback that is used when the users taps on the sprite with their finger - * basically a touch version of click - * @method tap - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user touch's over the displayObject - * @method touchstart - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases a touch over the displayObject - * @method touchend - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the touch that was over the displayObject - * for this callback to be fired, The touch must have started over the sprite - * @method touchendoutside - * @param interactionData {InteractionData} - */ -} - -// constructor -PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; - -/** - * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default - * Instead of using this function you can now simply set the interactive property to true or false - * - * @method setInteractive - * @param interactive {Boolean} - * @deprecated Simply set the `interactive` property directly - */ -PIXI.DisplayObject.prototype.setInteractive = function(interactive) -{ - this.interactive = interactive; -} - -/** - * Indicates if the sprite will have touch and mouse interactivity. It is false by default - * - * @property interactive - * @type Boolean - * @default false - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'interactive', { - get: function() { - return this._interactive; - }, - set: function(value) { - this._interactive = value; - - // TODO more to be done here.. - // need to sort out a re-crawl! - if(this.stage)this.stage.dirty = true; - } -}); - -/** - * Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. - * In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. - * To remove a mask, set this property to null. - * - * @property mask - * @type Graphics - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { - get: function() { - return this._mask; - }, - set: function(value) { - - - if(value) - { - if(this._mask) - { - value.start = this._mask.start; - value.end = this._mask.end; - } - else - { - this.addFilter(value); - value.renderable = false; - } - } - else - { - this.removeFilter(this._mask); - this._mask.renderable = true; - } - - this._mask = value; - } -}); - -/** - * Sets the filters for the displayObject. Currently there's a few limitations. - * 1: At the moment only one filter can be applied at a time.. - * 2: They cannot be nested. - * 3: There's no padding yet. - * 4: this is a webGL only feature. - * @property filters - * @type Array - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { - get: function() { - return this._filters; - }, - set: function(value) { - - //if(value == ) - if(value) - { - if(this._filters)this.removeFilter(this._filters); - this.addFilter(value) - } - else - { - if(this._filters)this.removeFilter(this._filters); - } - - this._filters = value; - } -}); - -/* - * Adds a filter to this displayObject - * - * @method addFilter - * @param mask {Graphics} the graphics object to use as a filter - * @private - */ -PIXI.DisplayObject.prototype.addFilter = function(data) -{ - //if(this.filter)return; - //this.filter = true; - - // insert a filter block.. - // TODO Onject pool thease bad boys.. - var start = new PIXI.FilterBlock(); - var end = new PIXI.FilterBlock(); - - data.start = start; - data.end = end; - - start.data = data; - end.data = data; - - start.first = start.last = this; - end.first = end.last = this; - - start.open = true; - - /* - * insert start - */ - - var childFirst = start - var childLast = start - var nextObject; - var previousObject; - - previousObject = this.first._iPrev; - - if(previousObject) - { - nextObject = previousObject._iNext; - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - } - else - { - nextObject = this; - } - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - - // now insert the end filter block.. - - /* - * insert end filter - */ - var childFirst = end - var childLast = end - var nextObject = null; - var previousObject = null; - - previousObject = this.last; - nextObject = previousObject._iNext; - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - var updateLast = this; - - var prevLast = this.last; - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = end; - } - updateLast = updateLast.parent; - } - - this.first = start; - - // if webGL... - if(this.__renderGroup) - { - this.__renderGroup.addFilterBlocks(start, end); - } - -} - -/* - * Removes the filter to this displayObject - * - * @method removeFilter - * @private - */ -PIXI.DisplayObject.prototype.removeFilter = function(data) -{ - //if(!this.filter)return; - //this.filter = false; - console.log("YUOIO") - // modify the list.. - var startBlock = data.start; - - - var nextObject = startBlock._iNext; - var previousObject = startBlock._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - if(previousObject)previousObject._iNext = nextObject; - - this.first = startBlock._iNext; - - // remove the end filter - var lastBlock = data.end; - - var nextObject = lastBlock._iNext; - var previousObject = lastBlock._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - - // this is always true too! - var tempLast = lastBlock._iPrev; - // need to make sure the parents last is updated too - var updateLast = this; - while(updateLast.last == lastBlock) - { - updateLast.last = tempLast; - updateLast = updateLast.parent; - if(!updateLast)break; - } - - // if webGL... - if(this.__renderGroup) - { - this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); - } -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.DisplayObject.prototype.updateTransform = function() -{ - // TODO OPTIMIZE THIS!! with dirty - if(this.rotation !== this.rotationCache) - { - this.rotationCache = this.rotation; - this._sr = Math.sin(this.rotation); - this._cr = Math.cos(this.rotation); - } - - var localTransform = this.localTransform; - var parentTransform = this.parent.worldTransform; - var worldTransform = this.worldTransform; - //console.log(localTransform) - localTransform[0] = this._cr * this.scale.x; - localTransform[1] = -this._sr * this.scale.y - localTransform[3] = this._sr * this.scale.x; - localTransform[4] = this._cr * this.scale.y; - - // TODO --> do we even need a local matrix??? - - var px = this.pivot.x; - var py = this.pivot.y; - - // Cache the matrix values (makes for huge speed increases!) - var a00 = localTransform[0], a01 = localTransform[1], a02 = this.position.x - localTransform[0] * px - py * localTransform[1], - a10 = localTransform[3], a11 = localTransform[4], a12 = this.position.y - localTransform[4] * py - px * localTransform[3], - - b00 = parentTransform[0], b01 = parentTransform[1], b02 = parentTransform[2], - b10 = parentTransform[3], b11 = parentTransform[4], b12 = parentTransform[5]; - - localTransform[2] = a02 - localTransform[5] = a12 - - worldTransform[0] = b00 * a00 + b01 * a10; - worldTransform[1] = b00 * a01 + b01 * a11; - worldTransform[2] = b00 * a02 + b01 * a12 + b02; - - worldTransform[3] = b10 * a00 + b11 * a10; - worldTransform[4] = b10 * a01 + b11 * a11; - worldTransform[5] = b10 * a02 + b11 * a12 + b12; - - // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! - // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); - this.worldAlpha = this.alpha * this.parent.worldAlpha; - - this.vcount = PIXI.visibleCount; - -} - -PIXI.visibleCount = 0; -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * A DisplayObjectContainer represents a collection of display objects. - * It is the base class of all display objects that act as a container for other objects. - * - * @class DisplayObjectContainer - * @extends DisplayObject - * @constructor - */ -PIXI.DisplayObjectContainer = function() -{ - PIXI.DisplayObject.call( this ); - - /** - * [read-only] The of children of this container. - * - * @property children - * @type Array - * @readOnly - */ - this.children = []; -} - -// constructor -PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); -PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; - -/** - * Adds a child to the container. - * - * @method addChild - * @param child {DisplayObject} The DisplayObject to add to the container - */ -PIXI.DisplayObjectContainer.prototype.addChild = function(child) -{ - if(child.parent != undefined) - { - - //// COULD BE THIS??? - child.parent.removeChild(child); - // return; - } - - child.parent = this; - - this.children.push(child); - - // update the stage refference.. - - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = this.stage; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // LINKED LIST // - - // modify the list.. - var childFirst = child.first - var childLast = child.last; - var nextObject; - var previousObject; - - // this could be wrong if there is a filter?? - if(this._filters) - { - previousObject = this.last._iPrev; - } - else - { - previousObject = this.last; - } - - nextObject = previousObject._iNext; - - // always true in this case - // need to make sure the parents last is updated too - var updateLast = this; - var prevLast = previousObject; - - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = child.last; - } - updateLast = updateLast.parent; - } - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - // need to remove any render groups.. - if(this.__renderGroup) - { - // being used by a renderTexture.. if it exists then it must be from a render texture; - if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); - // add them to the new render group.. - this.__renderGroup.addDisplayObjectAndChildren(child); - } - -} - -/** - * Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown - * - * @method addChildAt - * @param child {DisplayObject} The child to add - * @param index {Number} The index to place the child in - */ -PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) -{ - if(index >= 0 && index <= this.children.length) - { - if(child.parent != undefined) - { - child.parent.removeChild(child); - } - child.parent = this; - - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = this.stage; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // modify the list.. - var childFirst = child.first; - var childLast = child.last; - var nextObject; - var previousObject; - - if(index == this.children.length) - { - previousObject = this.last; - var updateLast = this; - var prevLast = this.last; - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = child.last; - } - updateLast = updateLast.parent; - } - } - else if(index == 0) - { - previousObject = this; - } - else - { - previousObject = this.children[index-1].last; - } - - nextObject = previousObject._iNext; - - // always true in this case - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - this.children.splice(index, 0, child); - // need to remove any render groups.. - if(this.__renderGroup) - { - // being used by a renderTexture.. if it exists then it must be from a render texture; - if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); - // add them to the new render group.. - this.__renderGroup.addDisplayObjectAndChildren(child); - } - - } - else - { - throw new Error(child + " The index "+ index +" supplied is out of bounds " + this.children.length); - } -} - -/** - * [NYI] Swaps the depth of 2 displayObjects - * - * @method swapChildren - * @param child {DisplayObject} - * @param child2 {DisplayObject} - * @private - */ -PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2) -{ - /* - * this funtion needs to be recoded.. - * can be done a lot faster.. - */ - return; - - // need to fix this function :/ - /* - // TODO I already know this?? - var index = this.children.indexOf( child ); - var index2 = this.children.indexOf( child2 ); - - if ( index !== -1 && index2 !== -1 ) - { - // cool - - /* - if(this.stage) - { - // this is to satisfy the webGL batching.. - // TODO sure there is a nicer way to achieve this! - this.stage.__removeChild(child); - this.stage.__removeChild(child2); - - this.stage.__addChild(child); - this.stage.__addChild(child2); - } - - // swap the positions.. - this.children[index] = child2; - this.children[index2] = child; - - } - else - { - throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); - }*/ -} - -/** - * Returns the Child at the specified index - * - * @method getChildAt - * @param index {Number} The index to get the child from - */ -PIXI.DisplayObjectContainer.prototype.getChildAt = function(index) -{ - if(index >= 0 && index < this.children.length) - { - return this.children[index]; - } - else - { - throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); - } -} - -/** - * Removes a child from the container. - * - * @method removeChild - * @param child {DisplayObject} The DisplayObject to remove - */ -PIXI.DisplayObjectContainer.prototype.removeChild = function(child) -{ - var index = this.children.indexOf( child ); - if ( index !== -1 ) - { - // unlink // - // modify the list.. - var childFirst = child.first; - var childLast = child.last; - - var nextObject = childLast._iNext; - var previousObject = childFirst._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - - if(this.last == childLast) - { - var tempLast = childFirst._iPrev; - // need to make sure the parents last is updated too - var updateLast = this; - while(updateLast.last == childLast.last) - { - updateLast.last = tempLast; - updateLast = updateLast.parent; - if(!updateLast)break; - } - } - - childLast._iNext = null; - childFirst._iPrev = null; - - // update the stage reference.. - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = null; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // webGL trim - if(child.__renderGroup) - { - child.__renderGroup.removeDisplayObjectAndChildren(child); - } - - child.parent = undefined; - this.children.splice( index, 1 ); - } - else - { - throw new Error(child + " The supplied DisplayObject must be a child of the caller " + this); - } -} - -/* - * Updates the container's children's transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.DisplayObjectContainer.prototype.updateTransform = function() -{ - if(!this.visible)return; - - PIXI.DisplayObject.prototype.updateTransform.call( this ); - - for(var i=0,j=this.children.length; i} an array of {Texture} objects that make up the animation - */ -PIXI.MovieClip = function(textures) -{ - PIXI.Sprite.call(this, textures[0]); - - /** - * The array of textures that make up the animation - * - * @property textures - * @type Array - */ - this.textures = textures; - - /** - * The speed that the MovieClip will play at. Higher is faster, lower is slower - * - * @property animationSpeed - * @type Number - * @default 1 - */ - this.animationSpeed = 1; - - /** - * Whether or not the movie clip repeats after playing. - * - * @property loop - * @type Boolean - * @default true - */ - this.loop = true; - - /** - * Function to call when a MovieClip finishes playing - * - * @property onComplete - * @type Function - */ - this.onComplete = null; - - /** - * [read-only] The index MovieClips current frame (this may not have to be a whole number) - * - * @property currentFrame - * @type Number - * @default 0 - * @readOnly - */ - this.currentFrame = 0; - - /** - * [read-only] Indicates if the MovieClip is currently playing - * - * @property playing - * @type Boolean - * @readOnly - */ - this.playing = false; -} - -// constructor -PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); -PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; - -/** -* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures -* assigned to the MovieClip. -* -* @property totalFrames -* @type Number -* @default 0 -* @readOnly -*/ -Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { - get: function() { - - return this.textures.length; - } -}); - - -/** - * Stops the MovieClip - * - * @method stop - */ -PIXI.MovieClip.prototype.stop = function() -{ - this.playing = false; -} - -/** - * Plays the MovieClip - * - * @method play - */ -PIXI.MovieClip.prototype.play = function() -{ - this.playing = true; -} - -/** - * Stops the MovieClip and goes to a specific frame - * - * @method gotoAndStop - * @param frameNumber {Number} frame index to stop at - */ -PIXI.MovieClip.prototype.gotoAndStop = function(frameNumber) -{ - this.playing = false; - this.currentFrame = frameNumber; - var round = (this.currentFrame + 0.5) | 0; - this.setTexture(this.textures[round % this.textures.length]); -} - -/** - * Goes to a specific frame and begins playing the MovieClip - * - * @method gotoAndPlay - * @param frameNumber {Number} frame index to start at - */ -PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) -{ - this.currentFrame = frameNumber; - this.playing = true; -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.MovieClip.prototype.updateTransform = function() -{ - PIXI.Sprite.prototype.updateTransform.call(this); - - if(!this.playing)return; - - this.currentFrame += this.animationSpeed; - - var round = (this.currentFrame + 0.5) | 0; - - if(this.loop || round < this.textures.length) - { - this.setTexture(this.textures[round % this.textures.length]); - } - else if(round >= this.textures.length) - { - this.gotoAndStop(this.textures.length - 1); - if(this.onComplete) - { - this.onComplete(); - } - } -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - - -PIXI.FilterBlock = function() -{ - this.visible = true; - this.renderable = true; -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.ColorMatrixFilter = function() -{ - // set the uniforms - this.uniforms = { - matrix: {type: 'mat4', value: [1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1]}, - }; - - this.fragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform float invert;", - "uniform mat4 matrix;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", - "gl_FragColor = gl_FragColor * vColor;", - "}" - ]; - -} - - -Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { - get: function() { - return this.uniforms.matrix.value; - }, - set: function(value) { - this.uniforms.matrix.value = value; - } -}); -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Text Object will create a line(s) of text to split a line you can use "\n" - * - * @class Text - * @extends Sprite - * @constructor - * @param text {String} The copy that you would like the text to display - * @param [style] {Object} The style parameters - * @param [style.font] {String} default "bold 20pt Arial" The style and size of the font - * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - * @param [style.stroke] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" - * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) - * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used - * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap - */ -PIXI.Text = function(text, style) -{ - this.canvas = document.createElement("canvas"); - this.context = this.canvas.getContext("2d"); - PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas)); - - this.setText(text); - this.setStyle(style); - - this.updateText(); - this.dirty = false; -}; - -// constructor -PIXI.Text.prototype = Object.create(PIXI.Sprite.prototype); -PIXI.Text.prototype.constructor = PIXI.Text; - -/** - * Set the style of the text - * - * @method setStyle - * @param [style] {Object} The style parameters - * @param [style.font="bold 20pt Arial"] {String} The style and size of the font - * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - * @param [style.stroke="black"] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" - * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) - * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used - * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap - */ -PIXI.Text.prototype.setStyle = function(style) -{ - style = style || {}; - style.font = style.font || "bold 20pt Arial"; - style.fill = style.fill || "black"; - style.align = style.align || "left"; - style.stroke = style.stroke || "black"; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136 - style.strokeThickness = style.strokeThickness || 0; - style.wordWrap = style.wordWrap || false; - style.wordWrapWidth = style.wordWrapWidth || 100; - this.style = style; - this.dirty = true; -}; - -/** - * Set the copy for the text object. To split a line you can use "\n" - * - * @methos setText - * @param {String} text The copy that you would like the text to display - */ -PIXI.Text.prototype.setText = function(text) -{ - this.text = text.toString() || " "; - this.dirty = true; -}; - -/** - * Renders text - * - * @method updateText - * @private - */ -PIXI.Text.prototype.updateText = function() -{ - this.context.font = this.style.font; - - var outputText = this.text; - - // word wrap - // preserve original text - if(this.style.wordWrap)outputText = this.wordWrap(this.text); - - //split text into lines - var lines = outputText.split(/(?:\r\n|\r|\n)/); - - //calculate text width - var lineWidths = []; - var maxLineWidth = 0; - for (var i = 0; i < lines.length; i++) - { - var lineWidth = this.context.measureText(lines[i]).width; - lineWidths[i] = lineWidth; - maxLineWidth = Math.max(maxLineWidth, lineWidth); - } - this.canvas.width = maxLineWidth + this.style.strokeThickness; - - //calculate text height - var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; - this.canvas.height = lineHeight * lines.length; - - //set canvas text styles - this.context.fillStyle = this.style.fill; - this.context.font = this.style.font; - - this.context.strokeStyle = this.style.stroke; - this.context.lineWidth = this.style.strokeThickness; - - this.context.textBaseline = "top"; - - //draw lines line by line - for (i = 0; i < lines.length; i++) - { - var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); - - if(this.style.align == "right") - { - linePosition.x += maxLineWidth - lineWidths[i]; - } - else if(this.style.align == "center") - { - linePosition.x += (maxLineWidth - lineWidths[i]) / 2; - } - - if(this.style.stroke && this.style.strokeThickness) - { - this.context.strokeText(lines[i], linePosition.x, linePosition.y); - } - - if(this.style.fill) - { - this.context.fillText(lines[i], linePosition.x, linePosition.y); - } - } - - this.updateTexture(); -}; - -/** - * Updates texture size based on canvas size - * - * @method updateTexture - * @private - */ -PIXI.Text.prototype.updateTexture = function() -{ - this.texture.baseTexture.width = this.canvas.width; - this.texture.baseTexture.height = this.canvas.height; - this.texture.frame.width = this.canvas.width; - this.texture.frame.height = this.canvas.height; - - this._width = this.canvas.width; - this._height = this.canvas.height; - - PIXI.texturesToUpdate.push(this.texture.baseTexture); -}; - -/** - * Updates the transfor of this object - * - * @method updateTransform - * @private - */ -PIXI.Text.prototype.updateTransform = function() -{ - if(this.dirty) - { - this.updateText(); - this.dirty = false; - } - - PIXI.Sprite.prototype.updateTransform.call(this); -}; - -/* - * http://stackoverflow.com/users/34441/ellisbben - * great solution to the problem! - * - * @method determineFontHeight - * @param fontStyle {Object} - * @private - */ -PIXI.Text.prototype.determineFontHeight = function(fontStyle) -{ - // build a little reference dictionary so if the font style has been used return a - // cached version... - var result = PIXI.Text.heightCache[fontStyle]; - - if(!result) - { - var body = document.getElementsByTagName("body")[0]; - var dummy = document.createElement("div"); - var dummyText = document.createTextNode("M"); - dummy.appendChild(dummyText); - dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); - body.appendChild(dummy); - - result = dummy.offsetHeight; - PIXI.Text.heightCache[fontStyle] = result; - - body.removeChild(dummy); - } - - return result; -}; - -/** - * A Text Object will apply wordwrap - * - * @method wordWrap - * @param text {String} - * @private - */ -PIXI.Text.prototype.wordWrap = function(text) -{ - // search good wrap position - var searchWrapPos = function(ctx, text, start, end, wrapWidth) - { - var p = Math.floor((end-start) / 2) + start; - if(p == start) { - return 1; - } - - if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) - { - if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) - { - return p; - } - else - { - return arguments.callee(ctx, text, p, end, wrapWidth); - } - } - else - { - return arguments.callee(ctx, text, start, p, wrapWidth); - } - }; - - var lineWrap = function(ctx, text, wrapWidth) - { - if(ctx.measureText(text).width <= wrapWidth || text.length < 1) - { - return text; - } - var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); - return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); - }; - - var result = ""; - var lines = text.split("\n"); - for (var i = 0; i < lines.length; i++) - { - result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; - } - - return result; -}; - -/** - * Destroys this text object - * - * @method destroy - * @param destroyTexture {Boolean} - */ -PIXI.Text.prototype.destroy = function(destroyTexture) -{ - if(destroyTexture) - { - this.texture.destroy(); - } - -}; - -PIXI.Text.heightCache = {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" - * You can generate the fnt files using - * http://www.angelcode.com/products/bmfont/ for windows or - * http://www.bmglyph.com/ for mac. - * - * @class BitmapText - * @extends DisplayObjectContainer - * @constructor - * @param text {String} The copy that you would like the text to display - * @param style {Object} The style parameters - * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - */ -PIXI.BitmapText = function(text, style) -{ - PIXI.DisplayObjectContainer.call(this); - - this.setText(text); - this.setStyle(style); - this.updateText(); - this.dirty = false - -}; - -// constructor -PIXI.BitmapText.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); -PIXI.BitmapText.prototype.constructor = PIXI.BitmapText; - -/** - * Set the copy for the text object - * - * @method setText - * @param text {String} The copy that you would like the text to display - */ -PIXI.BitmapText.prototype.setText = function(text) -{ - this.text = text || " "; - this.dirty = true; -}; - -/** - * Set the style of the text - * - * @method setStyle - * @param style {Object} The style parameters - * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - */ -PIXI.BitmapText.prototype.setStyle = function(style) -{ - style = style || {}; - style.align = style.align || "left"; - this.style = style; - - var font = style.font.split(" "); - this.fontName = font[font.length - 1]; - this.fontSize = font.length >= 2 ? parseInt(font[font.length - 2], 10) : PIXI.BitmapText.fonts[this.fontName].size; - - this.dirty = true; -}; - -/** - * Renders text - * - * @method updateText - * @private - */ -PIXI.BitmapText.prototype.updateText = function() -{ - var data = PIXI.BitmapText.fonts[this.fontName]; - var pos = new PIXI.Point(); - var prevCharCode = null; - var chars = []; - var maxLineWidth = 0; - var lineWidths = []; - var line = 0; - var scale = this.fontSize / data.size; - for(var i = 0; i < this.text.length; i++) - { - var charCode = this.text.charCodeAt(i); - if(/(?:\r\n|\r|\n)/.test(this.text.charAt(i))) - { - lineWidths.push(pos.x); - maxLineWidth = Math.max(maxLineWidth, pos.x); - line++; - - pos.x = 0; - pos.y += data.lineHeight; - prevCharCode = null; - continue; - } - - var charData = data.chars[charCode]; - if(!charData) continue; - - if(prevCharCode && charData[prevCharCode]) - { - pos.x += charData.kerning[prevCharCode]; - } - chars.push({texture:charData.texture, line: line, charCode: charCode, position: new PIXI.Point(pos.x + charData.xOffset, pos.y + charData.yOffset)}); - pos.x += charData.xAdvance; - - prevCharCode = charCode; - } - - lineWidths.push(pos.x); - maxLineWidth = Math.max(maxLineWidth, pos.x); - - var lineAlignOffsets = []; - for(i = 0; i <= line; i++) - { - var alignOffset = 0; - if(this.style.align == "right") - { - alignOffset = maxLineWidth - lineWidths[i]; - } - else if(this.style.align == "center") - { - alignOffset = (maxLineWidth - lineWidths[i]) / 2; - } - lineAlignOffsets.push(alignOffset); - } - - for(i = 0; i < chars.length; i++) - { - var c = new PIXI.Sprite(chars[i].texture)//PIXI.Sprite.fromFrame(chars[i].charCode); - c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale; - c.position.y = chars[i].position.y * scale; - c.scale.x = c.scale.y = scale; - this.addChild(c); - } - - this.width = pos.x * scale; - this.height = (pos.y + data.lineHeight) * scale; -}; - -/** - * Updates the transfor of this object - * - * @method updateTransform - * @private - */ -PIXI.BitmapText.prototype.updateTransform = function() -{ - if(this.dirty) - { - while(this.children.length > 0) - { - this.removeChild(this.getChildAt(0)); - } - this.updateText(); - - this.dirty = false; - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -}; - -PIXI.BitmapText.fonts = {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - /** - * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive - * This manager also supports multitouch. - * - * @class InteractionManager - * @constructor - * @param stage {Stage} The stage to handle interactions - */ -PIXI.InteractionManager = function(stage) -{ - /** - * a refference to the stage - * - * @property stage - * @type Stage - */ - this.stage = stage; - - /** - * the mouse data - * - * @property mouse - * @type InteractionData - */ - this.mouse = new PIXI.InteractionData(); - - /** - * an object that stores current touches (InteractionData) by id reference - * - * @property touchs - * @type Object - */ - this.touchs = {}; - - - - // helpers - this.tempPoint = new PIXI.Point(); - //this.tempMatrix = mat3.create(); - - this.mouseoverEnabled = true; - - //tiny little interactiveData pool! - this.pool = []; - - this.interactiveItems = []; - this.interactionDOMElement = null; - - //this will make it so that you dont have to call bind all the time - this.onMouseMove = this.onMouseMove.bind( this ); - this.onMouseDown = this.onMouseDown.bind(this); - this.onMouseOut = this.onMouseOut.bind(this); - this.onMouseUp = this.onMouseUp.bind(this); - - this.onTouchStart = this.onTouchStart.bind(this); - this.onTouchEnd = this.onTouchEnd.bind(this); - this.onTouchMove = this.onTouchMove.bind(this); - - - this.last = 0; -} - -// constructor -PIXI.InteractionManager.prototype.constructor = PIXI.InteractionManager; - -/** - * Collects an interactive sprite recursively to have their interactions managed - * - * @method collectInteractiveSprite - * @param displayObject {DisplayObject} the displayObject to collect - * @param iParent {DisplayObject} - * @private - */ -PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObject, iParent) -{ - var children = displayObject.children; - var length = children.length; - - /// make an interaction tree... {item.__interactiveParent} - for (var i = length-1; i >= 0; i--) - { - var child = children[i]; - -// if(child.visible) { - // push all interactive bits - if(child.interactive) - { - iParent.interactiveChildren = true; - //child.__iParent = iParent; - this.interactiveItems.push(child); - - if(child.children.length > 0) - { - this.collectInteractiveSprite(child, child); - } - } - else - { - child.__iParent = null; - - if(child.children.length > 0) - { - this.collectInteractiveSprite(child, iParent); - } - } -// } - } -} - -/** - * Sets the target for event delegation - * - * @method setTarget - * @param target {WebGLRenderer|CanvasRenderer} the renderer to bind events to - * @private - */ -PIXI.InteractionManager.prototype.setTarget = function(target) -{ - this.target = target; - - //check if the dom element has been set. If it has don't do anything - if( this.interactionDOMElement === null ) { - - this.setTargetDomElement( target.view ); - } - - document.body.addEventListener('mouseup', this.onMouseUp, true); -} - - -/** - * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM - * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element - * to receive those events - * - * @method setTargetDomElement - * @param domElement {DOMElement} the dom element which will receive mouse and touch events - * @private - */ -PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) -{ - //remove previouse listeners - if( this.interactionDOMElement !== null ) - { - this.interactionDOMElement.style['-ms-content-zooming'] = ''; - this.interactionDOMElement.style['-ms-touch-action'] = ''; - - this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); - this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); - this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); - - // aint no multi touch just yet! - this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); - this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); - this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); - } - - - if (window.navigator.msPointerEnabled) - { - // time to remove some of that zoom in ja.. - domElement.style['-ms-content-zooming'] = 'none'; - domElement.style['-ms-touch-action'] = 'none'; - - // DO some window specific touch! - } - - this.interactionDOMElement = domElement; - - domElement.addEventListener('mousemove', this.onMouseMove, true); - domElement.addEventListener('mousedown', this.onMouseDown, true); - domElement.addEventListener('mouseout', this.onMouseOut, true); - - // aint no multi touch just yet! - domElement.addEventListener('touchstart', this.onTouchStart, true); - domElement.addEventListener('touchend', this.onTouchEnd, true); - domElement.addEventListener('touchmove', this.onTouchMove, true); -} - - -/** - * updates the state of interactive objects - * - * @method update - * @private - */ -PIXI.InteractionManager.prototype.update = function() -{ - if(!this.target)return; - - // frequency of 30fps?? - var now = Date.now(); - var diff = now - this.last; - diff = (diff * 30) / 1000; - if(diff < 1)return; - this.last = now; - // - - // ok.. so mouse events?? - // yes for now :) - // OPTIMSE - how often to check?? - if(this.dirty) - { - this.dirty = false; - - var len = this.interactiveItems.length; - - for (var i=0; i < len; i++) { - this.interactiveItems[i].interactiveChildren = false; - } - - this.interactiveItems = []; - - if(this.stage.interactive)this.interactiveItems.push(this.stage); - // go through and collect all the objects that are interactive.. - this.collectInteractiveSprite(this.stage, this.stage); - } - - // loop through interactive objects! - var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - - //if(!item.visible)continue; - - // OPTIMISATION - only calculate every time if the mousemove function exists.. - // OK so.. does the object have any other interactive functions? - // hit-test the clip! - - - if(item.mouseover || item.mouseout || item.buttonMode) - { - // ok so there are some functions so lets hit test it.. - item.__hit = this.hitTest(item, this.mouse); - this.mouse.target = item; - // ok so deal with interactions.. - // loks like there was a hit! - if(item.__hit) - { - if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; - - if(!item.__isOver) - { - - if(item.mouseover)item.mouseover(this.mouse); - item.__isOver = true; - } - } - else - { - if(item.__isOver) - { - // roll out! - if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; - } - } - } - - // ---> - } -} - -/** - * Is called when the mouse moves accross the renderer element - * - * @method onMouseMove - * @param event {Event} The DOM event of the mouse moving - * @private - */ -PIXI.InteractionManager.prototype.onMouseMove = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - // TODO optimize by not check EVERY TIME! maybe half as often? // - var rect = this.interactionDOMElement.getBoundingClientRect(); - - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); - - var length = this.interactiveItems.length; - var global = this.mouse.global; - - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mousemove) - { - //call the function! - item.mousemove(this.mouse); - } - } -} - -/** - * Is called when the mouse button is pressed down on the renderer element - * - * @method onMouseDown - * @param event {Event} The DOM event of a mouse button being pressed down - * @private - */ -PIXI.InteractionManager.prototype.onMouseDown = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - - // loop through inteaction tree... - // hit test each item! -> - // get interactive items under point?? - //stage.__i - var length = this.interactiveItems.length; - var global = this.mouse.global; - - var index = 0; - var parent = this.stage; - - // while - // hit test - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mousedown || item.click) - { - item.__mouseIsDown = true; - item.__hit = this.hitTest(item, this.mouse); - - if(item.__hit) - { - //call the function! - if(item.mousedown)item.mousedown(this.mouse); - item.__isDown = true; - - // just the one! - if(!item.interactiveChildren)break; - } - } - } -} - - -PIXI.InteractionManager.prototype.onMouseOut = function(event) -{ - var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.__isOver) - { - this.mouse.target = item; - if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; - } - } -} - -/** - * Is called when the mouse button is released on the renderer element - * - * @method onMouseUp - * @param event {Event} The DOM event of a mouse button being released - * @private - */ -PIXI.InteractionManager.prototype.onMouseUp = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - - var global = this.mouse.global; - - - var length = this.interactiveItems.length; - var up = false; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mouseup || item.mouseupoutside || item.click) - { - item.__hit = this.hitTest(item, this.mouse); - - if(item.__hit && !up) - { - //call the function! - if(item.mouseup) - { - item.mouseup(this.mouse); - } - if(item.__isDown) - { - if(item.click)item.click(this.mouse); - } - - if(!item.interactiveChildren)up = true; - } - else - { - if(item.__isDown) - { - if(item.mouseupoutside)item.mouseupoutside(this.mouse); - } - } - - item.__isDown = false; - } - } -} - -/** - * Tests if the current mouse coords hit a sprite - * - * @method hitTest - * @param item {DisplayObject} The displayObject to test for a hit - * @param interactionData {InteractionData} The interactiondata object to update in the case of a hit - * @private - */ -PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) -{ - var global = interactionData.global; - - if(item.vcount !== PIXI.visibleCount)return false; - - var isSprite = (item instanceof PIXI.Sprite), - worldTransform = item.worldTransform, - a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10), - x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, - y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - interactionData.target = item; - - //a sprite or display object with a hit area defined - if(item.hitArea && item.hitArea.contains) { - if(item.hitArea.contains(x, y)) { - //if(isSprite) - interactionData.target = item; - - return true; - } - - return false; - } - // a sprite with no hitarea defined - else if(isSprite) - { - var width = item.texture.frame.width, - height = item.texture.frame.height, - x1 = -width * item.anchor.x, - y1; - - if(x > x1 && x < x1 + width) - { - y1 = -height * item.anchor.y; - - if(y > y1 && y < y1 + height) - { - // set the target property if a hit is true! - interactionData.target = item - return true; - } - } - } - - var length = item.children.length; - - for (var i = 0; i < length; i++) - { - var tempItem = item.children[i]; - var hit = this.hitTest(tempItem, interactionData); - if(hit) - { - // hmm.. TODO SET CORRECT TARGET? - interactionData.target = item - return true; - } - } - - return false; -} - -/** - * Is called when a touch is moved accross the renderer element - * - * @method onTouchMove - * @param event {Event} The DOM event of a touch moving accross the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchMove = function(event) -{ - var rect = this.interactionDOMElement.getBoundingClientRect(); - var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - var touchData = this.touchs[touchEvent.identifier]; - touchData.originalEvent = event || window.event; - - // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - } - - var length = this.interactiveItems.length; - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - if(item.touchmove)item.touchmove(touchData); - } -} - -/** - * Is called when a touch is started on the renderer element - * - * @method onTouchStart - * @param event {Event} The DOM event of a touch starting on the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchStart = function(event) -{ - var rect = this.interactionDOMElement.getBoundingClientRect(); - - var changedTouches = event.changedTouches; - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - - var touchData = this.pool.pop(); - if(!touchData)touchData = new PIXI.InteractionData(); - - touchData.originalEvent = event || window.event; - - this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - - var length = this.interactiveItems.length; - - for (var j = 0; j < length; j++) - { - var item = this.interactiveItems[j]; - - if(item.touchstart || item.tap) - { - item.__hit = this.hitTest(item, touchData); - - if(item.__hit) - { - //call the function! - if(item.touchstart)item.touchstart(touchData); - item.__isDown = true; - item.__touchData = touchData; - - if(!item.interactiveChildren)break; - } - } - } - } -} - -/** - * Is called when a touch is ended on the renderer element - * - * @method onTouchEnd - * @param event {Event} The DOM event of a touch ending on the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchEnd = function(event) -{ - //this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.interactionDOMElement.getBoundingClientRect(); - var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - var touchData = this.touchs[touchEvent.identifier]; - var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - - var length = this.interactiveItems.length; - for (var j = 0; j < length; j++) - { - var item = this.interactiveItems[j]; - var itemTouchData = item.__touchData; // <-- Here! - item.__hit = this.hitTest(item, touchData); - - if(itemTouchData == touchData) - { - // so this one WAS down... - touchData.originalEvent = event || window.event; - // hitTest?? - - if(item.touchend || item.tap) - { - if(item.__hit && !up) - { - if(item.touchend)item.touchend(touchData); - if(item.__isDown) - { - if(item.tap)item.tap(touchData); - } - - if(!item.interactiveChildren)up = true; - } - else - { - if(item.__isDown) - { - if(item.touchendoutside)item.touchendoutside(touchData); - } - } - - item.__isDown = false; - } - - item.__touchData = null; - - } - else - { - - } - } - // remove the touch.. - this.pool.push(touchData); - this.touchs[touchEvent.identifier] = null; - } -} - -/** - * Holds all information related to an Interaction event - * - * @class InteractionData - * @constructor - */ -PIXI.InteractionData = function() -{ - /** - * This point stores the global coords of where the touch/mouse event happened - * - * @property global - * @type Point - */ - this.global = new PIXI.Point(); - - // this is here for legacy... but will remove - this.local = new PIXI.Point(); - - /** - * The target Sprite that was interacted with - * - * @property target - * @type Sprite - */ - this.target; - - /** - * When passed to an event handler, this will be the original DOM Event that was captured - * - * @property originalEvent - * @type Event - */ - this.originalEvent; -} - -/** - * This will return the local coords of the specified displayObject for this InteractionData - * - * @method getLocalPosition - * @param displayObject {DisplayObject} The DisplayObject that you would like the local coords off - * @return {Point} A point containing the coords of the InteractionData position relative to the DisplayObject - */ -PIXI.InteractionData.prototype.getLocalPosition = function(displayObject) -{ - var worldTransform = displayObject.worldTransform; - var global = this.global; - - // do a cheeky transform to get the mouse coords; - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - // set the mouse coords... - return new PIXI.Point(a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, - a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id) -} - -// constructor -PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Stage represents the root of the display tree. Everything connected to the stage is rendered - * - * @class Stage - * @extends DisplayObjectContainer - * @constructor - * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format - * like: 0xFFFFFF for white - */ -PIXI.Stage = function(backgroundColor) -{ - PIXI.DisplayObjectContainer.call( this ); - - /** - * [read-only] Current transform of the object based on world (parent) factors - * - * @property worldTransform - * @type Mat3 - * @readOnly - * @private - */ - this.worldTransform = PIXI.mat3.create(); - - /** - * Whether or not the stage is interactive - * - * @property interactive - * @type Boolean - */ - this.interactive = true; - - /** - * The interaction manage for this stage, manages all interactive activity on the stage - * - * @property interactive - * @type InteractionManager - */ - this.interactionManager = new PIXI.InteractionManager(this); - - /** - * Whether the stage is dirty and needs to have interactions updated - * - * @property dirty - * @type Boolean - * @private - */ - this.dirty = true; - - this.__childrenAdded = []; - this.__childrenRemoved = []; - - //the stage is it's own stage - this.stage = this; - - //optimize hit detection a bit - this.stage.hitArea = new PIXI.Rectangle(0,0,100000, 100000); - - this.setBackgroundColor(backgroundColor); - this.worldVisible = true; -} - -// constructor -PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Stage.prototype.constructor = PIXI.Stage; - -/** - * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. - * This is useful for when you have other DOM elements ontop of the Canvas element. - * - * @method setInteractionDelegate - * @param domElement {DOMElement} This new domElement which will receive mouse/touch events - */ -PIXI.Stage.prototype.setInteractionDelegate = function(domElement) -{ - this.interactionManager.setTargetDomElement( domElement ); -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.Stage.prototype.updateTransform = function() -{ - this.worldAlpha = 1; - this.vcount = PIXI.visibleCount; - - for(var i=0,j=this.children.length; i> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; -} - -/** - * A polyfill for Function.prototype.bind - * - * @method bind - */ -if (typeof Function.prototype.bind != 'function') { - Function.prototype.bind = (function () { - var slice = Array.prototype.slice; - return function (thisArg) { - var target = this, boundArgs = slice.call(arguments, 1); - - if (typeof target != 'function') throw new TypeError(); - - function bound() { - var args = boundArgs.concat(slice.call(arguments)); - target.apply(this instanceof bound ? this : thisArg, args); - } - - bound.prototype = (function F(proto) { - proto && (F.prototype = proto); - if (!(this instanceof F)) return new F; - })(target.prototype); - - return bound; - }; - })(); -} - -/** - * A wrapper for ajax requests to be handled cross browser - * - * @class AjaxRequest - * @constructor - */ -var AjaxRequest = PIXI.AjaxRequest = function() -{ - var activexmodes = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Microsoft.XMLHTTP"] //activeX versions to check for in IE - - if (window.ActiveXObject) - { //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken) - for (var i=0; i>>>>>>>>") - console.log("_") - var safe = 0; - var tmp = item.first; - console.log(tmp); - - while(tmp._iNext) - { - safe++; - tmp = tmp._iNext; - console.log(tmp); - // console.log(tmp); - - if(safe > 100) - { - console.log("BREAK") - break - } - } -} - - - - - - -/** - * https://github.com/mrdoob/eventtarget.js/ - * THankS mr DOob! - */ - -/** - * Adds event emitter functionality to a class - * - * @class EventTarget - * @example - * function MyEmitter() { - * PIXI.EventTarget.call(this); //mixes in event target stuff - * } - * - * var em = new MyEmitter(); - * em.emit({ type: 'eventName', data: 'some data' }); - */ -PIXI.EventTarget = function () { - - var listeners = {}; - - this.addEventListener = this.on = function ( type, listener ) { - - - if ( listeners[ type ] === undefined ) { - - listeners[ type ] = []; - - } - - if ( listeners[ type ].indexOf( listener ) === - 1 ) { - - listeners[ type ].push( listener ); - } - - }; - - this.dispatchEvent = this.emit = function ( event ) { - - if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { - - return; - - } - - for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { - - listeners[ event.type ][ i ]( event ); - - } - - }; - - this.removeEventListener = this.off = function ( type, listener ) { - - var index = listeners[ type ].indexOf( listener ); - - if ( index !== - 1 ) { - - listeners[ type ].splice( index, 1 ); - - } - - }; - -}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * This helper function will automatically detect which renderer you should be using. - * WebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by - * the browser then this function will return a canvas renderer - * - * @method autoDetectRenderer - * @static - * @param width {Number} the width of the renderers view - * @param height {Number} the height of the renderers view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) - * - * antialias - */ -PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) -{ - if(!width)width = 800; - if(!height)height = 600; - - // BORROWED from Mr Doob (mrdoob.com) - var webgl = ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(); - - //console.log(webgl); - if( webgl ) - { - return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); - } - - return new PIXI.CanvasRenderer(width, height, view, transparent); -}; - - - -/* - PolyK library - url: http://polyk.ivank.net - Released under MIT licence. - - Copyright (c) 2012 Ivan Kuckir - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - - This is an amazing lib! - - slightly modified by mat groves (matgroves.com); -*/ - -PIXI.PolyK = {}; - -/** - * Triangulates shapes for webGL graphic fills - * - * @method Triangulate - * @namespace PolyK - * @constructor - */ -PIXI.PolyK.Triangulate = function(p) -{ - var sign = true; - - var n = p.length>>1; - if(n<3) return []; - var tgs = []; - var avl = []; - for(var i=0; i 3) - { - var i0 = avl[(i+0)%al]; - var i1 = avl[(i+1)%al]; - var i2 = avl[(i+2)%al]; - - var ax = p[2*i0], ay = p[2*i0+1]; - var bx = p[2*i1], by = p[2*i1+1]; - var cx = p[2*i2], cy = p[2*i2+1]; - - var earFound = false; - if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) - { - earFound = true; - for(var j=0; j 3*al) - { - // need to flip flip reverse it! - // reset! - if(sign) - { - var tgs = []; - avl = []; - for(var i=0; i= 0) && (v >= 0) && (u + v < 1); -} - -/** - * Checks if a shape is convex - * - * @class _convex - * @namespace PolyK - * @private - */ -PIXI.PolyK._convex = function(ax, ay, bx, by, cx, cy, sign) -{ - return ((ay-by)*(cx-bx) + (bx-ax)*(cy-by) >= 0) == sign; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/* - * the default suoer fast shader! - */ - -PIXI.shaderFragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", - "gl_FragColor = gl_FragColor * vColor;", - "}" -]; - -PIXI.shaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - - "uniform vec2 projectionVector;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "void main(void) {", - "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" -]; - -/* - * the triangle strip shader.. - */ - -PIXI.stripShaderFragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform float alpha;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", - "gl_FragColor = gl_FragColor * alpha;", - "}" -]; - - -PIXI.stripShaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" -]; - -/* - * primitive shader.. - */ - -PIXI.primitiveShaderFragmentSrc = [ - "precision mediump float;", - "varying vec4 vColor;", - "void main(void) {", - "gl_FragColor = vColor;", - "}" -]; - -PIXI.primitiveShaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec4 aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "uniform float alpha;", - "varying vec4 vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vColor = aColor * alpha;", - "}" -]; - -PIXI.shaderStack = []; - -PIXI.initPrimitiveShader = function() -{ - var gl = PIXI.gl; - - var shaderProgram = PIXI.compileProgram(PIXI.primitiveShaderVertexSrc, PIXI.primitiveShaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); - - - //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - //gl.enableVertexAttribArray(shaderProgram.colorAttribute); -//gl.enableVertexAttribArray(program.textureCoordAttribute); - - shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); - - PIXI.primitiveProgram = shaderProgram; - - -} - -PIXI.initDefaultShader = function() -{ - PIXI.defaultShader = new PIXI.PixiShader(); - PIXI.defaultShader.init(); - PIXI.activateShader(PIXI.defaultShader); - /* - PIXI.shaderStack.push(PIXI.defaultShader); - PIXI.current*/ -} - -PIXI.initDefaultStripShader = function() -{ - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.stripShaderVertexSrc, PIXI.stripShaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); - shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); - - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.stripShaderProgram = shaderProgram; -} - -PIXI.CompileVertexShader = function(gl, shaderSrc) -{ - return PIXI._CompileShader(gl, shaderSrc, gl.VERTEX_SHADER); -} - -PIXI.CompileFragmentShader = function(gl, shaderSrc) -{ - return PIXI._CompileShader(gl, shaderSrc, gl.FRAGMENT_SHADER); -} - -PIXI._CompileShader = function(gl, shaderSrc, shaderType) -{ - var src = shaderSrc.join("\n"); - var shader = gl.createShader(shaderType); - gl.shaderSource(shader, src); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - alert(gl.getShaderInfoLog(shader)); - return null; - } - - return shader; -} - - -PIXI.compileProgram = function(vertexSrc, fragmentSrc) -{ - var gl = PIXI.gl; - var fragmentShader = PIXI.CompileFragmentShader(gl, fragmentSrc); - var vertexShader = PIXI.CompileVertexShader(gl, vertexSrc); - - var shaderProgram = gl.createProgram(); - - gl.attachShader(shaderProgram, vertexShader); - gl.attachShader(shaderProgram, fragmentShader); - gl.linkProgram(shaderProgram); - - if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { - alert("Could not initialise shaders"); - } - - return shaderProgram; -} - -PIXI.activateShader = function(shader) -{ - PIXI.shaderStack.push(shader); - - //console.log(">>>") - var gl = PIXI.gl; - - var shaderProgram = shader.program; - - // map uniforms.. - gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - - shader.syncUniforms(); - - PIXI.currentShader = shaderProgram; -} - - -PIXI.popShader = function() -{ - var gl = PIXI.gl; - // activate last program.. - var lastProgram = PIXI.shaderStack.pop(); - - var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; - - gl.useProgram(shaderProgram); - - PIXI.currentShader = shaderProgram; -} - -PIXI.activatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.primitiveProgram); - - //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); - //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); - gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); - - //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); - //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); -} - -PIXI.deactivatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.currentShader); - - gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); - //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); - //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -PIXI.PixiShader = function() -{ - // the webGL program.. - this.program; - - this.fragmentSrc = [ - "precision lowp float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", - "}" - ]; - -} - -PIXI.PixiShader.prototype.init = function() -{ - var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) - - var gl = PIXI.gl; - - gl.useProgram(program); - - // get the default shader bits! - program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); - program.colorAttribute = gl.getAttribLocation(program, "aColor"); - program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); - - program.projectionVector = gl.getUniformLocation(program, "projectionVector"); - program.samplerUniform = gl.getUniformLocation(program, "uSampler"); - - // add those custom shaders! - for (var key in this.uniforms) - { - // get the uniform locations.. - program[key] = gl.getUniformLocation(program, key); - } - - this.program = program; -} - -PIXI.PixiShader.prototype.syncUniforms = function() -{ - var gl = PIXI.gl; - - for (var key in this.uniforms) - { - //var - var type = this.uniforms[key].type; - - // need to grow this! - if(type == "f") - { - gl.uniform1f(this.program[key], this.uniforms[key].value); - } - else if(type == "mat4") - { - gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); - } - } - -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A set of functions used by the webGL renderer to draw the primitive graphics data - * - * @class CanvasGraphics - */ -PIXI.WebGLGraphics = function() -{ - -} - -/** - * Renders the graphics object - * - * @static - * @private - * @method renderGraphics - * @param graphics {Graphics} - * @param projection {Object} - */ -PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) -{ - var gl = PIXI.gl; - - if(!graphics._webGL)graphics._webGL = {points:[], indices:[], lastIndex:0, - buffer:gl.createBuffer(), - indexBuffer:gl.createBuffer()}; - - if(graphics.dirty) - { - graphics.dirty = false; - - if(graphics.clearDirty) - { - graphics.clearDirty = false; - - graphics._webGL.lastIndex = 0; - graphics._webGL.points = []; - graphics._webGL.indices = []; - - } - - PIXI.WebGLGraphics.updateGraphics(graphics); - } - - - PIXI.activatePrimitiveShader(); - - // This could be speeded up fo sure! - var m = PIXI.mat3.clone(graphics.worldTransform); - - PIXI.mat3.transpose(m); - - // set the matrix transform for the - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - gl.uniformMatrix3fv(PIXI.primitiveProgram.translationMatrix, false, m); - - gl.uniform2f(PIXI.primitiveProgram.projectionVector, projection.x, projection.y); - - gl.uniform1f(PIXI.primitiveProgram.alpha, graphics.worldAlpha); - - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - - // WHY DOES THIS LINE NEED TO BE THERE??? - //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - // its not even used.. but need to be set or it breaks? - // only on pc though.. - - gl.vertexAttribPointer(PIXI.primitiveProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 4 * 6, 0); - gl.vertexAttribPointer(PIXI.primitiveProgram.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4); - - // set the index buffer! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); - - gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); - - PIXI.deactivatePrimitiveShader(); - - // return to default shader... -// PIXI.activateShader(PIXI.defaultShader); -} - -/** - * Updates the graphics object - * - * @static - * @private - * @method updateGraphics - * @param graphics {Graphics} - */ -PIXI.WebGLGraphics.updateGraphics = function(graphics) -{ - for (var i=graphics._webGL.lastIndex; i < graphics.graphicsData.length; i++) - { - var data = graphics.graphicsData[i]; - - if(data.type == PIXI.Graphics.POLY) - { - if(data.fill) - { - if(data.points.length>3) - PIXI.WebGLGraphics.buildPoly(data, graphics._webGL); - } - - if(data.lineWidth > 0) - { - PIXI.WebGLGraphics.buildLine(data, graphics._webGL); - } - } - else if(data.type == PIXI.Graphics.RECT) - { - PIXI.WebGLGraphics.buildRectangle(data, graphics._webGL); - } - else if(data.type == PIXI.Graphics.CIRC || data.type == PIXI.Graphics.ELIP) - { - PIXI.WebGLGraphics.buildCircle(data, graphics._webGL); - } - }; - - graphics._webGL.lastIndex = graphics.graphicsData.length; - - var gl = PIXI.gl; - - graphics._webGL.glPoints = new Float32Array(graphics._webGL.points); - - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - gl.bufferData(gl.ARRAY_BUFFER, graphics._webGL.glPoints, gl.STATIC_DRAW); - - graphics._webGL.glIndicies = new Uint16Array(graphics._webGL.indices); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.glIndicies, gl.STATIC_DRAW); -} - -/** - * Builds a rectangle to draw - * - * @static - * @private - * @method buildRectangle - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData) -{ - // --- // - // need to convert points to a nice regular data - // - var rectData = graphicsData.points; - var x = rectData[0]; - var y = rectData[1]; - var width = rectData[2]; - var height = rectData[3]; - - - if(graphicsData.fill) - { - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var verts = webGLData.points; - var indices = webGLData.indices; - - var vertPos = verts.length/6; - - // start - verts.push(x, y); - verts.push(r, g, b, alpha); - - verts.push(x + width, y); - verts.push(r, g, b, alpha); - - verts.push(x , y + height); - verts.push(r, g, b, alpha); - - verts.push(x + width, y + height); - verts.push(r, g, b, alpha); - - // insert 2 dead triangles.. - indices.push(vertPos, vertPos, vertPos+1, vertPos+2, vertPos+3, vertPos+3) - } - - if(graphicsData.lineWidth) - { - graphicsData.points = [x, y, - x + width, y, - x + width, y + height, - x, y + height, - x, y]; - - PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); - } - -} - -/** - * Builds a circle to draw - * - * @static - * @private - * @method buildCircle - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData) -{ - // --- // - // need to convert points to a nice regular data - // - var rectData = graphicsData.points; - var x = rectData[0]; - var y = rectData[1]; - var width = rectData[2]; - var height = rectData[3]; - - var totalSegs = 40; - var seg = (Math.PI * 2) / totalSegs ; - - if(graphicsData.fill) - { - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var verts = webGLData.points; - var indices = webGLData.indices; - - var vecPos = verts.length/6; - - indices.push(vecPos); - - for (var i=0; i < totalSegs + 1 ; i++) - { - verts.push(x,y, r, g, b, alpha); - - verts.push(x + Math.sin(seg * i) * width, - y + Math.cos(seg * i) * height, - r, g, b, alpha); - - indices.push(vecPos++, vecPos++); - }; - - indices.push(vecPos-1); - } - - if(graphicsData.lineWidth) - { - graphicsData.points = []; - - for (var i=0; i < totalSegs + 1; i++) - { - graphicsData.points.push(x + Math.sin(seg * i) * width, - y + Math.cos(seg * i) * height) - }; - - PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); - } - -} - -/** - * Builds a line to draw - * - * @static - * @private - * @method buildLine - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) -{ - // TODO OPTIMISE! - - var wrap = true; - var points = graphicsData.points; - if(points.length == 0)return; - - // get first and last point.. figure out the middle! - var firstPoint = new PIXI.Point( points[0], points[1] ); - var lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - - // if the first point is the last point - goona have issues :) - if(firstPoint.x == lastPoint.x && firstPoint.y == lastPoint.y) - { - points.pop(); - points.pop(); - - lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - - var midPointX = lastPoint.x + (firstPoint.x - lastPoint.x) *0.5; - var midPointY = lastPoint.y + (firstPoint.y - lastPoint.y) *0.5; - - points.unshift(midPointX, midPointY); - points.push(midPointX, midPointY) - } - - var verts = webGLData.points; - var indices = webGLData.indices; - var length = points.length / 2; - var indexCount = points.length; - var indexStart = verts.length/6; - - // DRAW the Line - var width = graphicsData.lineWidth / 2; - - // sort color - var color = HEXtoRGB(graphicsData.lineColor); - var alpha = graphicsData.lineAlpha; - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var p1x, p1y, p2x, p2y, p3x, p3y; - var perpx, perpy, perp2x, perp2y, perp3x, perp3y; - var ipx, ipy; - var a1, b1, c1, a2, b2, c2; - var denom, pdist, dist; - - p1x = points[0]; - p1y = points[1]; - - p2x = points[2]; - p2y = points[3]; - - perpx = -(p1y - p2y); - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - // start - verts.push(p1x - perpx , p1y - perpy, - r, g, b, alpha); - - verts.push(p1x + perpx , p1y + perpy, - r, g, b, alpha); - - for (var i = 1; i < length-1; i++) - { - p1x = points[(i-1)*2]; - p1y = points[(i-1)*2 + 1]; - - p2x = points[(i)*2] - p2y = points[(i)*2 + 1] - - p3x = points[(i+1)*2]; - p3y = points[(i+1)*2 + 1]; - - perpx = -(p1y - p2y); - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - perp2x = -(p2y - p3y); - perp2y = p2x - p3x; - - dist = Math.sqrt(perp2x*perp2x + perp2y*perp2y); - perp2x /= dist; - perp2y /= dist; - perp2x *= width; - perp2y *= width; - - a1 = (-perpy + p1y) - (-perpy + p2y); - b1 = (-perpx + p2x) - (-perpx + p1x); - c1 = (-perpx + p1x) * (-perpy + p2y) - (-perpx + p2x) * (-perpy + p1y); - a2 = (-perp2y + p3y) - (-perp2y + p2y); - b2 = (-perp2x + p2x) - (-perp2x + p3x); - c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y); - - denom = a1*b2 - a2*b1; - - if (denom == 0) { - denom+=1; - } - - px = (b1*c2 - b2*c1)/denom; - py = (a2*c1 - a1*c2)/denom; - - pdist = (px -p2x) * (px -p2x) + (py -p2y) + (py -p2y); - - if(pdist > 140 * 140) - { - perp3x = perpx - perp2x; - perp3y = perpy - perp2y; - - dist = Math.sqrt(perp3x*perp3x + perp3y*perp3y); - perp3x /= dist; - perp3y /= dist; - perp3x *= width; - perp3y *= width; - - verts.push(p2x - perp3x, p2y -perp3y); - verts.push(r, g, b, alpha); - - verts.push(p2x + perp3x, p2y +perp3y); - verts.push(r, g, b, alpha); - - verts.push(p2x - perp3x, p2y -perp3y); - verts.push(r, g, b, alpha); - - indexCount++; - } - else - { - verts.push(px , py); - verts.push(r, g, b, alpha); - - verts.push(p2x - (px-p2x), p2y - (py - p2y)); - verts.push(r, g, b, alpha); - } - } - - p1x = points[(length-2)*2] - p1y = points[(length-2)*2 + 1] - - p2x = points[(length-1)*2] - p2y = points[(length-1)*2 + 1] - - perpx = -(p1y - p2y) - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - verts.push(p2x - perpx , p2y - perpy) - verts.push(r, g, b, alpha); - - verts.push(p2x + perpx , p2y + perpy) - verts.push(r, g, b, alpha); - - indices.push(indexStart); - - for (var i=0; i < indexCount; i++) - { - indices.push(indexStart++); - }; - - indices.push(indexStart-1); -} - -/** - * Builds a polygon to draw - * - * @static - * @private - * @method buildPoly - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData) -{ - var points = graphicsData.points; - if(points.length < 6)return; - - // get first and last point.. figure out the middle! - var verts = webGLData.points; - var indices = webGLData.indices; - - var length = points.length / 2; - - // sort color - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var triangles = PIXI.PolyK.Triangulate(points); - - var vertPos = verts.length / 6; - - for (var i=0; i < triangles.length; i+=3) - { - indices.push(triangles[i] + vertPos); - indices.push(triangles[i] + vertPos); - indices.push(triangles[i+1] + vertPos); - indices.push(triangles[i+2] +vertPos); - indices.push(triangles[i+2] + vertPos); - }; - - for (var i = 0; i < length; i++) - { - verts.push(points[i * 2], points[i * 2 + 1], - r, g, b, alpha); - }; -} - -function HEXtoRGB(hex) { - return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; -} - - - - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI._defaultFrame = new PIXI.Rectangle(0,0,1,1); - -// an instance of the gl context.. -// only one at the moment :/ -PIXI.gl; - -/** - * the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer - * should be used for browsers support webGL. This Render works by automatically managing webGLBatchs. - * So no need for Sprite Batch's or Sprite Cloud's - * Dont forget to add the view to your DOM or you will not see anything :) - * - * @class WebGLRenderer - * @constructor - * @param width=0 {Number} the width of the canvas view - * @param height=0 {Number} the height of the canvas view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) - * - */ -PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) -{ - // do a catch.. only 1 webGL renderer.. - - this.transparent = !!transparent; - - this.width = width || 800; - this.height = height || 600; - - this.view = view || document.createElement( 'canvas' ); - this.view.width = this.width; - this.view.height = this.height; - - // deal with losing context.. - var scope = this; - this.view.addEventListener('webglcontextlost', function(event) { scope.handleContextLost(event); }, false) - this.view.addEventListener('webglcontextrestored', function(event) { scope.handleContextRestored(event); }, false) - - this.batchs = []; - - try - { - PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { - alpha: this.transparent, - antialias:!!antialias, // SPEED UP?? - premultipliedAlpha:false, - stencil:true - }); - } - catch (e) - { - throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); - } - - PIXI.initDefaultShader(); - PIXI.initPrimitiveShader(); - PIXI.initDefaultStripShader(); - - -// PIXI.activateDefaultShader(); - - var gl = this.gl; - PIXI.WebGLRenderer.gl = gl; - - this.batch = new PIXI.WebGLBatch(gl); - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - - gl.enable(gl.BLEND); - gl.colorMask(true, true, true, this.transparent); - - PIXI.projection = new PIXI.Point(400, 300); - - this.resize(this.width, this.height); - this.contextLost = false; - - PIXI.activateShader(PIXI.defaultShader); - - this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); - -} - -// constructor -PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; - -/** - * Gets a new WebGLBatch from the pool - * - * @static - * @method getBatch - * @return {WebGLBatch} - * @private - */ -PIXI.WebGLRenderer.getBatch = function() -{ - if(PIXI._batchs.length == 0) - { - return new PIXI.WebGLBatch(PIXI.WebGLRenderer.gl); - } - else - { - return PIXI._batchs.pop(); - } -} - -/** - * Puts a batch back into the pool - * - * @static - * @method returnBatch - * @param batch {WebGLBatch} The batch to return - * @private - */ -PIXI.WebGLRenderer.returnBatch = function(batch) -{ - batch.clean(); - PIXI._batchs.push(batch); -} - -/** - * Renders the stage to its webGL view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.WebGLRenderer.prototype.render = function(stage) -{ - if(this.contextLost)return; - - - // if rendering a new stage clear the batchs.. - if(this.__stage !== stage) - { - // TODO make this work - // dont think this is needed any more? - this.__stage = stage; - this.stageRenderGroup.setRenderable(stage); - } - - // TODO not needed now... - // update children if need be - // best to remove first! - /*for (var i=0; i < stage.__childrenRemoved.length; i++) - { - var group = stage.__childrenRemoved[i].__renderGroup - if(group)group.removeDisplayObject(stage.__childrenRemoved[i]); - }*/ - - // update any textures - PIXI.WebGLRenderer.updateTextures(); - - // update the scene graph - PIXI.visibleCount++; - stage.updateTransform(); - - var gl = this.gl; - - // -- Does this need to be set every frame? -- // - gl.colorMask(true, true, true, this.transparent); - gl.viewport(0, 0, this.width, this.height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); - gl.clear(gl.COLOR_BUFFER_BIT); - - // HACK TO TEST - - this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; - this.stageRenderGroup.render(PIXI.projection); - - // interaction - // run interaction! - if(stage.interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - - // after rendering lets confirm all frames that have been uodated.. - if(PIXI.Texture.frameUpdates.length > 0) - { - for (var i=0; i < PIXI.Texture.frameUpdates.length; i++) - { - PIXI.Texture.frameUpdates[i].updateFrame = false; - }; - - PIXI.Texture.frameUpdates = []; - } -} - -/** - * Updates the textures loaded into this webgl renderer - * - * @static - * @method updateTextures - * @private - */ -PIXI.WebGLRenderer.updateTextures = function() -{ - //TODO break this out into a texture manager... - for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); - PIXI.texturesToUpdate = []; - PIXI.texturesToDestroy = []; -} - -/** - * Updates a loaded webgl texture - * - * @static - * @method updateTexture - * @param texture {Texture} The texture to update - * @private - */ -PIXI.WebGLRenderer.updateTexture = function(texture) -{ - //TODO break this out into a texture manager... - var gl = PIXI.gl; - - if(!texture._glTexture) - { - texture._glTexture = gl.createTexture(); - } - - if(texture.hasLoaded) - { - gl.bindTexture(gl.TEXTURE_2D, texture._glTexture); - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - - // reguler... - - if(!texture._powerOf2) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - } - - gl.bindTexture(gl.TEXTURE_2D, null); - } -} - -/** - * Destroys a loaded webgl texture - * - * @method destroyTexture - * @param texture {Texture} The texture to update - * @private - */ -PIXI.WebGLRenderer.destroyTexture = function(texture) -{ - //TODO break this out into a texture manager... - var gl = PIXI.gl; - - if(texture._glTexture) - { - texture._glTexture = gl.createTexture(); - gl.deleteTexture(gl.TEXTURE_2D, texture._glTexture); - } -} - -/** - * resizes the webGL view to the specified width and height - * - * @method resize - * @param width {Number} the new width of the webGL view - * @param height {Number} the new height of the webGL view - */ -PIXI.WebGLRenderer.prototype.resize = function(width, height) -{ - this.width = width; - this.height = height; - - this.view.width = width; - this.view.height = height; - - this.gl.viewport(0, 0, this.width, this.height); - - //var projectionMatrix = this.projectionMatrix; - - PIXI.projection.x = this.width/2; - PIXI.projection.y = this.height/2; - -// projectionMatrix[0] = 2/this.width; -// projectionMatrix[5] = -2/this.height; -// projectionMatrix[12] = -1; -// projectionMatrix[13] = 1; -} - -/** - * Handles a lost webgl context - * - * @method handleContextLost - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextLost = function(event) -{ - event.preventDefault(); - this.contextLost = true; -} - -/** - * Handles a restored webgl context - * - * @method handleContextRestored - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextRestored = function(event) -{ - this.gl = this.view.getContext("experimental-webgl", { - alpha: true - }); - - this.initShaders(); - - for(var key in PIXI.TextureCache) - { - var texture = PIXI.TextureCache[key].baseTexture; - texture._glTexture = null; - PIXI.WebGLRenderer.updateTexture(texture); - }; - - for (var i=0; i < this.batchs.length; i++) - { - this.batchs[i].restoreLostContext(this.gl)// - this.batchs[i].dirty = true; - }; - - PIXI._restoreBatchs(this.gl); - - this.contextLost = false; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI._batchs = []; - -/** - * @private - */ -PIXI._getBatch = function(gl) -{ - if(PIXI._batchs.length == 0) - { - return new PIXI.WebGLBatch(gl); - } - else - { - return PIXI._batchs.pop(); - } -} - -/** - * @private - */ -PIXI._returnBatch = function(batch) -{ - batch.clean(); - PIXI._batchs.push(batch); -} - -/** - * @private - */ -PIXI._restoreBatchs = function(gl) -{ - for (var i=0; i < PIXI._batchs.length; i++) - { - PIXI._batchs[i].restoreLostContext(gl); - }; -} - -/** - * A WebGLBatch Enables a group of sprites to be drawn using the same settings. - * if a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch. - * All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites - * in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled - * automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster - * the webGL renderer will run. - * - * @class WebGLBatch - * @constructor - * @param gl {WebGLContext} an instance of the webGL context - */ -PIXI.WebGLBatch = function(gl) -{ - this.gl = gl; - - this.size = 0; - - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); - this.blendMode = PIXI.blendModes.NORMAL; - this.dynamicSize = 1; -} - -// constructor -PIXI.WebGLBatch.prototype.constructor = PIXI.WebGLBatch; - -/** - * Cleans the batch so that is can be returned to an object pool and reused - * - * @method clean - */ -PIXI.WebGLBatch.prototype.clean = function() -{ - this.verticies = []; - this.uvs = []; - this.indices = []; - this.colors = []; - this.dynamicSize = 1; - this.texture = null; - this.last = null; - this.size = 0; - this.head; - this.tail; -} - -/** - * Recreates the buffers in the event of a context loss - * - * @method restoreLostContext - * @param gl {WebGLContext} - */ -PIXI.WebGLBatch.prototype.restoreLostContext = function(gl) -{ - this.gl = gl; - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); -} - -/** - * inits the batch's texture and blend mode based if the supplied sprite - * - * @method init - * @param sprite {Sprite} the first sprite to be added to the batch. Only sprites with - * the same base texture and blend mode will be allowed to be added to this batch - */ -PIXI.WebGLBatch.prototype.init = function(sprite) -{ - sprite.batch = this; - this.dirty = true; - this.blendMode = sprite.blendMode; - this.texture = sprite.texture.baseTexture; - this.head = sprite; - this.tail = sprite; - this.size = 1; - - this.growBatch(); -} - -/** - * inserts a sprite before the specified sprite - * - * @method insertBefore - * @param sprite {Sprite} the sprite to be added - * @param nextSprite {nextSprite} the first sprite will be inserted before this sprite - */ -PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) -{ - this.size++; - - sprite.batch = this; - this.dirty = true; - var tempPrev = nextSprite.__prev; - nextSprite.__prev = sprite; - sprite.__next = nextSprite; - - if(tempPrev) - { - sprite.__prev = tempPrev; - tempPrev.__next = sprite; - } - else - { - this.head = sprite; - } -} - -/** - * inserts a sprite after the specified sprite - * - * @method insertAfter - * @param sprite {Sprite} the sprite to be added - * @param previousSprite {Sprite} the first sprite will be inserted after this sprite - */ -PIXI.WebGLBatch.prototype.insertAfter = function(sprite, previousSprite) -{ - this.size++; - - sprite.batch = this; - this.dirty = true; - - var tempNext = previousSprite.__next; - previousSprite.__next = sprite; - sprite.__prev = previousSprite; - - if(tempNext) - { - sprite.__next = tempNext; - tempNext.__prev = sprite; - } - else - { - this.tail = sprite - } -} - -/** - * removes a sprite from the batch - * - * @method remove - * @param sprite {Sprite} the sprite to be removed - */ -PIXI.WebGLBatch.prototype.remove = function(sprite) -{ - this.size--; - - if(this.size == 0) - { - sprite.batch = null; - sprite.__prev = null; - sprite.__next = null; - return; - } - - if(sprite.__prev) - { - sprite.__prev.__next = sprite.__next; - } - else - { - this.head = sprite.__next; - this.head.__prev = null; - } - - if(sprite.__next) - { - sprite.__next.__prev = sprite.__prev; - } - else - { - this.tail = sprite.__prev; - this.tail.__next = null - } - - sprite.batch = null; - sprite.__next = null; - sprite.__prev = null; - this.dirty = true; -} - -/** - * Splits the batch into two with the specified sprite being the start of the new batch. - * - * @method split - * @param sprite {Sprite} the sprite that indicates where the batch should be split - * @return {WebGLBatch} the new batch - */ -PIXI.WebGLBatch.prototype.split = function(sprite) -{ - this.dirty = true; - - var batch = new PIXI.WebGLBatch(this.gl); - batch.init(sprite); - batch.texture = this.texture; - batch.tail = this.tail; - - this.tail = sprite.__prev; - this.tail.__next = null; - - sprite.__prev = null; - // return a splite batch! - - // TODO this size is wrong! - // need to recalculate :/ problem with a linked list! - // unless it gets calculated in the "clean"? - - // need to loop through items as there is no way to know the length on a linked list :/ - var tempSize = 0; - while(sprite) - { - tempSize++; - sprite.batch = batch; - sprite = sprite.__next; - } - - batch.size = tempSize; - this.size -= tempSize; - - return batch; -} - -/** - * Merges two batchs together - * - * @method merge - * @param batch {WebGLBatch} the batch that will be merged - */ -PIXI.WebGLBatch.prototype.merge = function(batch) -{ - this.dirty = true; - - this.tail.__next = batch.head; - batch.head.__prev = this.tail; - - this.size += batch.size; - - this.tail = batch.tail; - - var sprite = batch.head; - while(sprite) - { - sprite.batch = this; - sprite = sprite.__next; - } -} - -/** - * Grows the size of the batch. As the elements in the batch cannot have a dynamic size this - * function is used to increase the size of the batch. It also creates a little extra room so - * that the batch does not need to be resized every time a sprite is added - * - * @method growBatch - */ -PIXI.WebGLBatch.prototype.growBatch = function() -{ - var gl = this.gl; - if( this.size == 1) - { - this.dynamicSize = 1; - } - else - { - this.dynamicSize = this.size * 1.5 - } - // grow verts - this.verticies = new Float32Array(this.dynamicSize * 8); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); - - this.uvs = new Float32Array( this.dynamicSize * 8 ); - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); - - this.dirtyUVS = true; - - this.colors = new Float32Array( this.dynamicSize * 4 ); - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); - - this.dirtyColors = true; - - this.indices = new Uint16Array(this.dynamicSize * 6); - var length = this.indices.length/6; - - for (var i=0; i < length; i++) - { - var index2 = i * 6; - var index3 = i * 4; - this.indices[index2 + 0] = index3 + 0; - this.indices[index2 + 1] = index3 + 1; - this.indices[index2 + 2] = index3 + 2; - this.indices[index2 + 3] = index3 + 0; - this.indices[index2 + 4] = index3 + 2; - this.indices[index2 + 5] = index3 + 3; - }; - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); -} - -/** - * Refresh's all the data in the batch and sync's it with the webGL buffers - * - * @method refresh - */ -PIXI.WebGLBatch.prototype.refresh = function() -{ - var gl = this.gl; - - if (this.dynamicSize < this.size) - { - this.growBatch(); - } - - var indexRun = 0; - var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index; - var a, b, c, d, tx, ty; - - var displayObject = this.head; - - while(displayObject) - { - index = indexRun * 8; - - var texture = displayObject.texture; - - var frame = texture.frame; - var tw = texture.baseTexture.width; - var th = texture.baseTexture.height; - - this.uvs[index + 0] = frame.x / tw; - this.uvs[index +1] = frame.y / th; - - this.uvs[index +2] = (frame.x + frame.width) / tw; - this.uvs[index +3] = frame.y / th; - - this.uvs[index +4] = (frame.x + frame.width) / tw; - this.uvs[index +5] = (frame.y + frame.height) / th; - - this.uvs[index +6] = frame.x / tw; - this.uvs[index +7] = (frame.y + frame.height) / th; - - displayObject.updateFrame = false; - - colorIndex = indexRun * 4; - this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; - - displayObject = displayObject.__next; - - indexRun ++; - } - - this.dirtyUVS = true; - this.dirtyColors = true; -} - -/** - * Updates all the relevant geometry and uploads the data to the GPU - * - * @method update - */ -PIXI.WebGLBatch.prototype.update = function() -{ - var gl = this.gl; - var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index, index2, index3 - - var a, b, c, d, tx, ty; - - var indexRun = 0; - - var displayObject = this.head; - - while(displayObject) - { - if(displayObject.vcount === PIXI.visibleCount) - { - width = displayObject.texture.frame.width; - height = displayObject.texture.frame.height; - - // TODO trim?? - aX = displayObject.anchor.x;// - displayObject.texture.trim.x - aY = displayObject.anchor.y; //- displayObject.texture.trim.y - w0 = width * (1-aX); - w1 = width * -aX; - - h0 = height * (1-aY); - h1 = height * -aY; - - index = indexRun * 8; - - worldTransform = displayObject.worldTransform; - - a = worldTransform[0]; - b = worldTransform[3]; - c = worldTransform[1]; - d = worldTransform[4]; - tx = worldTransform[2]; - ty = worldTransform[5]; - - this.verticies[index + 0 ] = a * w1 + c * h1 + tx; - this.verticies[index + 1 ] = d * h1 + b * w1 + ty; - - this.verticies[index + 2 ] = a * w0 + c * h1 + tx; - this.verticies[index + 3 ] = d * h1 + b * w0 + ty; - - this.verticies[index + 4 ] = a * w0 + c * h0 + tx; - this.verticies[index + 5 ] = d * h0 + b * w0 + ty; - - this.verticies[index + 6] = a * w1 + c * h0 + tx; - this.verticies[index + 7] = d * h0 + b * w1 + ty; - - if(displayObject.updateFrame || displayObject.texture.updateFrame) - { - this.dirtyUVS = true; - - var texture = displayObject.texture; - - var frame = texture.frame; - var tw = texture.baseTexture.width; - var th = texture.baseTexture.height; - - this.uvs[index + 0] = frame.x / tw; - this.uvs[index +1] = frame.y / th; - - this.uvs[index +2] = (frame.x + frame.width) / tw; - this.uvs[index +3] = frame.y / th; - - this.uvs[index +4] = (frame.x + frame.width) / tw; - this.uvs[index +5] = (frame.y + frame.height) / th; - - this.uvs[index +6] = frame.x / tw; - this.uvs[index +7] = (frame.y + frame.height) / th; - - displayObject.updateFrame = false; - } - - // TODO this probably could do with some optimisation.... - if(displayObject.cacheAlpha != displayObject.worldAlpha) - { - displayObject.cacheAlpha = displayObject.worldAlpha; - - var colorIndex = indexRun * 4; - this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; - this.dirtyColors = true; - } - } - else - { - index = indexRun * 8; - - this.verticies[index + 0 ] = 0; - this.verticies[index + 1 ] = 0; - - this.verticies[index + 2 ] = 0; - this.verticies[index + 3 ] = 0; - - this.verticies[index + 4 ] = 0; - this.verticies[index + 5 ] = 0; - - this.verticies[index + 6] = 0; - this.verticies[index + 7] = 0; - } - - indexRun++; - displayObject = displayObject.__next; - } -} - -/** - * Draws the batch to the frame buffer - * - * @method render - */ -PIXI.WebGLBatch.prototype.render = function(start, end) -{ - start = start || 0; - - if(end == undefined)end = this.size; - - if(this.dirty) - { - this.refresh(); - this.dirty = false; - } - - if (this.size == 0)return; - - this.update(); - var gl = this.gl; - - //TODO optimize this! - - var shaderProgram = PIXI.currentShader; - - //gl.useProgram(shaderProgram); - - // update the verts.. - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - // ok.. - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - // update the uvs - var isDefault = (shaderProgram == PIXI.shaderProgram) - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - - if(this.dirtyUVS) - { - this.dirtyUVS = false; - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvs); - } - - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this.texture._glTexture); - - // update color! - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - - if(this.dirtyColors) - { - this.dirtyColors = false; - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.colors); - } - - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - var len = end - start; - - // DRAW THAT this! - gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A WebGLBatch Enables a group of sprites to be drawn using the same settings. - * if a group of sprites all have the same baseTexture and blendMode then they can be - * grouped into a batch. All the sprites in a batch can then be drawn in one go by the - * GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch - * even if the batch only contains one sprite. Batching is handled automatically by the - * webGL renderer. A good tip is: the smaller the number of batchs there are, the faster - * the webGL renderer will run. - * - * @class WebGLBatch - * @contructor - * @param gl {WebGLContext} An instance of the webGL context - */ -PIXI.WebGLRenderGroup = function(gl) -{ - this.gl = gl; - this.root; - - this.backgroundColor; - this.batchs = []; - this.toRemove = []; -} - -// constructor -PIXI.WebGLRenderGroup.prototype.constructor = PIXI.WebGLRenderGroup; - -/** - * Add a display object to the webgl renderer - * - * @method setRenderable - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.setRenderable = function(displayObject) -{ - // has this changed?? - if(this.root)this.removeDisplayObjectAndChildren(this.root); - - displayObject.worldVisible = displayObject.visible; - - // soooooo // - // to check if any batchs exist already?? - - // TODO what if its already has an object? should remove it - this.root = displayObject; - this.addDisplayObjectAndChildren(displayObject); -} - -/** - * Renders the stage to its webgl view - * - * @method render - * @param projection {Object} - */ -PIXI.WebGLRenderGroup.prototype.render = function(projection) -{ - PIXI.WebGLRenderer.updateTextures(); - - var gl = this.gl; - - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - // will render all the elements in the group - var renderable; - for (var i=0; i < this.batchs.length; i++) - { - - renderable = this.batchs[i]; - if(renderable instanceof PIXI.WebGLBatch) - { - this.batchs[i].render(); - continue; - } - - // non sprite batch.. - var worldVisible = renderable.vcount === PIXI.visibleCount; - - if(renderable instanceof PIXI.TilingSprite) - { - if(worldVisible)this.renderTilingSprite(renderable, projection); - } - else if(renderable instanceof PIXI.Strip) - { - if(worldVisible)this.renderStrip(renderable, projection); - } - else if(renderable instanceof PIXI.Graphics) - { - if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); - } - else if(renderable instanceof PIXI.FilterBlock) - { - this.handleFilterBlock(renderable, projection); - } - } - -} - -/** - * Renders a specific displayObject - * - * @method renderSpecific - * @param displayObject {DisplayObject} - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection) -{ - PIXI.WebGLRenderer.updateTextures(); - - var gl = this.gl; - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - - // to do! - // render part of the scene... - - var startIndex; - var startBatchIndex; - - var endIndex; - var endBatchIndex; - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.first; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - var startBatch = nextRenderable.batch; - - if(nextRenderable instanceof PIXI.Sprite) - { - startBatch = nextRenderable.batch; - - var head = startBatch.head; - var next = head; - - // ok now we have the batch.. need to find the start index! - if(head == nextRenderable) - { - startIndex = 0; - } - else - { - startIndex = 1; - - while(head.__next != nextRenderable) - { - startIndex++; - head = head.__next; - } - } - } - else - { - startBatch = nextRenderable; - } - - // Get the LAST renderable object - var lastRenderable = displayObject; - var endBatch; - var lastItem = displayObject; - while(lastItem.children.length > 0) - { - lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem.last; - } - - if(lastRenderable instanceof PIXI.Sprite) - { - endBatch = lastRenderable.batch; - - var head = endBatch.head; - - if(head == lastRenderable) - { - endIndex = 0; - } - else - { - endIndex = 1; - - while(head.__next != lastRenderable) - { - endIndex++; - head = head.__next; - } - } - } - else - { - endBatch = lastRenderable; - } - - // TODO - need to fold this up a bit! - - if(startBatch == endBatch) - { - if(startBatch instanceof PIXI.WebGLBatch) - { - startBatch.render(startIndex, endIndex+1); - } - else - { - this.renderSpecial(startBatch, projection); - } - return; - } - - // now we have first and last! - startBatchIndex = this.batchs.indexOf(startBatch); - endBatchIndex = this.batchs.indexOf(endBatch); - - // DO the first batch - if(startBatch instanceof PIXI.WebGLBatch) - { - startBatch.render(startIndex); - } - else - { - this.renderSpecial(startBatch, projection); - } - - // DO the middle batchs.. - for (var i=startBatchIndex+1; i < endBatchIndex; i++) - { - renderable = this.batchs[i]; - - if(renderable instanceof PIXI.WebGLBatch) - { - this.batchs[i].render(); - } - else - { - this.renderSpecial(renderable, projection); - } - } - - // DO the last batch.. - if(endBatch instanceof PIXI.WebGLBatch) - { - endBatch.render(0, endIndex+1); - } - else - { - this.renderSpecial(endBatch, projection); - } -} - -/** - * Renders a specific renderable - * - * @method renderSpecial - * @param renderable {DisplayObject} - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) -{ - var sta = PIXI.shaderStack.length; - - var worldVisible = renderable.vcount === PIXI.visibleCount - - if(renderable instanceof PIXI.TilingSprite) - { - if(worldVisible)this.renderTilingSprite(renderable, projection); - } - else if(renderable instanceof PIXI.Strip) - { - if(worldVisible)this.renderStrip(renderable, projection); - } - else if(renderable instanceof PIXI.CustomRenderable) - { - if(worldVisible) renderable.renderWebGL(this, projection); - } - else if(renderable instanceof PIXI.Graphics) - { - if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); - } - else if(renderable instanceof PIXI.FilterBlock) - { - this.handleFilterBlock(renderable, projection); - } -} - -PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) -{ - /* - * for now only masks are supported.. - */ - var gl = PIXI.gl; - - if(renderable.open) - { - if(renderable.data instanceof Array) - { - var filter = renderable.data[0]; - - if(!filter.shader) - { - var shader = new PIXI.PixiShader(); - - shader.fragmentSrc = filter.fragmentSrc; - shader.uniforms = filter.uniforms; - shader.init(); - - filter.shader = shader - } - - PIXI.activateShader(filter.shader); - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - } - else - { - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); - - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - } - else - { - if(renderable.data instanceof Array) - { - PIXI.popShader(); - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - } - else - { - gl.disable(gl.STENCIL_TEST); - } - } -} - -/** - * Updates a webgl texture - * - * @method updateTexture - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject) -{ - - // TODO definitely can optimse this function.. - - this.removeObject(displayObject); - - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - var previousRenderable = displayObject.first; - while(previousRenderable != this.root) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.last; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - - this.insertObject(displayObject, previousRenderable, nextRenderable); -} - -/** - * Adds filter blocks - * - * @method addFilterBlocks - * @param start {FilterBlock} - * @param end {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) -{ - start.__renderGroup = this; - end.__renderGroup = this; - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - var previousRenderable = start; - while(previousRenderable != this.root.first) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - this.insertAfter(start, previousRenderable); - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var previousRenderable2 = end; - while(previousRenderable2 != this.root.first) - { - previousRenderable2 = previousRenderable2._iPrev; - if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; - } - this.insertAfter(end, previousRenderable2); -} - -/** - * Remove filter blocks - * - * @method removeFilterBlocks - * @param start {FilterBlock} - * @param end {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeFilterBlocks = function(start, end) -{ - this.removeObject(start); - this.removeObject(end); -} - -/** - * Adds a display object and children to the webgl context - * - * @method addDisplayObjectAndChildren - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayObject) -{ - if(displayObject.__renderGroup)displayObject.__renderGroup.removeDisplayObjectAndChildren(displayObject); - - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - - var previousRenderable = displayObject.first; - while(previousRenderable != this.root.first) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.last; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - - // one the display object hits this. we can break the loop - - var tempObject = displayObject.first; - var testObject = displayObject.last._iNext; - do - { - tempObject.__renderGroup = this; - - if(tempObject.renderable) - { - - this.insertObject(tempObject, previousRenderable, nextRenderable); - previousRenderable = tempObject; - } - - tempObject = tempObject._iNext; - } - while(tempObject != testObject) -} - -/** - * Removes a display object and children to the webgl context - * - * @method removeDisplayObjectAndChildren - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren = function(displayObject) -{ - if(displayObject.__renderGroup != this)return; - -// var displayObject = displayObject.first; - var lastObject = displayObject.last; - do - { - displayObject.__renderGroup = null; - if(displayObject.renderable)this.removeObject(displayObject); - displayObject = displayObject._iNext; - } - while(displayObject) -} - -/** - * Inserts a displayObject into the linked list - * - * @method insertObject - * @param displayObject {DisplayObject} - * @param previousObject {DisplayObject} - * @param nextObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousObject, nextObject) -{ - // while looping below THE OBJECT MAY NOT HAVE BEEN ADDED - var previousSprite = previousObject; - var nextSprite = nextObject; - - /* - * so now we have the next renderable and the previous renderable - * - */ - if(displayObject instanceof PIXI.Sprite) - { - var previousBatch - var nextBatch - - if(previousSprite instanceof PIXI.Sprite) - { - previousBatch = previousSprite.batch; - if(previousBatch) - { - if(previousBatch.texture == displayObject.texture.baseTexture && previousBatch.blendMode == displayObject.blendMode) - { - previousBatch.insertAfter(displayObject, previousSprite); - return; - } - } - } - else - { - // TODO reword! - previousBatch = previousSprite; - } - - if(nextSprite) - { - if(nextSprite instanceof PIXI.Sprite) - { - nextBatch = nextSprite.batch; - - //batch may not exist if item was added to the display list but not to the webGL - if(nextBatch) - { - if(nextBatch.texture == displayObject.texture.baseTexture && nextBatch.blendMode == displayObject.blendMode) - { - nextBatch.insertBefore(displayObject, nextSprite); - return; - } - else - { - if(nextBatch == previousBatch) - { - // THERE IS A SPLIT IN THIS BATCH! // - var splitBatch = previousBatch.split(nextSprite); - // COOL! - // add it back into the array - /* - * OOPS! - * seems the new sprite is in the middle of a batch - * lets split it.. - */ - var batch = PIXI.WebGLRenderer.getBatch(); - - var index = this.batchs.indexOf( previousBatch ); - batch.init(displayObject); - this.batchs.splice(index+1, 0, batch, splitBatch); - - return; - } - } - } - } - else - { - // TODO re-word! - - nextBatch = nextSprite; - } - } - - /* - * looks like it does not belong to any batch! - * but is also not intersecting one.. - * time to create anew one! - */ - - var batch = PIXI.WebGLRenderer.getBatch(); - batch.init(displayObject); - - if(previousBatch) // if this is invalid it means - { - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, batch); - } - else - { - this.batchs.push(batch); - } - - return; - } - else if(displayObject instanceof PIXI.TilingSprite) - { - - // add to a batch!! - this.initTilingSprite(displayObject); - // this.batchs.push(displayObject); - - } - else if(displayObject instanceof PIXI.Strip) - { - // add to a batch!! - this.initStrip(displayObject); - // this.batchs.push(displayObject); - } - else if(displayObject)// instanceof PIXI.Graphics) - { - //displayObject.initWebGL(this); - - // add to a batch!! - //this.initStrip(displayObject); - //this.batchs.push(displayObject); - } - - this.insertAfter(displayObject, previousSprite); - - // insert and SPLIT! - -} - -/** - * Inserts a displayObject into the linked list - * - * @method insertAfter - * @param item {DisplayObject} - * @param displayObject {DisplayObject} The object to insert - * @private - */ -PIXI.WebGLRenderGroup.prototype.insertAfter = function(item, displayObject) -{ - if(displayObject instanceof PIXI.Sprite) - { - var previousBatch = displayObject.batch; - - if(previousBatch) - { - // so this object is in a batch! - - // is it not? need to split the batch - if(previousBatch.tail == displayObject) - { - // is it tail? insert in to batchs - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, item); - } - else - { - // TODO MODIFY ADD / REMOVE CHILD TO ACCOUNT FOR FILTERS (also get prev and next) // - - // THERE IS A SPLIT IN THIS BATCH! // - var splitBatch = previousBatch.split(displayObject.__next); - - // COOL! - // add it back into the array - /* - * OOPS! - * seems the new sprite is in the middle of a batch - * lets split it.. - */ - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, item, splitBatch); - } - } - else - { - this.batchs.push(item); - } - } - else - { - var index = this.batchs.indexOf( displayObject ); - this.batchs.splice(index+1, 0, item); - } -} - -/** - * Removes a displayObject from the linked list - * - * @method removeObject - * @param displayObject {DisplayObject} The object to remove - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) -{ - // loop through children.. - // display object // - - // add a child from the render group.. - // remove it and all its children! - //displayObject.cacheVisible = false;//displayObject.visible; - - /* - * removing is a lot quicker.. - * - */ - var batchToRemove; - - if(displayObject instanceof PIXI.Sprite) - { - // should always have a batch! - var batch = displayObject.batch; - if(!batch)return; // this means the display list has been altered befre rendering - - batch.remove(displayObject); - - if(batch.size==0) - { - batchToRemove = batch; - } - } - else - { - batchToRemove = displayObject; - } - - /* - * Looks like there is somthing that needs removing! - */ - if(batchToRemove) - { - var index = this.batchs.indexOf( batchToRemove ); - if(index == -1)return;// this means it was added then removed before rendered - - // ok so.. check to see if you adjacent batchs should be joined. - // TODO may optimise? - if(index == 0 || index == this.batchs.length-1) - { - // wha - eva! just get of the empty batch! - this.batchs.splice(index, 1); - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - - return; - } - - if(this.batchs[index-1] instanceof PIXI.WebGLBatch && this.batchs[index+1] instanceof PIXI.WebGLBatch) - { - if(this.batchs[index-1].texture == this.batchs[index+1].texture && this.batchs[index-1].blendMode == this.batchs[index+1].blendMode) - { - //console.log("MERGE") - this.batchs[index-1].merge(this.batchs[index+1]); - - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - PIXI.WebGLRenderer.returnBatch(this.batchs[index+1]); - this.batchs.splice(index, 2); - return; - } - } - - this.batchs.splice(index, 1); - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - } -} - - -/** - * Initializes a tiling sprite - * - * @method initTilingSprite - * @param sprite {TilingSprite} The tiling sprite to initialize - * @private - */ -PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) -{ - var gl = this.gl; - - // make the texture tilable.. - - sprite.verticies = new Float32Array([0, 0, - sprite.width, 0, - sprite.width, sprite.height, - 0, sprite.height]); - - sprite.uvs = new Float32Array([0, 0, - 1, 0, - 1, 1, - 0, 1]); - - sprite.colors = new Float32Array([1,1,1,1]); - - sprite.indices = new Uint16Array([0, 1, 3,2])//, 2]); - - sprite._vertexBuffer = gl.createBuffer(); - sprite._indexBuffer = gl.createBuffer(); - sprite._uvBuffer = gl.createBuffer(); - sprite._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.verticies, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.uvs, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.colors, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sprite._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sprite.indices, gl.STATIC_DRAW); - -// return ( (x > 0) && ((x & (x - 1)) == 0) ); - - if(sprite.texture.baseTexture._glTexture) - { - gl.bindTexture(gl.TEXTURE_2D, sprite.texture.baseTexture._glTexture); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - sprite.texture.baseTexture._powerOf2 = true; - } - else - { - sprite.texture.baseTexture._powerOf2 = true; - } -} - -/** - * Renders a Strip - * - * @method renderStrip - * @param strip {Strip} The strip to render - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) -{ - var gl = this.gl; - var shaderProgram = PIXI.stripShaderProgram; - - - gl.useProgram(shaderProgram); - - var m = PIXI.mat3.clone(strip.worldTransform); - - PIXI.mat3.transpose(m); - - // set the matrix transform for the - gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); - gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); - -/* - if(strip.blendMode == PIXI.blendModes.NORMAL) - { - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - } - else - { - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR); - } - */ - - - if(!strip.dirty) - { - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, strip.verticies) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - } - else - { - strip.dirty = false; - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); - - } - - gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - - gl.useProgram(PIXI.currentProgram); -} - -/** - * Renders a TilingSprite - * - * @method renderTilingSprite - * @param sprite {TilingSprite} The tiling sprite to render - * @param projectionMatrix {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderTilingSprite = function(sprite, projectionMatrix) -{ - var gl = this.gl; - var shaderProgram = PIXI.shaderProgram; - - var tilePosition = sprite.tilePosition; - var tileScale = sprite.tileScale; - - var offsetX = tilePosition.x/sprite.texture.baseTexture.width; - var offsetY = tilePosition.y/sprite.texture.baseTexture.height; - - var scaleX = (sprite.width / sprite.texture.baseTexture.width) / tileScale.x; - var scaleY = (sprite.height / sprite.texture.baseTexture.height) / tileScale.y; - - sprite.uvs[0] = 0 - offsetX; - sprite.uvs[1] = 0 - offsetY; - - sprite.uvs[2] = (1 * scaleX) -offsetX; - sprite.uvs[3] = 0 - offsetY; - - sprite.uvs[4] = (1 *scaleX) - offsetX; - sprite.uvs[5] = (1 *scaleY) - offsetY; - - sprite.uvs[6] = 0 - offsetX; - sprite.uvs[7] = (1 *scaleY) - offsetY; - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, sprite.uvs) - - this.renderStrip(sprite, projectionMatrix); -} - -/** - * Initializes a strip to be rendered - * - * @method initStrip - * @param strip {Strip} The strip to initialize - * @private - */ -PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) -{ - // build the strip! - var gl = this.gl; - var shaderProgram = this.shaderProgram; - - strip._vertexBuffer = gl.createBuffer(); - strip._indexBuffer = gl.createBuffer(); - strip._uvBuffer = gl.createBuffer(); - strip._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW); - - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * the CanvasRenderer draws the stage and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. - * Dont forget to add the view to your DOM or you will not see anything :) - * - * @class CanvasRenderer - * @constructor - * @param width=0 {Number} the width of the canvas view - * @param height=0 {Number} the height of the canvas view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - */ -PIXI.CanvasRenderer = function(width, height, view, transparent) -{ - this.transparent = transparent; - - /** - * The width of the canvas view - * - * @property width - * @type Number - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @property height - * @type Number - * @default 600 - */ - this.height = height || 600; - - /** - * The canvas element that the everything is drawn to - * - * @property view - * @type Canvas - */ - this.view = view || document.createElement( 'canvas' ); - - /** - * The canvas context that the everything is drawn to - * @property context - * @type Canvas 2d Context - */ - this.context = this.view.getContext("2d"); - - this.refresh = true; - // hack to enable some hardware acceleration! - //this.view.style["transform"] = "translatez(0)"; - - this.view.width = this.width; - this.view.height = this.height; - this.count = 0; -} - -// constructor -PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; - -/** - * Renders the stage to its canvas view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.CanvasRenderer.prototype.render = function(stage) -{ - - //stage.__childrenAdded = []; - //stage.__childrenRemoved = []; - - // update textures if need be - PIXI.texturesToUpdate = []; - PIXI.texturesToDestroy = []; - - PIXI.visibleCount++; - stage.updateTransform(); - - // update the background color - if(this.view.style.backgroundColor!=stage.backgroundColorString && !this.transparent)this.view.style.backgroundColor = stage.backgroundColorString; - - this.context.setTransform(1,0,0,1,0,0); - this.context.clearRect(0, 0, this.width, this.height) - this.renderDisplayObject(stage); - //as - - // run interaction! - if(stage.interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - - // remove frame updates.. - if(PIXI.Texture.frameUpdates.length > 0) - { - PIXI.Texture.frameUpdates = []; - } - - -} - -/** - * resizes the canvas view to the specified width and height - * - * @method resize - * @param width {Number} the new width of the canvas view - * @param height {Number} the new height of the canvas view - */ -PIXI.CanvasRenderer.prototype.resize = function(width, height) -{ - this.width = width; - this.height = height; - - this.view.width = width; - this.view.height = height; -} - -/** - * Renders a display object - * - * @method renderDisplayObject - * @param displayObject {DisplayObject} The displayObject to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) -{ - // no loger recurrsive! - var transform; - var context = this.context; - - context.globalCompositeOperation = 'source-over'; - - // one the display object hits this. we can break the loop - var testObject = displayObject.last._iNext; - displayObject = displayObject.first; - - do - { - transform = displayObject.worldTransform; - - if(!displayObject.visible) - { - displayObject = displayObject.last._iNext; - continue; - } - - if(!displayObject.renderable) - { - displayObject = displayObject._iNext; - continue; - } - - if(displayObject instanceof PIXI.Sprite) - { - - var frame = displayObject.texture.frame; - - if(frame && frame.width && frame.height) - { - context.globalAlpha = displayObject.worldAlpha; - - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); - - context.drawImage(displayObject.texture.baseTexture.source, - frame.x, - frame.y, - frame.width, - frame.height, - (displayObject.anchor.x) * -frame.width, - (displayObject.anchor.y) * -frame.height, - frame.width, - frame.height); - } - } - else if(displayObject instanceof PIXI.Strip) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - this.renderStrip(displayObject); - } - else if(displayObject instanceof PIXI.TilingSprite) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - this.renderTilingSprite(displayObject); - } - else if(displayObject instanceof PIXI.CustomRenderable) - { - displayObject.renderCanvas(this); - } - else if(displayObject instanceof PIXI.Graphics) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - PIXI.CanvasGraphics.renderGraphics(displayObject, context); - } - else if(displayObject instanceof PIXI.FilterBlock) - { - if(PIXI.FilterBlock.data instanceof PIXI.Graphics) - { - if(displayObject.open) - { - context.save(); - - var cacheAlpha = displayObject.mask.alpha; - var maskTransform = displayObject.mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - displayObject.mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); - context.clip(); - - displayObject.mask.worldAlpha = cacheAlpha; - } - else - { - context.restore(); - } - } - else - { - // only masks supported right now! - } - } - // count++ - displayObject = displayObject._iNext; - - - } - while(displayObject != testObject) - - -} - -/** - * Renders a flat strip - * - * @method renderStripFlat - * @param strip {Strip} The Strip to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip) -{ - var context = this.context; - var verticies = strip.verticies; - var uvs = strip.uvs; - - var length = verticies.length/2; - this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - - // draw some triangles! - var index = i*2; - - var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; - var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - }; - - context.fillStyle = "#FF0000"; - context.fill(); - context.closePath(); -} - -/** - * Renders a tiling sprite - * - * @method renderTilingSprite - * @param sprite {TilingSprite} The tilingsprite to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) -{ - var context = this.context; - - context.globalAlpha = sprite.worldAlpha; - - if(!sprite.__tilePattern) sprite.__tilePattern = context.createPattern(sprite.texture.baseTexture.source, "repeat"); - - context.beginPath(); - - var tilePosition = sprite.tilePosition; - var tileScale = sprite.tileScale; - - // offset - context.scale(tileScale.x,tileScale.y); - context.translate(tilePosition.x, tilePosition.y); - - context.fillStyle = sprite.__tilePattern; - context.fillRect(-tilePosition.x,-tilePosition.y,sprite.width / tileScale.x, sprite.height / tileScale.y); - - context.scale(1/tileScale.x, 1/tileScale.y); - context.translate(-tilePosition.x, -tilePosition.y); - - context.closePath(); -} - -/** - * Renders a strip - * - * @method renderStrip - * @param strip {Strip} The Strip to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderStrip = function(strip) -{ - var context = this.context; - - // draw triangles!! - var verticies = strip.verticies; - var uvs = strip.uvs; - - var length = verticies.length/2; - this.count++; - for (var i=1; i < length-2; i++) - { - - // draw some triangles! - var index = i*2; - - var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; - var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - - var u0 = uvs[index] * strip.texture.width, u1 = uvs[index+2] * strip.texture.width, u2 = uvs[index+4]* strip.texture.width; - var v0 = uvs[index+1]* strip.texture.height, v1 = uvs[index+3] * strip.texture.height, v2 = uvs[index+5]* strip.texture.height; - - - 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 delta_a = x0*v1 + v0*x2 + x1*v2 - v1*x2 - v0*x1 - x0*v2; - var delta_b = u0*x1 + x0*u2 + u1*x2 - x1*u2 - x0*u1 - u0*x2; - var delta_c = u0*v1*x2 + v0*x1*u2 + x0*u1*v2 - x0*v1*u2 - v0*u1*x2 - u0*x1*v2; - var delta_d = y0*v1 + v0*y2 + y1*v2 - v1*y2 - v0*y1 - y0*v2; - var delta_e = u0*y1 + y0*u2 + u1*y2 - y1*u2 - y0*u1 - u0*y2; - var delta_f = u0*v1*y2 + v0*y1*u2 + y0*u1*v2 - y0*v1*u2 - v0*u1*y2 - u0*y1*v2; - - - - - context.transform(delta_a/delta, delta_d/delta, - delta_b/delta, delta_e/delta, - delta_c/delta, delta_f/delta); - - context.drawImage(strip.texture.baseTexture.source, 0, 0); - context.restore(); - }; - -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * A set of functions used by the canvas renderer to draw the primitive graphics data - * - * @class CanvasGraphics - */ -PIXI.CanvasGraphics = function() -{ - -} - - -/* - * Renders the graphics object - * - * @static - * @private - * @method renderGraphics - * @param graphics {Graphics} - * @param context {Context2D} - */ -PIXI.CanvasGraphics.renderGraphics = function(graphics, context) -{ - var worldAlpha = graphics.worldAlpha; - - for (var i=0; i < graphics.graphicsData.length; i++) - { - var data = graphics.graphicsData[i]; - var points = data.points; - - context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); - - context.lineWidth = data.lineWidth; - - if(data.type == PIXI.Graphics.POLY) - { - context.beginPath(); - - context.moveTo(points[0], points[1]); - - for (var j=1; j < points.length/2; j++) - { - context.lineTo(points[j * 2], points[j * 2 + 1]); - } - - // if the first and last point are the same close the path - much neater :) - if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) - { - context.closePath(); - } - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - else if(data.type == PIXI.Graphics.RECT) - { - - if(data.fillColor || data.fillColor === 0) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fillRect(points[0], points[1], points[2], points[3]); - - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.strokeRect(points[0], points[1], points[2], points[3]); - } - - } - else if(data.type == PIXI.Graphics.CIRC) - { - // TODO - need to be Undefined! - context.beginPath(); - context.arc(points[0], points[1], points[2],0,2*Math.PI); - context.closePath(); - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - else if(data.type == PIXI.Graphics.ELIP) - { - - // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - - var elipseData = data.points; - - var w = elipseData[2] * 2; - var h = elipseData[3] * 2; - - var x = elipseData[0] - w/2; - var y = elipseData[1] - h/2; - - context.beginPath(); - - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - - context.moveTo(x, ym); - context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - - context.closePath(); - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - - }; -} - -/* - * Renders a graphics mask - * - * @static - * @private - * @method renderGraphicsMask - * @param graphics {Graphics} - * @param context {Context2D} - */ -PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) -{ - var worldAlpha = graphics.worldAlpha; - - var len = graphics.graphicsData.length; - if(len > 1) - { - len = 1; - console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") - } - - for (var i=0; i < 1; i++) - { - var data = graphics.graphicsData[i]; - var points = data.points; - - if(data.type == PIXI.Graphics.POLY) - { - context.beginPath(); - context.moveTo(points[0], points[1]); - - for (var j=1; j < points.length/2; j++) - { - context.lineTo(points[j * 2], points[j * 2 + 1]); - } - - // if the first and last point are the same close the path - much neater :) - if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) - { - context.closePath(); - } - - } - else if(data.type == PIXI.Graphics.RECT) - { - context.beginPath(); - context.rect(points[0], points[1], points[2], points[3]); - context.closePath(); - } - else if(data.type == PIXI.Graphics.CIRC) - { - // TODO - need to be Undefined! - context.beginPath(); - context.arc(points[0], points[1], points[2],0,2*Math.PI); - context.closePath(); - } - else if(data.type == PIXI.Graphics.ELIP) - { - - // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - var elipseData = data.points; - - var w = elipseData[2] * 2; - var h = elipseData[3] * 2; - - var x = elipseData[0] - w/2; - var y = elipseData[1] - h/2; - - context.beginPath(); - - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - - context.moveTo(x, ym); - context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - context.closePath(); - } - - - }; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. - * It is important to know that with the webGL renderer only simple polys can be filled at this stage - * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png - * - * @class Graphics - * @extends DisplayObjectContainer - * @constructor - */ -PIXI.Graphics = function() -{ - PIXI.DisplayObjectContainer.call( this ); - - this.renderable = true; - - /** - * The alpha of the fill of this graphics object - * - * @property fillAlpha - * @type Number - */ - this.fillAlpha = 1; - - /** - * The width of any lines drawn - * - * @property lineWidth - * @type Number - */ - this.lineWidth = 0; - - /** - * The color of any lines drawn - * - * @property lineColor - * @type String - */ - this.lineColor = "black"; - - /** - * Graphics data - * - * @property graphicsData - * @type Array - * @private - */ - this.graphicsData = []; - - /** - * Current path - * - * @property currentPath - * @type Object - * @private - */ - this.currentPath = {points:[]}; -} - -// constructor -PIXI.Graphics.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Graphics.prototype.constructor = PIXI.Graphics; - -/** - * Specifies a line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method. - * - * @method lineStyle - * @param lineWidth {Number} width of the line to draw, will update the object's stored style - * @param color {Number} color of the line to draw, will update the object's stored style - * @param alpha {Number} alpha of the line to draw, will update the object's stored style - */ -PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.lineWidth = lineWidth || 0; - this.lineColor = color || 0; - this.lineAlpha = (alpha == undefined) ? 1 : alpha; - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - - this.graphicsData.push(this.currentPath); -} - -/** - * Moves the current drawing position to (x, y). - * - * @method moveTo - * @param x {Number} the X coord to move to - * @param y {Number} the Y coord to move to - */ -PIXI.Graphics.prototype.moveTo = function(x, y) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - - this.currentPath.points.push(x, y); - - this.graphicsData.push(this.currentPath); -} - -/** - * Draws a line using the current line style from the current drawing position to (x, y); - * the current drawing position is then set to (x, y). - * - * @method lineTo - * @param x {Number} the X coord to draw to - * @param y {Number} the Y coord to draw to - */ -PIXI.Graphics.prototype.lineTo = function(x, y) -{ - this.currentPath.points.push(x, y); - this.dirty = true; -} - -/** - * Specifies a simple one-color fill that subsequent calls to other Graphics methods - * (such as lineTo() or drawCircle()) use when drawing. - * - * @method beginFill - * @param color {uint} the color of the fill - * @param alpha {Number} the alpha - */ -PIXI.Graphics.prototype.beginFill = function(color, alpha) -{ - this.filling = true; - this.fillColor = color || 0; - this.fillAlpha = (alpha == undefined) ? 1 : alpha; -} - -/** - * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. - * - * @method endFill - */ -PIXI.Graphics.prototype.endFill = function() -{ - this.filling = false; - this.fillColor = null; - this.fillAlpha = 1; -} - -/** - * @method drawRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - */ -PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, width, height], type:PIXI.Graphics.RECT}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Draws a circle. - * - * @method drawCircle - * @param x {Number} The X coord of the center of the circle - * @param y {Number} The Y coord of the center of the circle - * @param radius {Number} The radius of the circle - */ -PIXI.Graphics.prototype.drawCircle = function( x, y, radius) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Draws an elipse. - * - * @method drawElipse - * @param x {Number} - * @param y {Number} - * @param width {Number} - * @param height {Number} - */ -PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, width, height], type:PIXI.Graphics.ELIP}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @method clear - */ -PIXI.Graphics.prototype.clear = function() -{ - this.lineWidth = 0; - this.filling = false; - - this.dirty = true; - this.clearDirty = true; - this.graphicsData = []; -} - -// SOME TYPES: -PIXI.Graphics.POLY = 0; -PIXI.Graphics.RECT = 1; -PIXI.Graphics.CIRC = 2; -PIXI.Graphics.ELIP = 3; - -/** - * @author Mat Groves http://matgroves.com/ - */ - -PIXI.Strip = function(texture, width, height) -{ - PIXI.DisplayObjectContainer.call( this ); - this.texture = texture; - this.blendMode = PIXI.blendModes.NORMAL; - - try - { - this.uvs = new Float32Array([0, 1, - 1, 1, - 1, 0, 0,1]); - - this.verticies = new Float32Array([0, 0, - 0,0, - 0,0, 0, - 0, 0]); - - this.colors = new Float32Array([1, 1, 1, 1]); - - this.indices = new Uint16Array([0, 1, 2, 3]); - } - catch(error) - { - this.uvs = [0, 1, - 1, 1, - 1, 0, 0,1]; - - this.verticies = [0, 0, - 0,0, - 0,0, 0, - 0, 0]; - - this.colors = [1, 1, 1, 1]; - - this.indices = [0, 1, 2, 3]; - } - - - /* - this.uvs = new Float32Array() - this.verticies = new Float32Array() - this.colors = new Float32Array() - this.indices = new Uint16Array() -*/ - this.width = width; - this.height = height; - - // load the texture! - if(texture.baseTexture.hasLoaded) - { - this.width = this.texture.frame.width; - this.height = this.texture.frame.height; - this.updateFrame = true; - } - else - { - this.onTextureUpdateBind = this.onTextureUpdate.bind(this); - this.texture.addEventListener( 'update', this.onTextureUpdateBind ); - } - - this.renderable = true; -} - -// constructor -PIXI.Strip.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Strip.prototype.constructor = PIXI.Strip; - -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; -} - -PIXI.Strip.prototype.onTextureUpdate = function(event) -{ - this.updateFrame = true; -} -// some helper functions.. - - -/** - * @author Mat Groves http://matgroves.com/ - */ - - -PIXI.Rope = function(texture, points) -{ - PIXI.Strip.call( this, texture ); - this.points = points; - - try - { - this.verticies = new Float32Array( points.length * 4); - this.uvs = new Float32Array( points.length * 4); - this.colors = new Float32Array( points.length * 2); - this.indices = new Uint16Array( points.length * 2); - } - catch(error) - { - this.verticies = verticies - - this.uvs = uvs - this.colors = colors - this.indices = indices - } - - this.refresh(); -} - - -// constructor -PIXI.Rope.prototype = Object.create( PIXI.Strip.prototype ); -PIXI.Rope.prototype.constructor = PIXI.Rope; - -PIXI.Rope.prototype.refresh = function() -{ - var points = this.points; - if(points.length < 1)return; - - var uvs = this.uvs - var indices = this.indices; - var colors = this.colors; - - var lastPoint = points[0]; - var nextPoint; - var perp = {x:0, y:0}; - var point = points[0]; - - this.count-=0.2; - - - uvs[0] = 0 - uvs[1] = 1 - uvs[2] = 0 - uvs[3] = 1 - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length; - - for (var i = 1; i < total; i++) - { - - var point = points[i]; - var index = i * 4; - // time to do some smart drawing! - var 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; - } -} - -PIXI.Rope.prototype.updateTransform = function() -{ - - var points = this.points; - if(points.length < 1)return; - - var verticies = this.verticies - - var lastPoint = points[0]; - var nextPoint; - var perp = {x:0, y:0}; - var point = points[0]; - - this.count-=0.2; - - verticies[0] = point.x + perp.x - verticies[1] = point.y + perp.y //+ 200 - verticies[2] = point.x - perp.x - verticies[3] = point.y - perp.y//+200 - // time to do some smart drawing! - - var total = points.length; - - for (var i = 1; i < total; i++) - { - - var point = points[i]; - var 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; - - var ratio = (1 - (i / (total-1))) * 10; - if(ratio > 1)ratio = 1; - - var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); - var 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; - - verticies[index] = point.x + perp.x - verticies[index+1] = point.y + perp.y - verticies[index+2] = point.x - perp.x - verticies[index+3] = point.y - perp.y - - lastPoint = point; - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); -} - -PIXI.Rope.prototype.setTexture = function(texture) -{ - // stop current texture - this.texture = texture; - this.updateFrame = true; -} - - - - - -/** - * @author Mat Groves http://matgroves.com/ - */ - -/** - * A tiling sprite is a fast way of rendering a tiling image - * - * @class TilingSprite - * @extends DisplayObjectContainer - * @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.DisplayObjectContainer.call( this ); - - /** - * The texture that the sprite is using - * - * @property texture - * @type Texture - */ - this.texture = texture; - - /** - * The width of the tiling sprite - * - * @property width - * @type Number - */ - this.width = width; - - /** - * The height of the tiling sprite - * - * @property height - * @type Number - */ - this.height = height; - - /** - * The scaling of the image that is being tiled - * - * @property tileScale - * @type Point - */ - this.tileScale = 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); - - this.renderable = true; - - this.blendMode = PIXI.blendModes.NORMAL -} - -// constructor -PIXI.TilingSprite.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite; - -/** - * Sets the texture of the tiling sprite - * - * @method setTexture - * @param texture {Texture} The PIXI texture that is displayed by the sprite - */ -PIXI.TilingSprite.prototype.setTexture = function(texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - - // stop current texture - this.texture = texture; - this.updateFrame = true; -} - -/** - * When the texture is updated, this event will fire to update the frame - * - * @method onTextureUpdate - * @param event - * @private - */ -PIXI.TilingSprite.prototype.onTextureUpdate = function(event) -{ - this.updateFrame = true; -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * - * Awesome JS run time provided by EsotericSoftware - * https://github.com/EsotericSoftware/spine-runtimes - * - */ - -/** - * 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)) { - continue; - } - var spriteName = attachment.rendererObject.name; - var sprite = this.createSprite(slot, attachment.rendererObject); - slot.currentSprite = sprite; - slot.currentSpriteName = spriteName; - slotContainer.addChild(sprite); - } -}; - -PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); -PIXI.Spine.prototype.constructor = PIXI.Spine; - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.Spine.prototype.updateTransform = function () { - this.lastTime = this.lastTime || Date.now(); - var timeDelta = (Date.now() - this.lastTime) * 0.001; - this.lastTime = Date.now(); - this.state.update(timeDelta); - 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 instanceof spine.RegionAttachment)) { - slotContainer.visible = false; - continue; - } - - 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.rendererObject); - slotContainer.addChild(sprite); - } - slot.currentSprite = slot.sprites[spriteName]; - slot.currentSpriteName = spriteName; - } - } - slotContainer.visible = true; - - 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 * Math.PI / 180); - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -}; - - -PIXI.Spine.prototype.createSprite = function (slot, descriptor) { - var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); - sprite.scale = descriptor.scale; - sprite.rotation = descriptor.rotation; - sprite.anchor.x = sprite.anchor.y = 0.5; - - slot.sprites = slot.sprites || {}; - slot.sprites[descriptor.name] = sprite; - return sprite; -}; - -/* - * Awesome JS run time provided by EsotericSoftware - * - * https://github.com/EsotericSoftware/spine-runtimes - * - */ - -var spine = {}; - -spine.BoneData = function (name, parent) { - this.name = name; - this.parent = parent; -}; -spine.BoneData.prototype = { - length: 0, - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1 -}; - -spine.SlotData = function (name, boneData) { - this.name = name; - this.boneData = boneData; -}; -spine.SlotData.prototype = { - r: 1, g: 1, b: 1, a: 1, - attachmentName: null -}; - -spine.Bone = function (boneData, parent) { - this.data = boneData; - this.parent = parent; - this.setToSetupPose(); -}; -spine.Bone.yDown = false; -spine.Bone.prototype = { - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1, - m00: 0, m01: 0, worldX: 0, // a b x - m10: 0, m11: 0, worldY: 0, // c d y - worldRotation: 0, - worldScaleX: 1, worldScaleY: 1, - updateWorldTransform: function (flipX, flipY) { - var parent = this.parent; - if (parent != null) { - this.worldX = this.x * parent.m00 + this.y * parent.m01 + parent.worldX; - this.worldY = this.x * parent.m10 + this.y * parent.m11 + parent.worldY; - this.worldScaleX = parent.worldScaleX * this.scaleX; - this.worldScaleY = parent.worldScaleY * this.scaleY; - this.worldRotation = parent.worldRotation + this.rotation; - } else { - this.worldX = this.x; - this.worldY = this.y; - this.worldScaleX = this.scaleX; - this.worldScaleY = this.scaleY; - this.worldRotation = this.rotation; - } - var radians = this.worldRotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - this.m00 = cos * this.worldScaleX; - this.m10 = sin * this.worldScaleX; - this.m01 = -sin * this.worldScaleY; - this.m11 = cos * this.worldScaleY; - if (flipX) { - this.m00 = -this.m00; - this.m01 = -this.m01; - } - if (flipY) { - this.m10 = -this.m10; - this.m11 = -this.m11; - } - if (spine.Bone.yDown) { - this.m10 = -this.m10; - this.m11 = -this.m11; - } - }, - setToSetupPose: function () { - var data = this.data; - this.x = data.x; - this.y = data.y; - this.rotation = data.rotation; - this.scaleX = data.scaleX; - this.scaleY = data.scaleY; - } -}; - -spine.Slot = function (slotData, skeleton, bone) { - this.data = slotData; - this.skeleton = skeleton; - this.bone = bone; - this.setToSetupPose(); -}; -spine.Slot.prototype = { - r: 1, g: 1, b: 1, a: 1, - _attachmentTime: 0, - attachment: null, - setAttachment: function (attachment) { - this.attachment = attachment; - this._attachmentTime = this.skeleton.time; - }, - setAttachmentTime: function (time) { - this._attachmentTime = this.skeleton.time - time; - }, - getAttachmentTime: function () { - return this.skeleton.time - this._attachmentTime; - }, - setToSetupPose: function () { - var data = this.data; - this.r = data.r; - this.g = data.g; - this.b = data.b; - this.a = data.a; - - var slotDatas = this.skeleton.data.slots; - for (var i = 0, n = slotDatas.length; i < n; i++) { - if (slotDatas[i] == data) { - this.setAttachment(!data.attachmentName ? null : this.skeleton.getAttachmentBySlotIndex(i, data.attachmentName)); - break; - } - } - } -}; - -spine.Skin = function (name) { - this.name = name; - this.attachments = {}; -}; -spine.Skin.prototype = { - addAttachment: function (slotIndex, name, attachment) { - this.attachments[slotIndex + ":" + name] = attachment; - }, - getAttachment: function (slotIndex, name) { - return this.attachments[slotIndex + ":" + name]; - }, - _attachAll: function (skeleton, oldSkin) { - for (var key in oldSkin.attachments) { - var colon = key.indexOf(":"); - var slotIndex = parseInt(key.substring(0, colon)); - var name = key.substring(colon + 1); - var slot = skeleton.slots[slotIndex]; - if (slot.attachment && slot.attachment.name == name) { - var attachment = this.getAttachment(slotIndex, name); - if (attachment) slot.setAttachment(attachment); - } - } - } -}; - -spine.Animation = function (name, timelines, duration) { - this.name = name; - this.timelines = timelines; - this.duration = duration; -}; -spine.Animation.prototype = { - apply: function (skeleton, time, loop) { - if (loop && this.duration != 0) time %= this.duration; - var timelines = this.timelines; - for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, time, 1); - }, - mix: function (skeleton, time, loop, alpha) { - if (loop && this.duration != 0) time %= this.duration; - var timelines = this.timelines; - for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, time, alpha); - } -}; - -spine.binarySearch = function (values, target, step) { - var low = 0; - var high = Math.floor(values.length / step) - 2; - if (high == 0) return step; - var current = high >>> 1; - while (true) { - if (values[(current + 1) * step] <= target) - low = current + 1; - else - high = current; - if (low == high) return (low + 1) * step; - current = (low + high) >>> 1; - } -}; -spine.linearSearch = function (values, target, step) { - for (var i = 0, last = values.length - step; i <= last; i += step) - if (values[i] > target) return i; - return -1; -}; - -spine.Curves = function (frameCount) { - this.curves = []; // dfx, dfy, ddfx, ddfy, dddfx, dddfy, ... - this.curves.length = (frameCount - 1) * 6; -}; -spine.Curves.prototype = { - setLinear: function (frameIndex) { - this.curves[frameIndex * 6] = 0/*LINEAR*/; - }, - setStepped: function (frameIndex) { - this.curves[frameIndex * 6] = -1/*STEPPED*/; - }, - /** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next. - * cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of - * the difference between the keyframe's values. */ - setCurve: function (frameIndex, cx1, cy1, cx2, cy2) { - var subdiv_step = 1 / 10/*BEZIER_SEGMENTS*/; - var subdiv_step2 = subdiv_step * subdiv_step; - var subdiv_step3 = subdiv_step2 * subdiv_step; - var pre1 = 3 * subdiv_step; - var pre2 = 3 * subdiv_step2; - var pre4 = 6 * subdiv_step2; - var pre5 = 6 * subdiv_step3; - var tmp1x = -cx1 * 2 + cx2; - var tmp1y = -cy1 * 2 + cy2; - var tmp2x = (cx1 - cx2) * 3 + 1; - var tmp2y = (cy1 - cy2) * 3 + 1; - var i = frameIndex * 6; - var curves = this.curves; - curves[i] = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; - curves[i + 1] = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; - curves[i + 2] = tmp1x * pre4 + tmp2x * pre5; - curves[i + 3] = tmp1y * pre4 + tmp2y * pre5; - curves[i + 4] = tmp2x * pre5; - curves[i + 5] = tmp2y * pre5; - }, - getCurvePercent: function (frameIndex, percent) { - percent = percent < 0 ? 0 : (percent > 1 ? 1 : percent); - var curveIndex = frameIndex * 6; - var curves = this.curves; - var dfx = curves[curveIndex]; - if (!dfx/*LINEAR*/) return percent; - if (dfx == -1/*STEPPED*/) return 0; - var dfy = curves[curveIndex + 1]; - var ddfx = curves[curveIndex + 2]; - var ddfy = curves[curveIndex + 3]; - var dddfx = curves[curveIndex + 4]; - var dddfy = curves[curveIndex + 5]; - var x = dfx, y = dfy; - var i = 10/*BEZIER_SEGMENTS*/ - 2; - while (true) { - if (x >= percent) { - var lastX = x - dfx; - var lastY = y - dfy; - return lastY + (y - lastY) * (percent - lastX) / (x - lastX); - } - if (i == 0) break; - i--; - dfx += ddfx; - dfy += ddfy; - ddfx += dddfx; - ddfy += dddfy; - x += dfx; - y += dfy; - } - return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1. - } -}; - -spine.RotateTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, angle, ... - this.frames.length = frameCount * 2; -}; -spine.RotateTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 2; - }, - setFrame: function (frameIndex, time, angle) { - frameIndex *= 2; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = angle; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 2]) { // Time is after last frame. - var amount = bone.data.rotation + frames[frames.length - 1] - bone.rotation; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - bone.rotation += amount * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 2); - var lastFrameValue = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex - 2/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent); - - var amount = frames[frameIndex + 1/*FRAME_VALUE*/] - lastFrameValue; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - amount = bone.data.rotation + (lastFrameValue + amount * percent) - bone.rotation; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - bone.rotation += amount * alpha; - } -}; - -spine.TranslateTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, x, y, ... - this.frames.length = frameCount * 3; -}; -spine.TranslateTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 3; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 3; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = x; - this.frames[frameIndex + 2] = y; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 3]) { // Time is after last frame. - bone.x += (bone.data.x + frames[frames.length - 2] - bone.x) * alpha; - bone.y += (bone.data.y + frames[frames.length - 1] - bone.y) * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 3); - var lastFrameX = frames[frameIndex - 2]; - var lastFrameY = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); - - bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; - bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; - } -}; - -spine.ScaleTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, x, y, ... - this.frames.length = frameCount * 3; -}; -spine.ScaleTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 3; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 3; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = x; - this.frames[frameIndex + 2] = y; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 3]) { // Time is after last frame. - bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 3); - var lastFrameX = frames[frameIndex - 2]; - var lastFrameY = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); - - bone.scaleX += (bone.data.scaleX - 1 + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - 1 + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.scaleY) * alpha; - } -}; - -spine.ColorTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, r, g, b, a, ... - this.frames.length = frameCount * 5; -}; -spine.ColorTimeline.prototype = { - slotIndex: 0, - getFrameCount: function () { - return this.frames.length / 2; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 5; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = r; - this.frames[frameIndex + 2] = g; - this.frames[frameIndex + 3] = b; - this.frames[frameIndex + 4] = a; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var slot = skeleton.slots[this.slotIndex]; - - if (time >= frames[frames.length - 5]) { // Time is after last frame. - var i = frames.length - 1; - slot.r = frames[i - 3]; - slot.g = frames[i - 2]; - slot.b = frames[i - 1]; - slot.a = frames[i]; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 5); - var lastFrameR = frames[frameIndex - 4]; - var lastFrameG = frames[frameIndex - 3]; - var lastFrameB = frames[frameIndex - 2]; - var lastFrameA = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex - 5/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent); - - var r = lastFrameR + (frames[frameIndex + 1/*FRAME_R*/] - lastFrameR) * percent; - var g = lastFrameG + (frames[frameIndex + 2/*FRAME_G*/] - lastFrameG) * percent; - var b = lastFrameB + (frames[frameIndex + 3/*FRAME_B*/] - lastFrameB) * percent; - var a = lastFrameA + (frames[frameIndex + 4/*FRAME_A*/] - lastFrameA) * percent; - if (alpha < 1) { - slot.r += (r - slot.r) * alpha; - slot.g += (g - slot.g) * alpha; - slot.b += (b - slot.b) * alpha; - slot.a += (a - slot.a) * alpha; - } else { - slot.r = r; - slot.g = g; - slot.b = b; - slot.a = a; - } - } -}; - -spine.AttachmentTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, ... - this.frames.length = frameCount; - this.attachmentNames = []; // time, ... - this.attachmentNames.length = frameCount; -}; -spine.AttachmentTimeline.prototype = { - slotIndex: 0, - getFrameCount: function () { - return this.frames.length; - }, - setFrame: function (frameIndex, time, attachmentName) { - this.frames[frameIndex] = time; - this.attachmentNames[frameIndex] = attachmentName; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var frameIndex; - if (time >= frames[frames.length - 1]) // Time is after last frame. - frameIndex = frames.length - 1; - else - frameIndex = spine.binarySearch(frames, time, 1) - 1; - - var attachmentName = this.attachmentNames[frameIndex]; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); - } -}; - -spine.SkeletonData = function () { - this.bones = []; - this.slots = []; - this.skins = []; - this.animations = []; -}; -spine.SkeletonData.prototype = { - defaultSkin: null, - /** @return May be null. */ - findBone: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].name == boneName) return bones[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findBoneIndex: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].name == boneName) return i; - return -1; - }, - /** @return May be null. */ - findSlot: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) { - if (slots[i].name == slotName) return slot[i]; - } - return null; - }, - /** @return -1 if the bone was not found. */ - findSlotIndex: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].name == slotName) return i; - return -1; - }, - /** @return May be null. */ - findSkin: function (skinName) { - var skins = this.skins; - for (var i = 0, n = skins.length; i < n; i++) - if (skins[i].name == skinName) return skins[i]; - return null; - }, - /** @return May be null. */ - findAnimation: function (animationName) { - var animations = this.animations; - for (var i = 0, n = animations.length; i < n; i++) - if (animations[i].name == animationName) return animations[i]; - return null; - } -}; - -spine.Skeleton = function (skeletonData) { - this.data = skeletonData; - - this.bones = []; - for (var i = 0, n = skeletonData.bones.length; i < n; i++) { - var boneData = skeletonData.bones[i]; - var parent = !boneData.parent ? null : this.bones[skeletonData.bones.indexOf(boneData.parent)]; - this.bones.push(new spine.Bone(boneData, parent)); - } - - this.slots = []; - this.drawOrder = []; - for (var i = 0, n = skeletonData.slots.length; i < n; i++) { - var slotData = skeletonData.slots[i]; - var bone = this.bones[skeletonData.bones.indexOf(slotData.boneData)]; - var slot = new spine.Slot(slotData, this, bone); - this.slots.push(slot); - this.drawOrder.push(slot); - } -}; -spine.Skeleton.prototype = { - x: 0, y: 0, - skin: null, - r: 1, g: 1, b: 1, a: 1, - time: 0, - flipX: false, flipY: false, - /** Updates the world transform for each bone. */ - updateWorldTransform: function () { - var flipX = this.flipX; - var flipY = this.flipY; - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - bones[i].updateWorldTransform(flipX, flipY); - }, - /** Sets the bones and slots to their setup pose values. */ - setToSetupPose: function () { - this.setBonesToSetupPose(); - this.setSlotsToSetupPose(); - }, - setBonesToSetupPose: function () { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - bones[i].setToSetupPose(); - }, - setSlotsToSetupPose: function () { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - slots[i].setToSetupPose(i); - }, - /** @return May return null. */ - getRootBone: function () { - return this.bones.length == 0 ? null : this.bones[0]; - }, - /** @return May be null. */ - findBone: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].data.name == boneName) return bones[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findBoneIndex: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].data.name == boneName) return i; - return -1; - }, - /** @return May be null. */ - findSlot: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].data.name == slotName) return slots[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findSlotIndex: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].data.name == slotName) return i; - return -1; - }, - setSkinByName: function (skinName) { - var skin = this.data.findSkin(skinName); - if (!skin) throw "Skin not found: " + skinName; - this.setSkin(skin); - }, - /** Sets the skin used to look up attachments not found in the {@link SkeletonData#getDefaultSkin() default skin}. Attachments - * from the new skin are attached if the corresponding attachment from the old skin was attached. - * @param newSkin May be null. */ - setSkin: function (newSkin) { - if (this.skin && newSkin) newSkin._attachAll(this, this.skin); - this.skin = newSkin; - }, - /** @return May be null. */ - getAttachmentBySlotName: function (slotName, attachmentName) { - return this.getAttachmentBySlotIndex(this.data.findSlotIndex(slotName), attachmentName); - }, - /** @return May be null. */ - getAttachmentBySlotIndex: function (slotIndex, attachmentName) { - if (this.skin) { - var attachment = this.skin.getAttachment(slotIndex, attachmentName); - if (attachment) return attachment; - } - if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); - return null; - }, - /** @param attachmentName May be null. */ - setAttachment: function (slotName, attachmentName) { - var slots = this.slots; - for (var i = 0, n = slots.size; i < n; i++) { - var slot = slots[i]; - if (slot.data.name == slotName) { - var attachment = null; - if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); - if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; - } - slot.setAttachment(attachment); - return; - } - } - throw "Slot not found: " + slotName; - }, - update: function (delta) { - time += delta; - } -}; - -spine.AttachmentType = { - region: 0 -}; - -spine.RegionAttachment = function () { - this.offset = []; - this.offset.length = 8; - this.uvs = []; - this.uvs.length = 8; -}; -spine.RegionAttachment.prototype = { - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1, - width: 0, height: 0, - rendererObject: null, - regionOffsetX: 0, regionOffsetY: 0, - regionWidth: 0, regionHeight: 0, - regionOriginalWidth: 0, regionOriginalHeight: 0, - setUVs: function (u, v, u2, v2, rotate) { - var uvs = this.uvs; - if (rotate) { - uvs[2/*X2*/] = u; - uvs[3/*Y2*/] = v2; - uvs[4/*X3*/] = u; - uvs[5/*Y3*/] = v; - uvs[6/*X4*/] = u2; - uvs[7/*Y4*/] = v; - uvs[0/*X1*/] = u2; - uvs[1/*Y1*/] = v2; - } else { - uvs[0/*X1*/] = u; - uvs[1/*Y1*/] = v2; - uvs[2/*X2*/] = u; - uvs[3/*Y2*/] = v; - uvs[4/*X3*/] = u2; - uvs[5/*Y3*/] = v; - uvs[6/*X4*/] = u2; - uvs[7/*Y4*/] = v2; - } - }, - updateOffset: function () { - var regionScaleX = this.width / this.regionOriginalWidth * this.scaleX; - var regionScaleY = this.height / this.regionOriginalHeight * this.scaleY; - var localX = -this.width / 2 * this.scaleX + this.regionOffsetX * regionScaleX; - var localY = -this.height / 2 * this.scaleY + this.regionOffsetY * regionScaleY; - var localX2 = localX + this.regionWidth * regionScaleX; - var localY2 = localY + this.regionHeight * regionScaleY; - var radians = this.rotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - var localXCos = localX * cos + this.x; - var localXSin = localX * sin; - var localYCos = localY * cos + this.y; - var localYSin = localY * sin; - var localX2Cos = localX2 * cos + this.x; - var localX2Sin = localX2 * sin; - var localY2Cos = localY2 * cos + this.y; - var localY2Sin = localY2 * sin; - var offset = this.offset; - offset[0/*X1*/] = localXCos - localYSin; - offset[1/*Y1*/] = localYCos + localXSin; - offset[2/*X2*/] = localXCos - localY2Sin; - offset[3/*Y2*/] = localY2Cos + localXSin; - offset[4/*X3*/] = localX2Cos - localY2Sin; - offset[5/*Y3*/] = localY2Cos + localX2Sin; - offset[6/*X4*/] = localX2Cos - localYSin; - offset[7/*Y4*/] = localYCos + localX2Sin; - }, - computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; - y += bone.worldY; - var m00 = bone.m00; - var m01 = bone.m01; - var m10 = bone.m10; - var m11 = bone.m11; - var offset = this.offset; - vertices[0/*X1*/] = offset[0/*X1*/] * m00 + offset[1/*Y1*/] * m01 + x; - vertices[1/*Y1*/] = offset[0/*X1*/] * m10 + offset[1/*Y1*/] * m11 + y; - vertices[2/*X2*/] = offset[2/*X2*/] * m00 + offset[3/*Y2*/] * m01 + x; - vertices[3/*Y2*/] = offset[2/*X2*/] * m10 + offset[3/*Y2*/] * m11 + y; - vertices[4/*X3*/] = offset[4/*X3*/] * m00 + offset[5/*X3*/] * m01 + x; - vertices[5/*X3*/] = offset[4/*X3*/] * m10 + offset[5/*X3*/] * m11 + y; - vertices[6/*X4*/] = offset[6/*X4*/] * m00 + offset[7/*Y4*/] * m01 + x; - vertices[7/*Y4*/] = offset[6/*X4*/] * m10 + offset[7/*Y4*/] * m11 + y; - } -} - -spine.AnimationStateData = function (skeletonData) { - this.skeletonData = skeletonData; - this.animationToMixTime = {}; -}; -spine.AnimationStateData.prototype = { - defaultMix: 0, - setMixByName: function (fromName, toName, duration) { - var from = this.skeletonData.findAnimation(fromName); - if (!from) throw "Animation not found: " + fromName; - var to = this.skeletonData.findAnimation(toName); - if (!to) throw "Animation not found: " + toName; - this.setMix(from, to, duration); - }, - setMix: function (from, to, duration) { - this.animationToMixTime[from.name + ":" + to.name] = duration; - }, - getMix: function (from, to) { - var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : this.defaultMix; - } -}; - -spine.AnimationState = function (stateData) { - this.data = stateData; - this.queue = []; -}; -spine.AnimationState.prototype = { - current: null, - previous: null, - currentTime: 0, - previousTime: 0, - currentLoop: false, - previousLoop: false, - mixTime: 0, - mixDuration: 0, - update: function (delta) { - this.currentTime += delta; - this.previousTime += delta; - this.mixTime += delta; - - if (this.queue.length > 0) { - var entry = this.queue[0]; - if (this.currentTime >= entry.delay) { - this._setAnimation(entry.animation, entry.loop); - this.queue.shift(); - } - } - }, - apply: function (skeleton) { - if (!this.current) return; - if (this.previous) { - this.previous.apply(skeleton, this.previousTime, this.previousLoop); - var alpha = this.mixTime / this.mixDuration; - if (alpha >= 1) { - alpha = 1; - this.previous = null; - } - this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else - this.current.apply(skeleton, this.currentTime, this.currentLoop); - }, - clearAnimation: function () { - this.previous = null; - this.current = null; - this.queue.length = 0; - }, - _setAnimation: function (animation, loop) { - this.previous = null; - if (animation && this.current) { - this.mixDuration = this.data.getMix(this.current, animation); - if (this.mixDuration > 0) { - this.mixTime = 0; - this.previous = this.current; - this.previousTime = this.currentTime; - this.previousLoop = this.currentLoop; - } - } - this.current = animation; - this.currentLoop = loop; - this.currentTime = 0; - }, - /** @see #setAnimation(Animation, Boolean) */ - setAnimationByName: function (animationName, loop) { - var animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw "Animation not found: " + animationName; - this.setAnimation(animation, loop); - }, - /** Set the current animation. Any queued animations are cleared and the current animation time is set to 0. - * @param animation May be null. */ - setAnimation: function (animation, loop) { - this.queue.length = 0; - this._setAnimation(animation, loop); - }, - /** @see #addAnimation(Animation, Boolean, Number) */ - addAnimationByName: function (animationName, loop, delay) { - var animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw "Animation not found: " + animationName; - this.addAnimation(animation, loop, delay); - }, - /** Adds an animation to be played delay seconds after the current or last queued animation. - * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */ - addAnimation: function (animation, loop, delay) { - var entry = {}; - entry.animation = animation; - entry.loop = loop; - - if (!delay || delay <= 0) { - var previousAnimation = this.queue.length == 0 ? this.current : this.queue[this.queue.length - 1].animation; - if (previousAnimation != null) - delay = previousAnimation.duration - this.data.getMix(previousAnimation, animation) + (delay || 0); - else - delay = 0; - } - entry.delay = delay; - - this.queue.push(entry); - }, - /** Returns true if no animation is set or if the current time is greater than the animation duration, regardless of looping. */ - isComplete: function () { - return !this.current || this.currentTime >= this.current.duration; - } -}; - -spine.SkeletonJson = function (attachmentLoader) { - this.attachmentLoader = attachmentLoader; -}; -spine.SkeletonJson.prototype = { - scale: 1, - readSkeletonData: function (root) { - var skeletonData = new spine.SkeletonData(); - - // Bones. - var bones = root["bones"]; - for (var i = 0, n = bones.length; i < n; i++) { - var boneMap = bones[i]; - var parent = null; - if (boneMap["parent"]) { - parent = skeletonData.findBone(boneMap["parent"]); - if (!parent) throw "Parent bone not found: " + boneMap["parent"]; - } - var boneData = new spine.BoneData(boneMap["name"], parent); - boneData.length = (boneMap["length"] || 0) * this.scale; - boneData.x = (boneMap["x"] || 0) * this.scale; - boneData.y = (boneMap["y"] || 0) * this.scale; - boneData.rotation = (boneMap["rotation"] || 0); - boneData.scaleX = boneMap["scaleX"] || 1; - boneData.scaleY = boneMap["scaleY"] || 1; - skeletonData.bones.push(boneData); - } - - // Slots. - var slots = root["slots"]; - for (var i = 0, n = slots.length; i < n; i++) { - var slotMap = slots[i]; - var boneData = skeletonData.findBone(slotMap["bone"]); - if (!boneData) throw "Slot bone not found: " + slotMap["bone"]; - var slotData = new spine.SlotData(slotMap["name"], boneData); - - var color = slotMap["color"]; - if (color) { - slotData.r = spine.SkeletonJson.toColor(color, 0); - slotData.g = spine.SkeletonJson.toColor(color, 1); - slotData.b = spine.SkeletonJson.toColor(color, 2); - slotData.a = spine.SkeletonJson.toColor(color, 3); - } - - slotData.attachmentName = slotMap["attachment"]; - - skeletonData.slots.push(slotData); - } - - // Skins. - var skins = root["skins"]; - for (var skinName in skins) { - if (!skins.hasOwnProperty(skinName)) continue; - var skinMap = skins[skinName]; - var skin = new spine.Skin(skinName); - for (var slotName in skinMap) { - if (!skinMap.hasOwnProperty(slotName)) continue; - var slotIndex = skeletonData.findSlotIndex(slotName); - var slotEntry = skinMap[slotName]; - for (var attachmentName in slotEntry) { - if (!slotEntry.hasOwnProperty(attachmentName)) continue; - var attachment = this.readAttachment(skin, attachmentName, slotEntry[attachmentName]); - if (attachment != null) skin.addAttachment(slotIndex, attachmentName, attachment); - } - } - skeletonData.skins.push(skin); - if (skin.name == "default") skeletonData.defaultSkin = skin; - } - - // Animations. - var animations = root["animations"]; - for (var animationName in animations) { - if (!animations.hasOwnProperty(animationName)) continue; - this.readAnimation(animationName, animations[animationName], skeletonData); - } - - return skeletonData; - }, - readAttachment: function (skin, name, map) { - name = map["name"] || name; - - var type = spine.AttachmentType[map["type"] || "region"]; - - if (type == spine.AttachmentType.region) { - var attachment = new spine.RegionAttachment(); - attachment.x = (map["x"] || 0) * this.scale; - attachment.y = (map["y"] || 0) * this.scale; - attachment.scaleX = map["scaleX"] || 1; - attachment.scaleY = map["scaleY"] || 1; - attachment.rotation = map["rotation"] || 0; - attachment.width = (map["width"] || 32) * this.scale; - attachment.height = (map["height"] || 32) * this.scale; - attachment.updateOffset(); - - attachment.rendererObject = {}; - attachment.rendererObject.name = name; - attachment.rendererObject.scale = {}; - attachment.rendererObject.scale.x = attachment.scaleX; - attachment.rendererObject.scale.y = attachment.scaleY; - attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; - return attachment; - } - - throw "Unknown attachment type: " + type; - }, - - readAnimation: function (name, map, skeletonData) { - var timelines = []; - var duration = 0; - - var bones = map["bones"]; - for (var boneName in bones) { - if (!bones.hasOwnProperty(boneName)) continue; - var boneIndex = skeletonData.findBoneIndex(boneName); - if (boneIndex == -1) throw "Bone not found: " + boneName; - var boneMap = bones[boneName]; - - for (var timelineName in boneMap) { - if (!boneMap.hasOwnProperty(timelineName)) continue; - var values = boneMap[timelineName]; - if (timelineName == "rotate") { - var timeline = new spine.RotateTimeline(values.length); - timeline.boneIndex = boneIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - timeline.setFrame(frameIndex, valueMap["time"], valueMap["angle"]); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 2 - 2]); - - } else if (timelineName == "translate" || timelineName == "scale") { - var timeline; - var timelineScale = 1; - if (timelineName == "scale") - timeline = new spine.ScaleTimeline(values.length); - else { - timeline = new spine.TranslateTimeline(values.length); - timelineScale = this.scale; - } - timeline.boneIndex = boneIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - var x = (valueMap["x"] || 0) * timelineScale; - var y = (valueMap["y"] || 0) * timelineScale; - timeline.setFrame(frameIndex, valueMap["time"], x, y); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - - } else - throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; - } - } - var slots = map["slots"]; - for (var slotName in slots) { - if (!slots.hasOwnProperty(slotName)) continue; - var slotMap = slots[slotName]; - var slotIndex = skeletonData.findSlotIndex(slotName); - - for (var timelineName in slotMap) { - if (!slotMap.hasOwnProperty(timelineName)) continue; - var values = slotMap[timelineName]; - if (timelineName == "color") { - var timeline = new spine.ColorTimeline(values.length); - timeline.slotIndex = slotIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - var color = valueMap["color"]; - var r = spine.SkeletonJson.toColor(color, 0); - var g = spine.SkeletonJson.toColor(color, 1); - var b = spine.SkeletonJson.toColor(color, 2); - var a = spine.SkeletonJson.toColor(color, 3); - timeline.setFrame(frameIndex, valueMap["time"], r, g, b, a); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 5 - 5]); - - } else if (timelineName == "attachment") { - var timeline = new spine.AttachmentTimeline(values.length); - timeline.slotIndex = slotIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); - - } else - throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; - } - } - skeletonData.animations.push(new spine.Animation(name, timelines, duration)); - } -}; -spine.SkeletonJson.readCurve = function (timeline, frameIndex, valueMap) { - var curve = valueMap["curve"]; - if (!curve) return; - if (curve == "stepped") - timeline.curves.setStepped(frameIndex); - else if (curve instanceof Array) - timeline.curves.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); -}; -spine.SkeletonJson.toColor = function (hexString, colorIndex) { - if (hexString.length != 8) throw "Color hexidecimal length must be 8, recieved: " + hexString; - return parseInt(hexString.substring(colorIndex * 2, 2), 16) / 255; -}; - -spine.Atlas = function (atlasText, textureLoader) { - this.textureLoader = textureLoader; - this.pages = []; - this.regions = []; - - var reader = new spine.AtlasReader(atlasText); - var tuple = []; - tuple.length = 4; - var page = null; - while (true) { - var line = reader.readLine(); - if (line == null) break; - line = reader.trim(line); - if (line.length == 0) - page = null; - else if (!page) { - page = new spine.AtlasPage(); - page.name = line; - - page.format = spine.Atlas.Format[reader.readValue()]; - - reader.readTuple(tuple); - page.minFilter = spine.Atlas.TextureFilter[tuple[0]]; - page.magFilter = spine.Atlas.TextureFilter[tuple[1]]; - - var direction = reader.readValue(); - page.uWrap = spine.Atlas.TextureWrap.clampToEdge; - page.vWrap = spine.Atlas.TextureWrap.clampToEdge; - if (direction == "x") - page.uWrap = spine.Atlas.TextureWrap.repeat; - else if (direction == "y") - page.vWrap = spine.Atlas.TextureWrap.repeat; - else if (direction == "xy") - page.uWrap = page.vWrap = spine.Atlas.TextureWrap.repeat; - - textureLoader.load(page, line); - - this.pages.push(page); - - } else { - var region = new spine.AtlasRegion(); - region.name = line; - region.page = page; - - region.rotate = reader.readValue() == "true"; - - reader.readTuple(tuple); - var x = parseInt(tuple[0]); - var y = parseInt(tuple[1]); - - reader.readTuple(tuple); - var width = parseInt(tuple[0]); - var height = parseInt(tuple[1]); - - region.u = x / page.width; - region.v = y / page.height; - if (region.rotate) { - region.u2 = (x + height) / page.width; - region.v2 = (y + width) / page.height; - } else { - region.u2 = (x + width) / page.width; - region.v2 = (y + height) / page.height; - } - region.x = x; - region.y = y; - region.width = Math.abs(width); - region.height = Math.abs(height); - - if (reader.readTuple(tuple) == 4) { // split is optional - region.splits = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; - - if (reader.readTuple(tuple) == 4) { // pad is optional, but only present with splits - region.pads = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; - - reader.readTuple(tuple); - } - } - - region.originalWidth = parseInt(tuple[0]); - region.originalHeight = parseInt(tuple[1]); - - reader.readTuple(tuple); - region.offsetX = parseInt(tuple[0]); - region.offsetY = parseInt(tuple[1]); - - region.index = parseInt(reader.readValue()); - - this.regions.push(region); - } - } -}; -spine.Atlas.prototype = { - findRegion: function (name) { - var regions = this.regions; - for (var i = 0, n = regions.length; i < n; i++) - if (regions[i].name == name) return regions[i]; - return null; - }, - dispose: function () { - var pages = this.pages; - for (var i = 0, n = pages.length; i < n; i++) - this.textureLoader.unload(pages[i].rendererObject); - }, - updateUVs: function (page) { - var regions = this.regions; - for (var i = 0, n = regions.length; i < n; i++) { - var region = regions[i]; - if (region.page != page) continue; - region.u = region.x / page.width; - region.v = region.y / page.height; - if (region.rotate) { - region.u2 = (region.x + region.height) / page.width; - region.v2 = (region.y + region.width) / page.height; - } else { - region.u2 = (region.x + region.width) / page.width; - region.v2 = (region.y + region.height) / page.height; - } - } - } -}; - -spine.Atlas.Format = { - alpha: 0, - intensity: 1, - luminanceAlpha: 2, - rgb565: 3, - rgba4444: 4, - rgb888: 5, - rgba8888: 6 -}; - -spine.Atlas.TextureFilter = { - nearest: 0, - linear: 1, - mipMap: 2, - mipMapNearestNearest: 3, - mipMapLinearNearest: 4, - mipMapNearestLinear: 5, - mipMapLinearLinear: 6 -}; - -spine.Atlas.TextureWrap = { - mirroredRepeat: 0, - clampToEdge: 1, - repeat: 2 -}; - -spine.AtlasPage = function () {}; -spine.AtlasPage.prototype = { - name: null, - format: null, - minFilter: null, - magFilter: null, - uWrap: null, - vWrap: null, - rendererObject: null, - width: 0, - height: 0 -}; - -spine.AtlasRegion = function () {}; -spine.AtlasRegion.prototype = { - page: null, - name: null, - x: 0, y: 0, - width: 0, height: 0, - u: 0, v: 0, u2: 0, v2: 0, - offsetX: 0, offsetY: 0, - originalWidth: 0, originalHeight: 0, - index: 0, - rotate: false, - splits: null, - pads: null, -}; - -spine.AtlasReader = function (text) { - this.lines = text.split(/\r\n|\r|\n/); -}; -spine.AtlasReader.prototype = { - index: 0, - trim: function (value) { - return value.replace(/^\s+|\s+$/g, ""); - }, - readLine: function () { - if (this.index >= this.lines.length) return null; - return this.lines[this.index++]; - }, - readValue: function () { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) throw "Invalid line: " + line; - return this.trim(line.substring(colon + 1)); - }, - /** Returns the number of tuple values read (2 or 4). */ - readTuple: function (tuple) { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) throw "Invalid line: " + line; - var i = 0, lastMatch= colon + 1; - for (; i < 3; i++) { - var comma = line.indexOf(",", lastMatch); - if (comma == -1) { - if (i == 0) throw "Invalid line: " + line; - break; - } - tuple[i] = this.trim(line.substr(lastMatch, comma - lastMatch)); - lastMatch = comma + 1; - } - tuple[i] = this.trim(line.substring(lastMatch)); - return i + 1; - } -} - -spine.AtlasAttachmentLoader = function (atlas) { - this.atlas = atlas; -} -spine.AtlasAttachmentLoader.prototype = { - newAttachment: function (skin, type, name) { - switch (type) { - case spine.AttachmentType.region: - var region = this.atlas.findRegion(name); - if (!region) throw "Region not found in atlas: " + name + " (" + type + ")"; - var attachment = new spine.RegionAttachment(name); - attachment.rendererObject = region; - attachment.setUVs(region.u, region.v, region.u2, region.v2, region.rotate); - attachment.regionOffsetX = region.offsetX; - attachment.regionOffsetY = region.offsetY; - attachment.regionWidth = region.width; - attachment.regionHeight = region.height; - attachment.regionOriginalWidth = region.originalWidth; - attachment.regionOriginalHeight = region.originalHeight; - return attachment; - } - throw "Unknown attachment type: " + type; - } -} - -PIXI.AnimCache = {}; -spine.Bone.yDown = true; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * This object is one that will allow you to specify custom rendering functions based on render type - * - * @class CustomRenderable - * @extends DisplayObject - * @constructor - */ -PIXI.CustomRenderable = function() -{ - PIXI.DisplayObject.call( this ); - -} - -// constructor -PIXI.CustomRenderable.prototype = Object.create( PIXI.DisplayObject.prototype ); -PIXI.CustomRenderable.prototype.constructor = PIXI.CustomRenderable; - -/** - * If this object is being rendered by a CanvasRenderer it will call this callback - * - * @method renderCanvas - * @param renderer {CanvasRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.renderCanvas = function(renderer) -{ - // override! -} - -/** - * If this object is being rendered by a WebGLRenderer it will call this callback to initialize - * - * @method initWebGL - * @param renderer {WebGLRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.initWebGL = function(renderer) -{ - // override! -} - -/** - * If this object is being rendered by a WebGLRenderer it will call this callback - * - * @method renderWebGL - * @param renderer {WebGLRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.renderWebGL = function(renderGroup, projectionMatrix) -{ - // not sure if both needed? but ya have for now! - // override! -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.BaseTextureCache = {}; -PIXI.texturesToUpdate = []; -PIXI.texturesToDestroy = []; - -/** - * A texture stores the information that represents an image. All textures have a base texture - * - * @class BaseTexture - * @uses EventTarget - * @constructor - * @param source {String} the source object (image or canvas) - */ -PIXI.BaseTexture = function(source) -{ - PIXI.EventTarget.call( this ); - - /** - * [read-only] The width of the base texture set when the image has loaded - * - * @property width - * @type Number - * @readOnly - */ - this.width = 100; - - /** - * [read-only] The height of the base texture set when the image has loaded - * - * @property height - * @type Number - * @readOnly - */ - this.height = 100; - - /** - * [read-only] Describes if the base texture has loaded or not - * - * @property hasLoaded - * @type Boolean - * @readOnly - */ - this.hasLoaded = false; - - /** - * The source that is loaded to create the texture - * - * @property source - * @type Image - */ - this.source = source; - - if(!source)return; - - if(this.source instanceof Image || this.source instanceof HTMLImageElement) - { - if(this.source.complete) - { - this.hasLoaded = true; - this.width = this.source.width; - this.height = this.source.height; - - PIXI.texturesToUpdate.push(this); - } - else - { - - var scope = this; - this.source.onload = function(){ - - scope.hasLoaded = true; - scope.width = scope.source.width; - scope.height = scope.source.height; - - // add it to somewhere... - PIXI.texturesToUpdate.push(scope); - scope.dispatchEvent( { type: 'loaded', content: scope } ); - } - // this.image.src = imageUrl; - } - } - else - { - this.hasLoaded = true; - this.width = this.source.width; - this.height = this.source.height; - - PIXI.texturesToUpdate.push(this); - } - - this._powerOf2 = false; -} - -PIXI.BaseTexture.prototype.constructor = PIXI.BaseTexture; - -/** - * Destroys this base texture - * - * @method destroy - */ -PIXI.BaseTexture.prototype.destroy = function() -{ - if(this.source instanceof Image) - { - this.source.src = null; - } - this.source = null; - PIXI.texturesToDestroy.push(this); -} - -/** - * Helper function that returns a base texture based on an image url - * If the image is not in the base texture cache it will be created and loaded - * - * @static - * @method fromImage - * @param imageUrl {String} The image url of the texture - * @return BaseTexture - */ -PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) -{ - var baseTexture = PIXI.BaseTextureCache[imageUrl]; - if(!baseTexture) - { - // new Image() breaks tex loading in some versions of Chrome. - // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); - if (crossorigin) - { - image.crossOrigin = ''; - } - image.src = imageUrl; - baseTexture = new PIXI.BaseTexture(image); - PIXI.BaseTextureCache[imageUrl] = baseTexture; - } - - return baseTexture; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.TextureCache = {}; -PIXI.FrameCache = {}; - -/** - * A texture stores the information that represents an image or part of an image. It cannot be added - * to the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used - * - * @class Texture - * @uses EventTarget - * @constructor - * @param baseTexture {BaseTexture} The base texture source to create the texture from - * @param frame {Rectangle} The rectangle frame of the texture to show - */ -PIXI.Texture = function(baseTexture, frame) -{ - PIXI.EventTarget.call( this ); - - if(!frame) - { - this.noFrame = true; - frame = new PIXI.Rectangle(0,0,1,1); - } - - if(baseTexture instanceof PIXI.Texture) - baseTexture = baseTexture.baseTexture; - - /** - * The base texture of this texture - * - * @property baseTexture - * @type BaseTexture - */ - this.baseTexture = baseTexture; - - /** - * The frame specifies the region of the base texture that this texture uses - * - * @property frame - * @type Rectangle - */ - this.frame = frame; - - /** - * The trim point - * - * @property trim - * @type Point - */ - this.trim = new PIXI.Point(); - - this.scope = this; - - if(baseTexture.hasLoaded) - { - if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); - //console.log(frame) - - this.setFrame(frame); - } - else - { - var scope = this; - baseTexture.addEventListener( 'loaded', function(){ scope.onBaseTextureLoaded()} ); - } -} - -PIXI.Texture.prototype.constructor = PIXI.Texture; - -/** - * Called when the base texture is loaded - * - * @method onBaseTextureLoaded - * @param event - * @private - */ -PIXI.Texture.prototype.onBaseTextureLoaded = function(event) -{ - var baseTexture = this.baseTexture; - baseTexture.removeEventListener( 'loaded', this.onLoaded ); - - if(this.noFrame)this.frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); - this.noFrame = false; - this.width = this.frame.width; - this.height = this.frame.height; - - this.scope.dispatchEvent( { type: 'update', content: this } ); -} - -/** - * Destroys this texture - * - * @method destroy - * @param destroyBase {Boolean} Whether to destroy the base texture as well - */ -PIXI.Texture.prototype.destroy = function(destroyBase) -{ - if(destroyBase)this.baseTexture.destroy(); -} - -/** - * Specifies the rectangle region of the baseTexture - * - * @method setFrame - * @param frame {Rectangle} The frame of the texture to set it to - */ -PIXI.Texture.prototype.setFrame = function(frame) -{ - this.frame = frame; - this.width = frame.width; - this.height = frame.height; - - if(frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height) - { - throw new Error("Texture Error: frame does not fit inside the base Texture dimensions " + this); - } - - this.updateFrame = true; - - PIXI.Texture.frameUpdates.push(this); - //this.dispatchEvent( { type: 'update', content: this } ); -} - -/** - * Helper function that returns a texture based on an image url - * If the image is not in the texture cache it will be created and loaded - * - * @static - * @method fromImage - * @param imageUrl {String} The image url of the texture - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - * @return Texture - */ -PIXI.Texture.fromImage = function(imageUrl, crossorigin) -{ - var texture = PIXI.TextureCache[imageUrl]; - - if(!texture) - { - texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); - PIXI.TextureCache[imageUrl] = texture; - } - - return texture; -} - -/** - * Helper function that returns a texture based on a frame id - * If the frame id is not in the texture cache an error will be thrown - * - * @static - * @method fromFrame - * @param frameId {String} The frame id of the texture - * @return Texture - */ -PIXI.Texture.fromFrame = function(frameId) -{ - var texture = PIXI.TextureCache[frameId]; - if(!texture)throw new Error("The frameId '"+ frameId +"' does not exist in the texture cache " + this); - return texture; -} - -/** - * Helper function that returns a texture based on a canvas element - * If the canvas is not in the texture cache it will be created and loaded - * - * @static - * @method fromCanvas - * @param canvas {Canvas} The canvas element source of the texture - * @return Texture - */ -PIXI.Texture.fromCanvas = function(canvas) -{ - var baseTexture = new PIXI.BaseTexture(canvas); - return new PIXI.Texture(baseTexture); -} - - -/** - * Adds a texture to the textureCache. - * - * @static - * @method addTextureToCache - * @param texture {Texture} - * @param id {String} the id that the texture will be stored against. - */ -PIXI.Texture.addTextureToCache = function(texture, id) -{ - PIXI.TextureCache[id] = texture; -} - -/** - * Remove a texture from the textureCache. - * - * @static - * @method removeTextureFromCache - * @param id {String} the id of the texture to be removed - * @return {Texture} the texture that was removed - */ -PIXI.Texture.removeTextureFromCache = function(id) -{ - var texture = PIXI.TextureCache[id] - PIXI.TextureCache[id] = null; - return texture; -} - -// this is more for webGL.. it contains updated frames.. -PIXI.Texture.frameUpdates = []; - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - A RenderTexture is a special texture that allows any pixi displayObject to be rendered to it. - - __Hint__: All DisplayObjects (exmpl. Sprites) that renders on RenderTexture should be preloaded. - Otherwise black rectangles will be drawn instead. - - RenderTexture takes snapshot of DisplayObject passed to render method. If DisplayObject is passed to render method, position and rotation of it will be ignored. For example: - - var renderTexture = new PIXI.RenderTexture(800, 600); - var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - sprite.position.x = 800/2; - sprite.position.y = 600/2; - sprite.anchor.x = 0.5; - sprite.anchor.y = 0.5; - renderTexture.render(sprite); - - Sprite in this case will be rendered to 0,0 position. To render this sprite at center DisplayObjectContainer should be used: - - var doc = new PIXI.DisplayObjectContainer(); - doc.addChild(sprite); - renderTexture.render(doc); // Renders to center of renderTexture - - @class RenderTexture - @extends Texture - @constructor - @param width {Number} The width of the render texture - @param height {Number} The height of the render texture - */ -PIXI.RenderTexture = function(width, height) -{ - PIXI.EventTarget.call( this ); - - this.width = width || 100; - this.height = height || 100; - - this.indetityMatrix = PIXI.mat3.create(); - - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); - - if(PIXI.gl) - { - this.initWebGL(); - } - else - { - this.initCanvas(); - } -} - -PIXI.RenderTexture.prototype = Object.create( PIXI.Texture.prototype ); -PIXI.RenderTexture.prototype.constructor = PIXI.RenderTexture; - -/** - * Initializes the webgl data for this texture - * - * @method initWebGL - * @private - */ -PIXI.RenderTexture.prototype.initWebGL = function() -{ - var gl = PIXI.gl; - this.glFramebuffer = gl.createFramebuffer(); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - - this.glFramebuffer.width = this.width; - this.glFramebuffer.height = this.height; - - this.baseTexture = new PIXI.BaseTexture(); - - this.baseTexture.width = this.width; - this.baseTexture.height = this.height; - - this.baseTexture._glTexture = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - - this.baseTexture.isRender = true; - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.baseTexture._glTexture, 0); - - // create a projection matrix.. - this.projection = new PIXI.Point(this.width/2 , this.height/2); - - // set the correct render function.. - this.render = this.renderWebGL; - - -} - - -PIXI.RenderTexture.prototype.resize = function(width, height) -{ - - this.width = width; - this.height = height; - - if(PIXI.gl) - { - this.projection.x = this.width/2 - this.projection.y = this.height/2; - - var gl = PIXI.gl; - gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - } - else - { - - this.frame.width = this.width - this.frame.height = this.height; - this.renderer.resize(this.width, this.height); - } -} - -/** - * Initializes the canvas data for this texture - * - * @method initCanvas - * @private - */ -PIXI.RenderTexture.prototype.initCanvas = function() -{ - this.renderer = new PIXI.CanvasRenderer(this.width, this.height, null, 0); - - this.baseTexture = new PIXI.BaseTexture(this.renderer.view); - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); - - this.render = this.renderCanvas; -} - -/** - * This function will draw the display object to the texture. - * - * @method renderWebGL - * @param displayObject {DisplayObject} The display object to render this texture on - * @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn - * @private - */ -PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, clear) -{ - var gl = PIXI.gl; - - // enable the alpha color mask.. - gl.colorMask(true, true, true, true); - - gl.viewport(0, 0, this.width, this.height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - - if(clear) - { - gl.clearColor(0,0,0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - } - - // THIS WILL MESS WITH HIT TESTING! - var children = displayObject.children; - - //TODO -? create a new one??? dont think so! - var originalWorldTransform = displayObject.worldTransform; - displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; - // modify to flip... - displayObject.worldTransform[4] = -1; - displayObject.worldTransform[5] = this.projection.y * 2; - - - if(position) - { - displayObject.worldTransform[2] = position.x; - displayObject.worldTransform[5] -= position.y; - } - - PIXI.visibleCount++; - displayObject.vcount = PIXI.visibleCount; - - for(var i=0,j=children.length; i} assetURLs an array of image/sprite sheet urls that you would like loaded - * supported. Supported image formats include "jpeg", "jpg", "png", "gif". Supported - * sprite sheet data formats only include "JSON" at this time. Supported bitmap font - * data formats include "xml" and "fnt". - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.AssetLoader = function(assetURLs, crossorigin) -{ - PIXI.EventTarget.call(this); - - /** - * The array of asset URLs that are going to be loaded - * - * @property assetURLs - * @type Array - */ - this.assetURLs = assetURLs; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * Maps file extension to loader types - * - * @property loadersByType - * @type Object - */ - this.loadersByType = { - "jpg": PIXI.ImageLoader, - "jpeg": PIXI.ImageLoader, - "png": PIXI.ImageLoader, - "gif": PIXI.ImageLoader, - "json": PIXI.JsonLoader, - "anim": PIXI.SpineLoader, - "xml": PIXI.BitmapFontLoader, - "fnt": PIXI.BitmapFontLoader - }; - - -}; - -/** - * Fired when an item has loaded - * @event onProgress - */ - -/** - * Fired when all the assets have loaded - * @event onComplete - */ - -// constructor -PIXI.AssetLoader.prototype.constructor = PIXI.AssetLoader; - -/** - * Starts loading the assets sequentially - * - * @method load - */ -PIXI.AssetLoader.prototype.load = function() -{ - var scope = this; - - this.loadCount = this.assetURLs.length; - - for (var i=0; i < this.assetURLs.length; i++) - { - var fileName = this.assetURLs[i]; - var fileType = fileName.split(".").pop().toLowerCase(); - - var loaderClass = this.loadersByType[fileType]; - if(!loaderClass) - throw new Error(fileType + " is an unsupported file type"); - - var loader = new loaderClass(fileName, this.crossorigin); - - loader.addEventListener("loaded", function() - { - scope.onAssetLoaded(); - }); - loader.load(); - } -}; - -/** - * Invoked after each file is loaded - * - * @method onAssetLoaded - * @private - */ -PIXI.AssetLoader.prototype.onAssetLoaded = function() -{ - this.loadCount--; - this.dispatchEvent({type: "onProgress", content: this}); - if(this.onProgress) this.onProgress(); - - if(this.loadCount == 0) - { - this.dispatchEvent({type: "onComplete", content: this}); - if(this.onComplete) this.onComplete(); - } -}; - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The json file loader is used to load in JSON data and parsing it - * When loaded this class will dispatch a "loaded" event - * If load failed this class will dispatch a "error" event - * - * @class JsonLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the JSON file - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.JsonLoader = function (url, crossorigin) { - PIXI.EventTarget.call(this); - - /** - * The url of the bitmap font data - * - * @property url - * @type String - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * [read-only] The base url of the bitmap font data - * - * @property baseUrl - * @type String - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ""); - - /** - * [read-only] Whether the data has loaded yet - * - * @property loaded - * @type Boolean - * @readOnly - */ - this.loaded = false; - -}; - -// constructor -PIXI.JsonLoader.prototype.constructor = PIXI.JsonLoader; - -/** - * Loads the JSON data - * - * @method load - */ -PIXI.JsonLoader.prototype.load = function () { - this.ajaxRequest = new AjaxRequest(); - var scope = this; - this.ajaxRequest.onreadystatechange = function () { - scope.onJSONLoaded(); - }; - - this.ajaxRequest.open("GET", this.url, true); - if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/json"); - this.ajaxRequest.send(null); -}; - -/** - * Invoke when JSON file is loaded - * - * @method onJSONLoaded - * @private - */ -PIXI.JsonLoader.prototype.onJSONLoaded = function () { - if (this.ajaxRequest.readyState == 4) { - if (this.ajaxRequest.status == 200 || window.location.href.indexOf("http") == -1) { - this.json = JSON.parse(this.ajaxRequest.responseText); - - if(this.json.frames) - { - // sprite sheet - var scope = this; - var textureUrl = this.baseUrl + this.json.meta.image; - var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); - var frameData = this.json.frames; - - this.texture = image.texture.baseTexture; - image.addEventListener("loaded", function (event) { - scope.onLoaded(); - }); - - for (var i in frameData) { - var rect = frameData[i].frame; - if (rect) { - PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) { - //var realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) - // calculate the offset! - } - } - } - - image.load(); - - } - else if(this.json.bones) - { - // spine animation - var spineJsonParser = new spine.SkeletonJson(); - var skeletonData = spineJsonParser.readSkeletonData(this.json); - PIXI.AnimCache[this.url] = skeletonData; - this.onLoaded(); - } - else - { - this.onLoaded(); - } - } - else - { - this.onError(); - } - } -}; - -/** - * Invoke when json file loaded - * - * @method onLoaded - * @private - */ -PIXI.JsonLoader.prototype.onLoaded = function () { - this.loaded = true; - this.dispatchEvent({ - type: "loaded", - content: this - }); -}; - -/** - * Invoke when error occured - * - * @method onError - * @private - */ -PIXI.JsonLoader.prototype.onError = function () { - this.dispatchEvent({ - type: "error", - content: this - }); -}; -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The sprite sheet loader is used to load in JSON sprite sheet data - * To generate the data you can use http://www.codeandweb.com/texturepacker and publish the "JSON" format - * There is a free version so thats nice, although the paid version is great value for money. - * It is highly recommended to use Sprite sheets (also know as texture atlas") as it means sprite"s can be batched and drawn together for highly increased rendering speed. - * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() - * This loader will also load the image file that the Spritesheet points to as well as the data. - * When loaded this class will dispatch a "loaded" event - * - * @class SpriteSheetLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the sprite sheet JSON file - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ - -PIXI.SpriteSheetLoader = function (url, crossorigin) { - /* - * i use texture packer to load the assets.. - * http://www.codeandweb.com/texturepacker - * make sure to set the format as "JSON" - */ - PIXI.EventTarget.call(this); - - /** - * The url of the bitmap font data - * - * @property url - * @type String - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * [read-only] The base url of the bitmap font data - * - * @property baseUrl - * @type String - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ""); - - /** - * The texture being loaded - * - * @property texture - * @type Texture - */ - this.texture = null; - - /** - * The frames of the sprite sheet - * - * @property frames - * @type Object - */ - this.frames = {}; -}; - -// constructor -PIXI.SpriteSheetLoader.prototype.constructor = PIXI.SpriteSheetLoader; - -/** - * This will begin loading the JSON file - * - * @method load - */ -PIXI.SpriteSheetLoader.prototype.load = function () { - var scope = this; - var jsonLoader = new PIXI.JsonLoader(this.url, this.crossorigin); - jsonLoader.addEventListener("loaded", function (event) { - scope.json = event.content.json; - scope.onJSONLoaded(); - }); - jsonLoader.load(); -}; - -/** - * Invoke when JSON file is loaded - * - * @method onJSONLoaded - * @private - */ -PIXI.SpriteSheetLoader.prototype.onJSONLoaded = function () { - var scope = this; - var textureUrl = this.baseUrl + this.json.meta.image; - var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); - var frameData = this.json.frames; - - this.texture = image.texture.baseTexture; - image.addEventListener("loaded", function (event) { - scope.onLoaded(); - }); - - for (var i in frameData) { - var rect = frameData[i].frame; - if (rect) { - PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) { - //var realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) - // calculate the offset! - } - } - } - - image.load(); -}; -/** - * Invoke when all files are loaded (json and texture) - * - * @method onLoaded - * @private - */ -PIXI.SpriteSheetLoader.prototype.onLoaded = function () { - this.dispatchEvent({ - type: "loaded", - content: this - }); -}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The image loader class is responsible for loading images file formats ("jpeg", "jpg", "png" and "gif") - * Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() - * When loaded this class will dispatch a 'loaded' event - * - * @class ImageLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the image - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.ImageLoader = function(url, crossorigin) -{ - PIXI.EventTarget.call(this); - - /** - * The texture being loaded - * - * @property texture - * @type Texture - */ - this.texture = PIXI.Texture.fromImage(url, crossorigin); - - /** - * if the image is loaded with loadFramedSpriteSheet - * frames will contain the sprite sheet frames - * - */ - this.frames = []; -}; - -// constructor -PIXI.ImageLoader.prototype.constructor = PIXI.ImageLoader; - -/** - * Loads image or takes it from cache - * - * @method load - */ -PIXI.ImageLoader.prototype.load = function() -{ - if(!this.texture.baseTexture.hasLoaded) - { - var scope = this; - this.texture.baseTexture.addEventListener("loaded", function() - { - scope.onLoaded(); - }); - } - else - { - this.onLoaded(); - } -}; - -/** - * Invoked when image file is loaded or it is already cached and ready to use - * - * @method onLoaded - * @private - */ -PIXI.ImageLoader.prototype.onLoaded = function() -{ - this.dispatchEvent({type: "loaded", content: this}); -}; - -/** - * Loads image and split it to uniform sized frames - * - * - * @method loadFramedSpriteSheet - * @param frameWidth {Number} with of each frame - * @param frameHeight {Number} height of each frame - * @param textureName {String} if given, the frames will be cached in - format - */ -PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) -{ - this.frames = []; - var cols = Math.floor(this.texture.width / frameWidth); - var rows = Math.floor(this.texture.height / frameHeight); - - var i=0; - for (var y=0; y - + diff --git a/examples/example 5 - Morph/pixi.js b/examples/example 5 - Morph/pixi.js deleted file mode 100644 index 6d567a2..0000000 --- a/examples/example 5 - Morph/pixi.js +++ /dev/null @@ -1,10649 +0,0 @@ -/** - * @license - * Pixi.JS - v1.3.0 - * Copyright (c) 2012, Mat Groves - * http://goodboydigital.com/ - * - * Compiled: 2013-09-30 - * - * Pixi.JS is licensed under the MIT License. - * http://www.opensource.org/licenses/mit-license.php - */ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -(function(){ - - var root = this; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * @module PIXI - */ -var PIXI = PIXI || {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The Point object represents a location in a two-dimensional coordinate system, where x represents the horizontal axis and y represents the vertical axis. - * - * @class Point - * @constructor - * @param x {Number} position of the point - * @param y {Number} position of the point - */ -PIXI.Point = function(x, y) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; -} - -/** - * Creates a clone of this point - * - * @method clone - * @return {Point} a copy of the point - */ -PIXI.Point.prototype.clone = function() -{ - return new PIXI.Point(this.x, this.y); -} - -// constructor -PIXI.Point.prototype.constructor = PIXI.Point; - - -/** - * @author Mat Groves http://matgroves.com/ - */ - -/** - * the Rectangle object is an area defined by its position, as indicated by its top-left corner point (x, y) and by its width and its height. - * - * @class Rectangle - * @constructor - * @param x {Number} The X coord of the upper-left corner of the rectangle - * @param y {Number} The Y coord of the upper-left corner of the rectangle - * @param width {Number} The overall width of this rectangle - * @param height {Number} The overall height of this rectangle - */ -PIXI.Rectangle = function(x, y, width, height) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property width - * @type Number - * @default 0 - */ - this.width = width || 0; - - /** - * @property height - * @type Number - * @default 0 - */ - this.height = height || 0; -} - -/** - * Creates a clone of this Rectangle - * - * @method clone - * @return {Rectangle} a copy of the rectangle - */ -PIXI.Rectangle.prototype.clone = function() -{ - return new PIXI.Rectangle(this.x, this.y, this.width, this.height); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this Rectangle - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this Rectangle - */ -PIXI.Rectangle.prototype.contains = function(x, y) -{ - if(this.width <= 0 || this.height <= 0) - return false; - - var x1 = this.x; - if(x >= x1 && x <= x1 + this.width) - { - var y1 = this.y; - - if(y >= y1 && y <= y1 + this.height) - { - return true; - } - } - - return false; -} - -// constructor -PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; - - -/** - * @author Adrien Brault - */ - -/** - * @class Polygon - * @constructor - * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, - * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be - * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the - * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are - * Numbers. - */ -PIXI.Polygon = function(points) -{ - //if points isn't an array, use arguments as the array - if(!(points instanceof Array)) - points = Array.prototype.slice.call(arguments); - - //if this is a flat array of numbers, convert it to points - if(typeof points[0] === 'number') { - var p = []; - for(var i = 0, il = points.length; i < il; i+=2) { - p.push( - new PIXI.Point(points[i], points[i + 1]) - ); - } - - points = p; - } - - this.points = points; -} - -/** - * Creates a clone of this polygon - * - * @method clone - * @return {Polygon} a copy of the polygon - */ -PIXI.Polygon.prototype.clone = function() -{ - var points = []; - for (var i=0; i y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); - - if(intersect) inside = !inside; - } - - return inside; -} - -// constructor -PIXI.Polygon.prototype.constructor = PIXI.Polygon; - -/** - * @author Chad Engler - */ - -/** - * The Circle object can be used to specify a hit area for displayobjects - * - * @class Circle - * @constructor - * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle - * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle - * @param radius {Number} The radius of the circle - */ -PIXI.Circle = function(x, y, radius) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property radius - * @type Number - * @default 0 - */ - this.radius = radius || 0; -} - -/** - * Creates a clone of this Circle instance - * - * @method clone - * @return {Circle} a copy of the polygon - */ -PIXI.Circle.prototype.clone = function() -{ - return new PIXI.Circle(this.x, this.y, this.radius); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this circle - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this polygon - */ -PIXI.Circle.prototype.contains = function(x, y) -{ - if(this.radius <= 0) - return false; - - var dx = (this.x - x), - dy = (this.y - y), - r2 = this.radius * this.radius; - - dx *= dx; - dy *= dy; - - return (dx + dy <= r2); -} - -// constructor -PIXI.Circle.prototype.constructor = PIXI.Circle; - - -/** - * @author Chad Engler - */ - -/** - * The Ellipse object can be used to specify a hit area for displayobjects - * - * @class Ellipse - * @constructor - * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse - * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse - * @param width {Number} The overall width of this ellipse - * @param height {Number} The overall height of this ellipse - */ -PIXI.Ellipse = function(x, y, width, height) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property width - * @type Number - * @default 0 - */ - this.width = width || 0; - - /** - * @property height - * @type Number - * @default 0 - */ - this.height = height || 0; -} - -/** - * Creates a clone of this Ellipse instance - * - * @method clone - * @return {Ellipse} a copy of the ellipse - */ -PIXI.Ellipse.prototype.clone = function() -{ - return new PIXI.Ellipse(this.x, this.y, this.width, this.height); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this ellipse - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this ellipse - */ -PIXI.Ellipse.prototype.contains = function(x, y) -{ - if(this.width <= 0 || this.height <= 0) - return false; - - //normalize the coords to an ellipse with center 0,0 - //and a radius of 0.5 - var normx = ((x - this.x) / this.width) - 0.5, - normy = ((y - this.y) / this.height) - 0.5; - - normx *= normx; - normy *= normy; - - return (normx + normy < 0.25); -} - -PIXI.Ellipse.getBounds = function() -{ - return new PIXI.Rectangle(this.x, this.y, this.width, this.height); -} - -// constructor -PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; - - - -/* - * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV - * you both rock! - */ - -function determineMatrixArrayType() { - PIXI.Matrix = (typeof Float32Array !== 'undefined') ? Float32Array : Array; - return PIXI.Matrix; -} - -determineMatrixArrayType(); - -PIXI.mat3 = {}; - -PIXI.mat3.create = function() -{ - var matrix = new PIXI.Matrix(9); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 1; - matrix[5] = 0; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 1; - - return matrix; -} - - -PIXI.mat3.identity = function(matrix) -{ - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 1; - matrix[5] = 0; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 1; - - return matrix; -} - - -PIXI.mat4 = {}; - -PIXI.mat4.create = function() -{ - var matrix = new PIXI.Matrix(16); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 0; - matrix[5] = 1; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = 1; - matrix[11] = 0; - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; - - return matrix; -} - -PIXI.mat3.multiply = function (mat, mat2, dest) -{ - if (!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[0], a01 = mat[1], a02 = mat[2], - a10 = mat[3], a11 = mat[4], a12 = mat[5], - a20 = mat[6], a21 = mat[7], a22 = mat[8], - - b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], - b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], - b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; - - dest[0] = b00 * a00 + b01 * a10 + b02 * a20; - dest[1] = b00 * a01 + b01 * a11 + b02 * a21; - dest[2] = b00 * a02 + b01 * a12 + b02 * a22; - - dest[3] = b10 * a00 + b11 * a10 + b12 * a20; - dest[4] = b10 * a01 + b11 * a11 + b12 * a21; - dest[5] = b10 * a02 + b11 * a12 + b12 * a22; - - dest[6] = b20 * a00 + b21 * a10 + b22 * a20; - dest[7] = b20 * a01 + b21 * a11 + b22 * a21; - dest[8] = b20 * a02 + b21 * a12 + b22 * a22; - - return dest; -} - -PIXI.mat3.clone = function(mat) -{ - var matrix = new PIXI.Matrix(9); - - matrix[0] = mat[0]; - matrix[1] = mat[1]; - matrix[2] = mat[2]; - matrix[3] = mat[3]; - matrix[4] = mat[4]; - matrix[5] = mat[5]; - matrix[6] = mat[6]; - matrix[7] = mat[7]; - matrix[8] = mat[8]; - - return matrix; -} - -PIXI.mat3.transpose = function (mat, dest) -{ - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) { - var a01 = mat[1], a02 = mat[2], - a12 = mat[5]; - - mat[1] = mat[3]; - mat[2] = mat[6]; - mat[3] = a01; - mat[5] = mat[7]; - mat[6] = a02; - mat[7] = a12; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[3]; - dest[2] = mat[6]; - dest[3] = mat[1]; - dest[4] = mat[4]; - dest[5] = mat[7]; - dest[6] = mat[2]; - dest[7] = mat[5]; - dest[8] = mat[8]; - return dest; -} - -PIXI.mat3.toMat4 = function (mat, dest) -{ - if (!dest) { dest = PIXI.mat4.create(); } - - dest[15] = 1; - dest[14] = 0; - dest[13] = 0; - dest[12] = 0; - - dest[11] = 0; - dest[10] = mat[8]; - dest[9] = mat[7]; - dest[8] = mat[6]; - - dest[7] = 0; - dest[6] = mat[5]; - dest[5] = mat[4]; - dest[4] = mat[3]; - - dest[3] = 0; - dest[2] = mat[2]; - dest[1] = mat[1]; - dest[0] = mat[0]; - - return dest; -} - - -///// - - -PIXI.mat4.create = function() -{ - var matrix = new PIXI.Matrix(16); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 0; - matrix[5] = 1; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = 1; - matrix[11] = 0; - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; - - return matrix; -} - -PIXI.mat4.transpose = function (mat, dest) -{ - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) - { - var a01 = mat[1], a02 = mat[2], a03 = mat[3], - a12 = mat[6], a13 = mat[7], - a23 = mat[11]; - - mat[1] = mat[4]; - mat[2] = mat[8]; - mat[3] = mat[12]; - mat[4] = a01; - mat[6] = mat[9]; - mat[7] = mat[13]; - mat[8] = a02; - mat[9] = a12; - mat[11] = mat[14]; - mat[12] = a03; - mat[13] = a13; - mat[14] = a23; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[4]; - dest[2] = mat[8]; - dest[3] = mat[12]; - dest[4] = mat[1]; - dest[5] = mat[5]; - dest[6] = mat[9]; - dest[7] = mat[13]; - dest[8] = mat[2]; - dest[9] = mat[6]; - dest[10] = mat[10]; - dest[11] = mat[14]; - dest[12] = mat[3]; - dest[13] = mat[7]; - dest[14] = mat[11]; - dest[15] = mat[15]; - return dest; -} - -PIXI.mat4.multiply = function (mat, mat2, dest) -{ - if (!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; - var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; - var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; - var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - - // Cache only the current line of the second matrix - var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; - dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[4]; - b1 = mat2[5]; - b2 = mat2[6]; - b3 = mat2[7]; - dest[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[8]; - b1 = mat2[9]; - b2 = mat2[10]; - b3 = mat2[11]; - dest[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[12]; - b1 = mat2[13]; - b2 = mat2[14]; - b3 = mat2[15]; - dest[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - return dest; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The base class for all objects that are rendered on the screen. - * - * @class DisplayObject - * @constructor - */ -PIXI.DisplayObject = function() -{ - this.last = this; - this.first = this; - /** - * The coordinate of the object relative to the local coordinates of the parent. - * - * @property position - * @type Point - */ - this.position = new PIXI.Point(); - - /** - * The scale factor of the object. - * - * @property scale - * @type Point - */ - this.scale = new PIXI.Point(1,1);//{x:1, y:1}; - - /** - * The pivot point of the displayObject that it rotates around - * - * @property pivot - * @type Point - */ - this.pivot = new PIXI.Point(0,0); - - /** - * The rotation of the object in radians. - * - * @property rotation - * @type Number - */ - this.rotation = 0; - - /** - * The opacity of the object. - * - * @property alpha - * @type Number - */ - this.alpha = 1; - - /** - * The visibility of the object. - * - * @property visible - * @type Boolean - */ - this.visible = true; - - /** - * This is the defined area that will pick up mouse / touch events. It is null by default. - * Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children) - * - * @property hitArea - * @type Rectangle|Circle|Ellipse|Polygon - */ - this.hitArea = null; - - /** - * This is used to indicate if the displayObject should display a mouse hand cursor on rollover - * - * @property buttonMode - * @type Boolean - */ - this.buttonMode = false; - - /** - * Can this object be rendered - * - * @property renderable - * @type Boolean - */ - this.renderable = false; - - /** - * [read-only] The display object container that contains this display object. - * - * @property parent - * @type DisplayObjectContainer - * @readOnly - */ - this.parent = null; - - /** - * [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage. - * - * @property stage - * @type Stage - * @readOnly - */ - this.stage = null; - - /** - * [read-only] The multiplied alpha of the displayobject - * - * @property worldAlpha - * @type Number - * @readOnly - */ - this.worldAlpha = 1; - - /** - * [read-only] Whether or not the object is interactive, do not toggle directly! use the `interactive` property - * - * @property _interactive - * @type Boolean - * @readOnly - * @private - */ - this._interactive = false; - - /** - * [read-only] Current transform of the object based on world (parent) factors - * - * @property worldTransform - * @type Mat3 - * @readOnly - * @private - */ - this.worldTransform = PIXI.mat3.create()//mat3.identity(); - - /** - * [read-only] Current transform of the object locally - * - * @property localTransform - * @type Mat3 - * @readOnly - * @private - */ - this.localTransform = PIXI.mat3.create()//mat3.identity(); - - /** - * [NYI] Unkown - * - * @property color - * @type Array<> - * @private - */ - this.color = []; - - /** - * [NYI] Holds whether or not this object is dynamic, for rendering optimization - * - * @property dynamic - * @type Boolean - * @private - */ - this.dynamic = true; - - // chach that puppy! - this._sr = 0; - this._cr = 1; - - /* - * MOUSE Callbacks - */ - - /** - * A callback that is used when the users clicks on the displayObject with their mouse - * @method click - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user clicks the mouse down over the sprite - * @method mousedown - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject - * for this callback to be fired the mouse must have been pressed down over the displayObject - * @method mouseup - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject - * for this callback to be fired, The touch must have started over the displayObject - * @method mouseupoutside - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the users mouse rolls over the displayObject - * @method mouseover - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the users mouse leaves the displayObject - * @method mouseout - * @param interactionData {InteractionData} - */ - - - /* - * TOUCH Callbacks - */ - - /** - * A callback that is used when the users taps on the sprite with their finger - * basically a touch version of click - * @method tap - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user touch's over the displayObject - * @method touchstart - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases a touch over the displayObject - * @method touchend - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the touch that was over the displayObject - * for this callback to be fired, The touch must have started over the sprite - * @method touchendoutside - * @param interactionData {InteractionData} - */ -} - -// constructor -PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; - -/** - * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default - * Instead of using this function you can now simply set the interactive property to true or false - * - * @method setInteractive - * @param interactive {Boolean} - * @deprecated Simply set the `interactive` property directly - */ -PIXI.DisplayObject.prototype.setInteractive = function(interactive) -{ - this.interactive = interactive; -} - -/** - * Indicates if the sprite will have touch and mouse interactivity. It is false by default - * - * @property interactive - * @type Boolean - * @default false - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'interactive', { - get: function() { - return this._interactive; - }, - set: function(value) { - this._interactive = value; - - // TODO more to be done here.. - // need to sort out a re-crawl! - if(this.stage)this.stage.dirty = true; - } -}); - -/** - * Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. - * In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. - * To remove a mask, set this property to null. - * - * @property mask - * @type Graphics - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { - get: function() { - return this._mask; - }, - set: function(value) { - - - if(value) - { - if(this._mask) - { - value.start = this._mask.start; - value.end = this._mask.end; - } - else - { - this.addFilter(value); - value.renderable = false; - } - } - else - { - this.removeFilter(this._mask); - this._mask.renderable = true; - } - - this._mask = value; - } -}); - -/** - * Sets the filters for the displayObject. Currently there's a few limitations. - * 1: At the moment only one filter can be applied at a time.. - * 2: They cannot be nested. - * 3: There's no padding yet. - * 4: this is a webGL only feature. - * @property filters - * @type Array - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { - get: function() { - return this._filters; - }, - set: function(value) { - - //if(value == ) - if(value) - { - if(this._filters)this.removeFilter(this._filters); - this.addFilter(value) - } - else - { - if(this._filters)this.removeFilter(this._filters); - } - - this._filters = value; - } -}); - -/* - * Adds a filter to this displayObject - * - * @method addFilter - * @param mask {Graphics} the graphics object to use as a filter - * @private - */ -PIXI.DisplayObject.prototype.addFilter = function(data) -{ - //if(this.filter)return; - //this.filter = true; - - // insert a filter block.. - // TODO Onject pool thease bad boys.. - var start = new PIXI.FilterBlock(); - var end = new PIXI.FilterBlock(); - - data.start = start; - data.end = end; - - start.data = data; - end.data = data; - - start.first = start.last = this; - end.first = end.last = this; - - start.open = true; - - /* - * insert start - */ - - var childFirst = start - var childLast = start - var nextObject; - var previousObject; - - previousObject = this.first._iPrev; - - if(previousObject) - { - nextObject = previousObject._iNext; - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - } - else - { - nextObject = this; - } - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - - // now insert the end filter block.. - - /* - * insert end filter - */ - var childFirst = end - var childLast = end - var nextObject = null; - var previousObject = null; - - previousObject = this.last; - nextObject = previousObject._iNext; - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - var updateLast = this; - - var prevLast = this.last; - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = end; - } - updateLast = updateLast.parent; - } - - this.first = start; - - // if webGL... - if(this.__renderGroup) - { - this.__renderGroup.addFilterBlocks(start, end); - } - -} - -/* - * Removes the filter to this displayObject - * - * @method removeFilter - * @private - */ -PIXI.DisplayObject.prototype.removeFilter = function(data) -{ - //if(!this.filter)return; - //this.filter = false; - console.log("YUOIO") - // modify the list.. - var startBlock = data.start; - - - var nextObject = startBlock._iNext; - var previousObject = startBlock._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - if(previousObject)previousObject._iNext = nextObject; - - this.first = startBlock._iNext; - - // remove the end filter - var lastBlock = data.end; - - var nextObject = lastBlock._iNext; - var previousObject = lastBlock._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - - // this is always true too! - var tempLast = lastBlock._iPrev; - // need to make sure the parents last is updated too - var updateLast = this; - while(updateLast.last == lastBlock) - { - updateLast.last = tempLast; - updateLast = updateLast.parent; - if(!updateLast)break; - } - - // if webGL... - if(this.__renderGroup) - { - this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); - } -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.DisplayObject.prototype.updateTransform = function() -{ - // TODO OPTIMIZE THIS!! with dirty - if(this.rotation !== this.rotationCache) - { - this.rotationCache = this.rotation; - this._sr = Math.sin(this.rotation); - this._cr = Math.cos(this.rotation); - } - - var localTransform = this.localTransform; - var parentTransform = this.parent.worldTransform; - var worldTransform = this.worldTransform; - //console.log(localTransform) - localTransform[0] = this._cr * this.scale.x; - localTransform[1] = -this._sr * this.scale.y - localTransform[3] = this._sr * this.scale.x; - localTransform[4] = this._cr * this.scale.y; - - // TODO --> do we even need a local matrix??? - - var px = this.pivot.x; - var py = this.pivot.y; - - // Cache the matrix values (makes for huge speed increases!) - var a00 = localTransform[0], a01 = localTransform[1], a02 = this.position.x - localTransform[0] * px - py * localTransform[1], - a10 = localTransform[3], a11 = localTransform[4], a12 = this.position.y - localTransform[4] * py - px * localTransform[3], - - b00 = parentTransform[0], b01 = parentTransform[1], b02 = parentTransform[2], - b10 = parentTransform[3], b11 = parentTransform[4], b12 = parentTransform[5]; - - localTransform[2] = a02 - localTransform[5] = a12 - - worldTransform[0] = b00 * a00 + b01 * a10; - worldTransform[1] = b00 * a01 + b01 * a11; - worldTransform[2] = b00 * a02 + b01 * a12 + b02; - - worldTransform[3] = b10 * a00 + b11 * a10; - worldTransform[4] = b10 * a01 + b11 * a11; - worldTransform[5] = b10 * a02 + b11 * a12 + b12; - - // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! - // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); - this.worldAlpha = this.alpha * this.parent.worldAlpha; - - this.vcount = PIXI.visibleCount; - -} - -PIXI.visibleCount = 0; -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * A DisplayObjectContainer represents a collection of display objects. - * It is the base class of all display objects that act as a container for other objects. - * - * @class DisplayObjectContainer - * @extends DisplayObject - * @constructor - */ -PIXI.DisplayObjectContainer = function() -{ - PIXI.DisplayObject.call( this ); - - /** - * [read-only] The of children of this container. - * - * @property children - * @type Array - * @readOnly - */ - this.children = []; -} - -// constructor -PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); -PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; - -/** - * Adds a child to the container. - * - * @method addChild - * @param child {DisplayObject} The DisplayObject to add to the container - */ -PIXI.DisplayObjectContainer.prototype.addChild = function(child) -{ - if(child.parent != undefined) - { - - //// COULD BE THIS??? - child.parent.removeChild(child); - // return; - } - - child.parent = this; - - this.children.push(child); - - // update the stage refference.. - - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = this.stage; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // LINKED LIST // - - // modify the list.. - var childFirst = child.first - var childLast = child.last; - var nextObject; - var previousObject; - - // this could be wrong if there is a filter?? - if(this._filters) - { - previousObject = this.last._iPrev; - } - else - { - previousObject = this.last; - } - - nextObject = previousObject._iNext; - - // always true in this case - // need to make sure the parents last is updated too - var updateLast = this; - var prevLast = previousObject; - - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = child.last; - } - updateLast = updateLast.parent; - } - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - // need to remove any render groups.. - if(this.__renderGroup) - { - // being used by a renderTexture.. if it exists then it must be from a render texture; - if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); - // add them to the new render group.. - this.__renderGroup.addDisplayObjectAndChildren(child); - } - -} - -/** - * Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown - * - * @method addChildAt - * @param child {DisplayObject} The child to add - * @param index {Number} The index to place the child in - */ -PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) -{ - if(index >= 0 && index <= this.children.length) - { - if(child.parent != undefined) - { - child.parent.removeChild(child); - } - child.parent = this; - - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = this.stage; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // modify the list.. - var childFirst = child.first; - var childLast = child.last; - var nextObject; - var previousObject; - - if(index == this.children.length) - { - previousObject = this.last; - var updateLast = this; - var prevLast = this.last; - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = child.last; - } - updateLast = updateLast.parent; - } - } - else if(index == 0) - { - previousObject = this; - } - else - { - previousObject = this.children[index-1].last; - } - - nextObject = previousObject._iNext; - - // always true in this case - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - this.children.splice(index, 0, child); - // need to remove any render groups.. - if(this.__renderGroup) - { - // being used by a renderTexture.. if it exists then it must be from a render texture; - if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); - // add them to the new render group.. - this.__renderGroup.addDisplayObjectAndChildren(child); - } - - } - else - { - throw new Error(child + " The index "+ index +" supplied is out of bounds " + this.children.length); - } -} - -/** - * [NYI] Swaps the depth of 2 displayObjects - * - * @method swapChildren - * @param child {DisplayObject} - * @param child2 {DisplayObject} - * @private - */ -PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2) -{ - /* - * this funtion needs to be recoded.. - * can be done a lot faster.. - */ - return; - - // need to fix this function :/ - /* - // TODO I already know this?? - var index = this.children.indexOf( child ); - var index2 = this.children.indexOf( child2 ); - - if ( index !== -1 && index2 !== -1 ) - { - // cool - - /* - if(this.stage) - { - // this is to satisfy the webGL batching.. - // TODO sure there is a nicer way to achieve this! - this.stage.__removeChild(child); - this.stage.__removeChild(child2); - - this.stage.__addChild(child); - this.stage.__addChild(child2); - } - - // swap the positions.. - this.children[index] = child2; - this.children[index2] = child; - - } - else - { - throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); - }*/ -} - -/** - * Returns the Child at the specified index - * - * @method getChildAt - * @param index {Number} The index to get the child from - */ -PIXI.DisplayObjectContainer.prototype.getChildAt = function(index) -{ - if(index >= 0 && index < this.children.length) - { - return this.children[index]; - } - else - { - throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); - } -} - -/** - * Removes a child from the container. - * - * @method removeChild - * @param child {DisplayObject} The DisplayObject to remove - */ -PIXI.DisplayObjectContainer.prototype.removeChild = function(child) -{ - var index = this.children.indexOf( child ); - if ( index !== -1 ) - { - // unlink // - // modify the list.. - var childFirst = child.first; - var childLast = child.last; - - var nextObject = childLast._iNext; - var previousObject = childFirst._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - - if(this.last == childLast) - { - var tempLast = childFirst._iPrev; - // need to make sure the parents last is updated too - var updateLast = this; - while(updateLast.last == childLast.last) - { - updateLast.last = tempLast; - updateLast = updateLast.parent; - if(!updateLast)break; - } - } - - childLast._iNext = null; - childFirst._iPrev = null; - - // update the stage reference.. - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = null; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // webGL trim - if(child.__renderGroup) - { - child.__renderGroup.removeDisplayObjectAndChildren(child); - } - - child.parent = undefined; - this.children.splice( index, 1 ); - } - else - { - throw new Error(child + " The supplied DisplayObject must be a child of the caller " + this); - } -} - -/* - * Updates the container's children's transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.DisplayObjectContainer.prototype.updateTransform = function() -{ - if(!this.visible)return; - - PIXI.DisplayObject.prototype.updateTransform.call( this ); - - for(var i=0,j=this.children.length; i} an array of {Texture} objects that make up the animation - */ -PIXI.MovieClip = function(textures) -{ - PIXI.Sprite.call(this, textures[0]); - - /** - * The array of textures that make up the animation - * - * @property textures - * @type Array - */ - this.textures = textures; - - /** - * The speed that the MovieClip will play at. Higher is faster, lower is slower - * - * @property animationSpeed - * @type Number - * @default 1 - */ - this.animationSpeed = 1; - - /** - * Whether or not the movie clip repeats after playing. - * - * @property loop - * @type Boolean - * @default true - */ - this.loop = true; - - /** - * Function to call when a MovieClip finishes playing - * - * @property onComplete - * @type Function - */ - this.onComplete = null; - - /** - * [read-only] The index MovieClips current frame (this may not have to be a whole number) - * - * @property currentFrame - * @type Number - * @default 0 - * @readOnly - */ - this.currentFrame = 0; - - /** - * [read-only] Indicates if the MovieClip is currently playing - * - * @property playing - * @type Boolean - * @readOnly - */ - this.playing = false; -} - -// constructor -PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); -PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; - -/** -* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures -* assigned to the MovieClip. -* -* @property totalFrames -* @type Number -* @default 0 -* @readOnly -*/ -Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { - get: function() { - - return this.textures.length; - } -}); - - -/** - * Stops the MovieClip - * - * @method stop - */ -PIXI.MovieClip.prototype.stop = function() -{ - this.playing = false; -} - -/** - * Plays the MovieClip - * - * @method play - */ -PIXI.MovieClip.prototype.play = function() -{ - this.playing = true; -} - -/** - * Stops the MovieClip and goes to a specific frame - * - * @method gotoAndStop - * @param frameNumber {Number} frame index to stop at - */ -PIXI.MovieClip.prototype.gotoAndStop = function(frameNumber) -{ - this.playing = false; - this.currentFrame = frameNumber; - var round = (this.currentFrame + 0.5) | 0; - this.setTexture(this.textures[round % this.textures.length]); -} - -/** - * Goes to a specific frame and begins playing the MovieClip - * - * @method gotoAndPlay - * @param frameNumber {Number} frame index to start at - */ -PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) -{ - this.currentFrame = frameNumber; - this.playing = true; -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.MovieClip.prototype.updateTransform = function() -{ - PIXI.Sprite.prototype.updateTransform.call(this); - - if(!this.playing)return; - - this.currentFrame += this.animationSpeed; - - var round = (this.currentFrame + 0.5) | 0; - - if(this.loop || round < this.textures.length) - { - this.setTexture(this.textures[round % this.textures.length]); - } - else if(round >= this.textures.length) - { - this.gotoAndStop(this.textures.length - 1); - if(this.onComplete) - { - this.onComplete(); - } - } -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - - -PIXI.FilterBlock = function() -{ - this.visible = true; - this.renderable = true; -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.ColorMatrixFilter = function() -{ - // set the uniforms - this.uniforms = { - matrix: {type: 'mat4', value: [1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1]}, - }; - - this.fragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform float invert;", - "uniform mat4 matrix;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", - "gl_FragColor = gl_FragColor * vColor;", - "}" - ]; - -} - - -Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { - get: function() { - return this.uniforms.matrix.value; - }, - set: function(value) { - this.uniforms.matrix.value = value; - } -}); -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Text Object will create a line(s) of text to split a line you can use "\n" - * - * @class Text - * @extends Sprite - * @constructor - * @param text {String} The copy that you would like the text to display - * @param [style] {Object} The style parameters - * @param [style.font] {String} default "bold 20pt Arial" The style and size of the font - * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - * @param [style.stroke] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" - * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) - * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used - * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap - */ -PIXI.Text = function(text, style) -{ - this.canvas = document.createElement("canvas"); - this.context = this.canvas.getContext("2d"); - PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas)); - - this.setText(text); - this.setStyle(style); - - this.updateText(); - this.dirty = false; -}; - -// constructor -PIXI.Text.prototype = Object.create(PIXI.Sprite.prototype); -PIXI.Text.prototype.constructor = PIXI.Text; - -/** - * Set the style of the text - * - * @method setStyle - * @param [style] {Object} The style parameters - * @param [style.font="bold 20pt Arial"] {String} The style and size of the font - * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - * @param [style.stroke="black"] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" - * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) - * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used - * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap - */ -PIXI.Text.prototype.setStyle = function(style) -{ - style = style || {}; - style.font = style.font || "bold 20pt Arial"; - style.fill = style.fill || "black"; - style.align = style.align || "left"; - style.stroke = style.stroke || "black"; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136 - style.strokeThickness = style.strokeThickness || 0; - style.wordWrap = style.wordWrap || false; - style.wordWrapWidth = style.wordWrapWidth || 100; - this.style = style; - this.dirty = true; -}; - -/** - * Set the copy for the text object. To split a line you can use "\n" - * - * @methos setText - * @param {String} text The copy that you would like the text to display - */ -PIXI.Text.prototype.setText = function(text) -{ - this.text = text.toString() || " "; - this.dirty = true; -}; - -/** - * Renders text - * - * @method updateText - * @private - */ -PIXI.Text.prototype.updateText = function() -{ - this.context.font = this.style.font; - - var outputText = this.text; - - // word wrap - // preserve original text - if(this.style.wordWrap)outputText = this.wordWrap(this.text); - - //split text into lines - var lines = outputText.split(/(?:\r\n|\r|\n)/); - - //calculate text width - var lineWidths = []; - var maxLineWidth = 0; - for (var i = 0; i < lines.length; i++) - { - var lineWidth = this.context.measureText(lines[i]).width; - lineWidths[i] = lineWidth; - maxLineWidth = Math.max(maxLineWidth, lineWidth); - } - this.canvas.width = maxLineWidth + this.style.strokeThickness; - - //calculate text height - var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; - this.canvas.height = lineHeight * lines.length; - - //set canvas text styles - this.context.fillStyle = this.style.fill; - this.context.font = this.style.font; - - this.context.strokeStyle = this.style.stroke; - this.context.lineWidth = this.style.strokeThickness; - - this.context.textBaseline = "top"; - - //draw lines line by line - for (i = 0; i < lines.length; i++) - { - var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); - - if(this.style.align == "right") - { - linePosition.x += maxLineWidth - lineWidths[i]; - } - else if(this.style.align == "center") - { - linePosition.x += (maxLineWidth - lineWidths[i]) / 2; - } - - if(this.style.stroke && this.style.strokeThickness) - { - this.context.strokeText(lines[i], linePosition.x, linePosition.y); - } - - if(this.style.fill) - { - this.context.fillText(lines[i], linePosition.x, linePosition.y); - } - } - - this.updateTexture(); -}; - -/** - * Updates texture size based on canvas size - * - * @method updateTexture - * @private - */ -PIXI.Text.prototype.updateTexture = function() -{ - this.texture.baseTexture.width = this.canvas.width; - this.texture.baseTexture.height = this.canvas.height; - this.texture.frame.width = this.canvas.width; - this.texture.frame.height = this.canvas.height; - - this._width = this.canvas.width; - this._height = this.canvas.height; - - PIXI.texturesToUpdate.push(this.texture.baseTexture); -}; - -/** - * Updates the transfor of this object - * - * @method updateTransform - * @private - */ -PIXI.Text.prototype.updateTransform = function() -{ - if(this.dirty) - { - this.updateText(); - this.dirty = false; - } - - PIXI.Sprite.prototype.updateTransform.call(this); -}; - -/* - * http://stackoverflow.com/users/34441/ellisbben - * great solution to the problem! - * - * @method determineFontHeight - * @param fontStyle {Object} - * @private - */ -PIXI.Text.prototype.determineFontHeight = function(fontStyle) -{ - // build a little reference dictionary so if the font style has been used return a - // cached version... - var result = PIXI.Text.heightCache[fontStyle]; - - if(!result) - { - var body = document.getElementsByTagName("body")[0]; - var dummy = document.createElement("div"); - var dummyText = document.createTextNode("M"); - dummy.appendChild(dummyText); - dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); - body.appendChild(dummy); - - result = dummy.offsetHeight; - PIXI.Text.heightCache[fontStyle] = result; - - body.removeChild(dummy); - } - - return result; -}; - -/** - * A Text Object will apply wordwrap - * - * @method wordWrap - * @param text {String} - * @private - */ -PIXI.Text.prototype.wordWrap = function(text) -{ - // search good wrap position - var searchWrapPos = function(ctx, text, start, end, wrapWidth) - { - var p = Math.floor((end-start) / 2) + start; - if(p == start) { - return 1; - } - - if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) - { - if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) - { - return p; - } - else - { - return arguments.callee(ctx, text, p, end, wrapWidth); - } - } - else - { - return arguments.callee(ctx, text, start, p, wrapWidth); - } - }; - - var lineWrap = function(ctx, text, wrapWidth) - { - if(ctx.measureText(text).width <= wrapWidth || text.length < 1) - { - return text; - } - var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); - return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); - }; - - var result = ""; - var lines = text.split("\n"); - for (var i = 0; i < lines.length; i++) - { - result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; - } - - return result; -}; - -/** - * Destroys this text object - * - * @method destroy - * @param destroyTexture {Boolean} - */ -PIXI.Text.prototype.destroy = function(destroyTexture) -{ - if(destroyTexture) - { - this.texture.destroy(); - } - -}; - -PIXI.Text.heightCache = {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" - * You can generate the fnt files using - * http://www.angelcode.com/products/bmfont/ for windows or - * http://www.bmglyph.com/ for mac. - * - * @class BitmapText - * @extends DisplayObjectContainer - * @constructor - * @param text {String} The copy that you would like the text to display - * @param style {Object} The style parameters - * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - */ -PIXI.BitmapText = function(text, style) -{ - PIXI.DisplayObjectContainer.call(this); - - this.setText(text); - this.setStyle(style); - this.updateText(); - this.dirty = false - -}; - -// constructor -PIXI.BitmapText.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); -PIXI.BitmapText.prototype.constructor = PIXI.BitmapText; - -/** - * Set the copy for the text object - * - * @method setText - * @param text {String} The copy that you would like the text to display - */ -PIXI.BitmapText.prototype.setText = function(text) -{ - this.text = text || " "; - this.dirty = true; -}; - -/** - * Set the style of the text - * - * @method setStyle - * @param style {Object} The style parameters - * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - */ -PIXI.BitmapText.prototype.setStyle = function(style) -{ - style = style || {}; - style.align = style.align || "left"; - this.style = style; - - var font = style.font.split(" "); - this.fontName = font[font.length - 1]; - this.fontSize = font.length >= 2 ? parseInt(font[font.length - 2], 10) : PIXI.BitmapText.fonts[this.fontName].size; - - this.dirty = true; -}; - -/** - * Renders text - * - * @method updateText - * @private - */ -PIXI.BitmapText.prototype.updateText = function() -{ - var data = PIXI.BitmapText.fonts[this.fontName]; - var pos = new PIXI.Point(); - var prevCharCode = null; - var chars = []; - var maxLineWidth = 0; - var lineWidths = []; - var line = 0; - var scale = this.fontSize / data.size; - for(var i = 0; i < this.text.length; i++) - { - var charCode = this.text.charCodeAt(i); - if(/(?:\r\n|\r|\n)/.test(this.text.charAt(i))) - { - lineWidths.push(pos.x); - maxLineWidth = Math.max(maxLineWidth, pos.x); - line++; - - pos.x = 0; - pos.y += data.lineHeight; - prevCharCode = null; - continue; - } - - var charData = data.chars[charCode]; - if(!charData) continue; - - if(prevCharCode && charData[prevCharCode]) - { - pos.x += charData.kerning[prevCharCode]; - } - chars.push({texture:charData.texture, line: line, charCode: charCode, position: new PIXI.Point(pos.x + charData.xOffset, pos.y + charData.yOffset)}); - pos.x += charData.xAdvance; - - prevCharCode = charCode; - } - - lineWidths.push(pos.x); - maxLineWidth = Math.max(maxLineWidth, pos.x); - - var lineAlignOffsets = []; - for(i = 0; i <= line; i++) - { - var alignOffset = 0; - if(this.style.align == "right") - { - alignOffset = maxLineWidth - lineWidths[i]; - } - else if(this.style.align == "center") - { - alignOffset = (maxLineWidth - lineWidths[i]) / 2; - } - lineAlignOffsets.push(alignOffset); - } - - for(i = 0; i < chars.length; i++) - { - var c = new PIXI.Sprite(chars[i].texture)//PIXI.Sprite.fromFrame(chars[i].charCode); - c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale; - c.position.y = chars[i].position.y * scale; - c.scale.x = c.scale.y = scale; - this.addChild(c); - } - - this.width = pos.x * scale; - this.height = (pos.y + data.lineHeight) * scale; -}; - -/** - * Updates the transfor of this object - * - * @method updateTransform - * @private - */ -PIXI.BitmapText.prototype.updateTransform = function() -{ - if(this.dirty) - { - while(this.children.length > 0) - { - this.removeChild(this.getChildAt(0)); - } - this.updateText(); - - this.dirty = false; - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -}; - -PIXI.BitmapText.fonts = {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - /** - * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive - * This manager also supports multitouch. - * - * @class InteractionManager - * @constructor - * @param stage {Stage} The stage to handle interactions - */ -PIXI.InteractionManager = function(stage) -{ - /** - * a refference to the stage - * - * @property stage - * @type Stage - */ - this.stage = stage; - - /** - * the mouse data - * - * @property mouse - * @type InteractionData - */ - this.mouse = new PIXI.InteractionData(); - - /** - * an object that stores current touches (InteractionData) by id reference - * - * @property touchs - * @type Object - */ - this.touchs = {}; - - - - // helpers - this.tempPoint = new PIXI.Point(); - //this.tempMatrix = mat3.create(); - - this.mouseoverEnabled = true; - - //tiny little interactiveData pool! - this.pool = []; - - this.interactiveItems = []; - this.interactionDOMElement = null; - - //this will make it so that you dont have to call bind all the time - this.onMouseMove = this.onMouseMove.bind( this ); - this.onMouseDown = this.onMouseDown.bind(this); - this.onMouseOut = this.onMouseOut.bind(this); - this.onMouseUp = this.onMouseUp.bind(this); - - this.onTouchStart = this.onTouchStart.bind(this); - this.onTouchEnd = this.onTouchEnd.bind(this); - this.onTouchMove = this.onTouchMove.bind(this); - - - this.last = 0; -} - -// constructor -PIXI.InteractionManager.prototype.constructor = PIXI.InteractionManager; - -/** - * Collects an interactive sprite recursively to have their interactions managed - * - * @method collectInteractiveSprite - * @param displayObject {DisplayObject} the displayObject to collect - * @param iParent {DisplayObject} - * @private - */ -PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObject, iParent) -{ - var children = displayObject.children; - var length = children.length; - - /// make an interaction tree... {item.__interactiveParent} - for (var i = length-1; i >= 0; i--) - { - var child = children[i]; - -// if(child.visible) { - // push all interactive bits - if(child.interactive) - { - iParent.interactiveChildren = true; - //child.__iParent = iParent; - this.interactiveItems.push(child); - - if(child.children.length > 0) - { - this.collectInteractiveSprite(child, child); - } - } - else - { - child.__iParent = null; - - if(child.children.length > 0) - { - this.collectInteractiveSprite(child, iParent); - } - } -// } - } -} - -/** - * Sets the target for event delegation - * - * @method setTarget - * @param target {WebGLRenderer|CanvasRenderer} the renderer to bind events to - * @private - */ -PIXI.InteractionManager.prototype.setTarget = function(target) -{ - this.target = target; - - //check if the dom element has been set. If it has don't do anything - if( this.interactionDOMElement === null ) { - - this.setTargetDomElement( target.view ); - } - - document.body.addEventListener('mouseup', this.onMouseUp, true); -} - - -/** - * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM - * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element - * to receive those events - * - * @method setTargetDomElement - * @param domElement {DOMElement} the dom element which will receive mouse and touch events - * @private - */ -PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) -{ - //remove previouse listeners - if( this.interactionDOMElement !== null ) - { - this.interactionDOMElement.style['-ms-content-zooming'] = ''; - this.interactionDOMElement.style['-ms-touch-action'] = ''; - - this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); - this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); - this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); - - // aint no multi touch just yet! - this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); - this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); - this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); - } - - - if (window.navigator.msPointerEnabled) - { - // time to remove some of that zoom in ja.. - domElement.style['-ms-content-zooming'] = 'none'; - domElement.style['-ms-touch-action'] = 'none'; - - // DO some window specific touch! - } - - this.interactionDOMElement = domElement; - - domElement.addEventListener('mousemove', this.onMouseMove, true); - domElement.addEventListener('mousedown', this.onMouseDown, true); - domElement.addEventListener('mouseout', this.onMouseOut, true); - - // aint no multi touch just yet! - domElement.addEventListener('touchstart', this.onTouchStart, true); - domElement.addEventListener('touchend', this.onTouchEnd, true); - domElement.addEventListener('touchmove', this.onTouchMove, true); -} - - -/** - * updates the state of interactive objects - * - * @method update - * @private - */ -PIXI.InteractionManager.prototype.update = function() -{ - if(!this.target)return; - - // frequency of 30fps?? - var now = Date.now(); - var diff = now - this.last; - diff = (diff * 30) / 1000; - if(diff < 1)return; - this.last = now; - // - - // ok.. so mouse events?? - // yes for now :) - // OPTIMSE - how often to check?? - if(this.dirty) - { - this.dirty = false; - - var len = this.interactiveItems.length; - - for (var i=0; i < len; i++) { - this.interactiveItems[i].interactiveChildren = false; - } - - this.interactiveItems = []; - - if(this.stage.interactive)this.interactiveItems.push(this.stage); - // go through and collect all the objects that are interactive.. - this.collectInteractiveSprite(this.stage, this.stage); - } - - // loop through interactive objects! - var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - - //if(!item.visible)continue; - - // OPTIMISATION - only calculate every time if the mousemove function exists.. - // OK so.. does the object have any other interactive functions? - // hit-test the clip! - - - if(item.mouseover || item.mouseout || item.buttonMode) - { - // ok so there are some functions so lets hit test it.. - item.__hit = this.hitTest(item, this.mouse); - this.mouse.target = item; - // ok so deal with interactions.. - // loks like there was a hit! - if(item.__hit) - { - if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; - - if(!item.__isOver) - { - - if(item.mouseover)item.mouseover(this.mouse); - item.__isOver = true; - } - } - else - { - if(item.__isOver) - { - // roll out! - if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; - } - } - } - - // ---> - } -} - -/** - * Is called when the mouse moves accross the renderer element - * - * @method onMouseMove - * @param event {Event} The DOM event of the mouse moving - * @private - */ -PIXI.InteractionManager.prototype.onMouseMove = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - // TODO optimize by not check EVERY TIME! maybe half as often? // - var rect = this.interactionDOMElement.getBoundingClientRect(); - - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); - - var length = this.interactiveItems.length; - var global = this.mouse.global; - - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mousemove) - { - //call the function! - item.mousemove(this.mouse); - } - } -} - -/** - * Is called when the mouse button is pressed down on the renderer element - * - * @method onMouseDown - * @param event {Event} The DOM event of a mouse button being pressed down - * @private - */ -PIXI.InteractionManager.prototype.onMouseDown = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - - // loop through inteaction tree... - // hit test each item! -> - // get interactive items under point?? - //stage.__i - var length = this.interactiveItems.length; - var global = this.mouse.global; - - var index = 0; - var parent = this.stage; - - // while - // hit test - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mousedown || item.click) - { - item.__mouseIsDown = true; - item.__hit = this.hitTest(item, this.mouse); - - if(item.__hit) - { - //call the function! - if(item.mousedown)item.mousedown(this.mouse); - item.__isDown = true; - - // just the one! - if(!item.interactiveChildren)break; - } - } - } -} - - -PIXI.InteractionManager.prototype.onMouseOut = function(event) -{ - var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.__isOver) - { - this.mouse.target = item; - if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; - } - } -} - -/** - * Is called when the mouse button is released on the renderer element - * - * @method onMouseUp - * @param event {Event} The DOM event of a mouse button being released - * @private - */ -PIXI.InteractionManager.prototype.onMouseUp = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - - var global = this.mouse.global; - - - var length = this.interactiveItems.length; - var up = false; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mouseup || item.mouseupoutside || item.click) - { - item.__hit = this.hitTest(item, this.mouse); - - if(item.__hit && !up) - { - //call the function! - if(item.mouseup) - { - item.mouseup(this.mouse); - } - if(item.__isDown) - { - if(item.click)item.click(this.mouse); - } - - if(!item.interactiveChildren)up = true; - } - else - { - if(item.__isDown) - { - if(item.mouseupoutside)item.mouseupoutside(this.mouse); - } - } - - item.__isDown = false; - } - } -} - -/** - * Tests if the current mouse coords hit a sprite - * - * @method hitTest - * @param item {DisplayObject} The displayObject to test for a hit - * @param interactionData {InteractionData} The interactiondata object to update in the case of a hit - * @private - */ -PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) -{ - var global = interactionData.global; - - if(item.vcount !== PIXI.visibleCount)return false; - - var isSprite = (item instanceof PIXI.Sprite), - worldTransform = item.worldTransform, - a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10), - x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, - y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - interactionData.target = item; - - //a sprite or display object with a hit area defined - if(item.hitArea && item.hitArea.contains) { - if(item.hitArea.contains(x, y)) { - //if(isSprite) - interactionData.target = item; - - return true; - } - - return false; - } - // a sprite with no hitarea defined - else if(isSprite) - { - var width = item.texture.frame.width, - height = item.texture.frame.height, - x1 = -width * item.anchor.x, - y1; - - if(x > x1 && x < x1 + width) - { - y1 = -height * item.anchor.y; - - if(y > y1 && y < y1 + height) - { - // set the target property if a hit is true! - interactionData.target = item - return true; - } - } - } - - var length = item.children.length; - - for (var i = 0; i < length; i++) - { - var tempItem = item.children[i]; - var hit = this.hitTest(tempItem, interactionData); - if(hit) - { - // hmm.. TODO SET CORRECT TARGET? - interactionData.target = item - return true; - } - } - - return false; -} - -/** - * Is called when a touch is moved accross the renderer element - * - * @method onTouchMove - * @param event {Event} The DOM event of a touch moving accross the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchMove = function(event) -{ - var rect = this.interactionDOMElement.getBoundingClientRect(); - var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - var touchData = this.touchs[touchEvent.identifier]; - touchData.originalEvent = event || window.event; - - // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - } - - var length = this.interactiveItems.length; - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - if(item.touchmove)item.touchmove(touchData); - } -} - -/** - * Is called when a touch is started on the renderer element - * - * @method onTouchStart - * @param event {Event} The DOM event of a touch starting on the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchStart = function(event) -{ - var rect = this.interactionDOMElement.getBoundingClientRect(); - - var changedTouches = event.changedTouches; - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - - var touchData = this.pool.pop(); - if(!touchData)touchData = new PIXI.InteractionData(); - - touchData.originalEvent = event || window.event; - - this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - - var length = this.interactiveItems.length; - - for (var j = 0; j < length; j++) - { - var item = this.interactiveItems[j]; - - if(item.touchstart || item.tap) - { - item.__hit = this.hitTest(item, touchData); - - if(item.__hit) - { - //call the function! - if(item.touchstart)item.touchstart(touchData); - item.__isDown = true; - item.__touchData = touchData; - - if(!item.interactiveChildren)break; - } - } - } - } -} - -/** - * Is called when a touch is ended on the renderer element - * - * @method onTouchEnd - * @param event {Event} The DOM event of a touch ending on the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchEnd = function(event) -{ - //this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.interactionDOMElement.getBoundingClientRect(); - var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - var touchData = this.touchs[touchEvent.identifier]; - var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - - var length = this.interactiveItems.length; - for (var j = 0; j < length; j++) - { - var item = this.interactiveItems[j]; - var itemTouchData = item.__touchData; // <-- Here! - item.__hit = this.hitTest(item, touchData); - - if(itemTouchData == touchData) - { - // so this one WAS down... - touchData.originalEvent = event || window.event; - // hitTest?? - - if(item.touchend || item.tap) - { - if(item.__hit && !up) - { - if(item.touchend)item.touchend(touchData); - if(item.__isDown) - { - if(item.tap)item.tap(touchData); - } - - if(!item.interactiveChildren)up = true; - } - else - { - if(item.__isDown) - { - if(item.touchendoutside)item.touchendoutside(touchData); - } - } - - item.__isDown = false; - } - - item.__touchData = null; - - } - else - { - - } - } - // remove the touch.. - this.pool.push(touchData); - this.touchs[touchEvent.identifier] = null; - } -} - -/** - * Holds all information related to an Interaction event - * - * @class InteractionData - * @constructor - */ -PIXI.InteractionData = function() -{ - /** - * This point stores the global coords of where the touch/mouse event happened - * - * @property global - * @type Point - */ - this.global = new PIXI.Point(); - - // this is here for legacy... but will remove - this.local = new PIXI.Point(); - - /** - * The target Sprite that was interacted with - * - * @property target - * @type Sprite - */ - this.target; - - /** - * When passed to an event handler, this will be the original DOM Event that was captured - * - * @property originalEvent - * @type Event - */ - this.originalEvent; -} - -/** - * This will return the local coords of the specified displayObject for this InteractionData - * - * @method getLocalPosition - * @param displayObject {DisplayObject} The DisplayObject that you would like the local coords off - * @return {Point} A point containing the coords of the InteractionData position relative to the DisplayObject - */ -PIXI.InteractionData.prototype.getLocalPosition = function(displayObject) -{ - var worldTransform = displayObject.worldTransform; - var global = this.global; - - // do a cheeky transform to get the mouse coords; - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - // set the mouse coords... - return new PIXI.Point(a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, - a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id) -} - -// constructor -PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Stage represents the root of the display tree. Everything connected to the stage is rendered - * - * @class Stage - * @extends DisplayObjectContainer - * @constructor - * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format - * like: 0xFFFFFF for white - */ -PIXI.Stage = function(backgroundColor) -{ - PIXI.DisplayObjectContainer.call( this ); - - /** - * [read-only] Current transform of the object based on world (parent) factors - * - * @property worldTransform - * @type Mat3 - * @readOnly - * @private - */ - this.worldTransform = PIXI.mat3.create(); - - /** - * Whether or not the stage is interactive - * - * @property interactive - * @type Boolean - */ - this.interactive = true; - - /** - * The interaction manage for this stage, manages all interactive activity on the stage - * - * @property interactive - * @type InteractionManager - */ - this.interactionManager = new PIXI.InteractionManager(this); - - /** - * Whether the stage is dirty and needs to have interactions updated - * - * @property dirty - * @type Boolean - * @private - */ - this.dirty = true; - - this.__childrenAdded = []; - this.__childrenRemoved = []; - - //the stage is it's own stage - this.stage = this; - - //optimize hit detection a bit - this.stage.hitArea = new PIXI.Rectangle(0,0,100000, 100000); - - this.setBackgroundColor(backgroundColor); - this.worldVisible = true; -} - -// constructor -PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Stage.prototype.constructor = PIXI.Stage; - -/** - * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. - * This is useful for when you have other DOM elements ontop of the Canvas element. - * - * @method setInteractionDelegate - * @param domElement {DOMElement} This new domElement which will receive mouse/touch events - */ -PIXI.Stage.prototype.setInteractionDelegate = function(domElement) -{ - this.interactionManager.setTargetDomElement( domElement ); -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.Stage.prototype.updateTransform = function() -{ - this.worldAlpha = 1; - this.vcount = PIXI.visibleCount; - - for(var i=0,j=this.children.length; i> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; -} - -/** - * A polyfill for Function.prototype.bind - * - * @method bind - */ -if (typeof Function.prototype.bind != 'function') { - Function.prototype.bind = (function () { - var slice = Array.prototype.slice; - return function (thisArg) { - var target = this, boundArgs = slice.call(arguments, 1); - - if (typeof target != 'function') throw new TypeError(); - - function bound() { - var args = boundArgs.concat(slice.call(arguments)); - target.apply(this instanceof bound ? this : thisArg, args); - } - - bound.prototype = (function F(proto) { - proto && (F.prototype = proto); - if (!(this instanceof F)) return new F; - })(target.prototype); - - return bound; - }; - })(); -} - -/** - * A wrapper for ajax requests to be handled cross browser - * - * @class AjaxRequest - * @constructor - */ -var AjaxRequest = PIXI.AjaxRequest = function() -{ - var activexmodes = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Microsoft.XMLHTTP"] //activeX versions to check for in IE - - if (window.ActiveXObject) - { //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken) - for (var i=0; i>>>>>>>>") - console.log("_") - var safe = 0; - var tmp = item.first; - console.log(tmp); - - while(tmp._iNext) - { - safe++; - tmp = tmp._iNext; - console.log(tmp); - // console.log(tmp); - - if(safe > 100) - { - console.log("BREAK") - break - } - } -} - - - - - - -/** - * https://github.com/mrdoob/eventtarget.js/ - * THankS mr DOob! - */ - -/** - * Adds event emitter functionality to a class - * - * @class EventTarget - * @example - * function MyEmitter() { - * PIXI.EventTarget.call(this); //mixes in event target stuff - * } - * - * var em = new MyEmitter(); - * em.emit({ type: 'eventName', data: 'some data' }); - */ -PIXI.EventTarget = function () { - - var listeners = {}; - - this.addEventListener = this.on = function ( type, listener ) { - - - if ( listeners[ type ] === undefined ) { - - listeners[ type ] = []; - - } - - if ( listeners[ type ].indexOf( listener ) === - 1 ) { - - listeners[ type ].push( listener ); - } - - }; - - this.dispatchEvent = this.emit = function ( event ) { - - if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { - - return; - - } - - for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { - - listeners[ event.type ][ i ]( event ); - - } - - }; - - this.removeEventListener = this.off = function ( type, listener ) { - - var index = listeners[ type ].indexOf( listener ); - - if ( index !== - 1 ) { - - listeners[ type ].splice( index, 1 ); - - } - - }; - -}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * This helper function will automatically detect which renderer you should be using. - * WebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by - * the browser then this function will return a canvas renderer - * - * @method autoDetectRenderer - * @static - * @param width {Number} the width of the renderers view - * @param height {Number} the height of the renderers view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) - * - * antialias - */ -PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) -{ - if(!width)width = 800; - if(!height)height = 600; - - // BORROWED from Mr Doob (mrdoob.com) - var webgl = ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(); - - //console.log(webgl); - if( webgl ) - { - return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); - } - - return new PIXI.CanvasRenderer(width, height, view, transparent); -}; - - - -/* - PolyK library - url: http://polyk.ivank.net - Released under MIT licence. - - Copyright (c) 2012 Ivan Kuckir - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - - This is an amazing lib! - - slightly modified by mat groves (matgroves.com); -*/ - -PIXI.PolyK = {}; - -/** - * Triangulates shapes for webGL graphic fills - * - * @method Triangulate - * @namespace PolyK - * @constructor - */ -PIXI.PolyK.Triangulate = function(p) -{ - var sign = true; - - var n = p.length>>1; - if(n<3) return []; - var tgs = []; - var avl = []; - for(var i=0; i 3) - { - var i0 = avl[(i+0)%al]; - var i1 = avl[(i+1)%al]; - var i2 = avl[(i+2)%al]; - - var ax = p[2*i0], ay = p[2*i0+1]; - var bx = p[2*i1], by = p[2*i1+1]; - var cx = p[2*i2], cy = p[2*i2+1]; - - var earFound = false; - if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) - { - earFound = true; - for(var j=0; j 3*al) - { - // need to flip flip reverse it! - // reset! - if(sign) - { - var tgs = []; - avl = []; - for(var i=0; i= 0) && (v >= 0) && (u + v < 1); -} - -/** - * Checks if a shape is convex - * - * @class _convex - * @namespace PolyK - * @private - */ -PIXI.PolyK._convex = function(ax, ay, bx, by, cx, cy, sign) -{ - return ((ay-by)*(cx-bx) + (bx-ax)*(cy-by) >= 0) == sign; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/* - * the default suoer fast shader! - */ - -PIXI.shaderFragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", - "gl_FragColor = gl_FragColor * vColor;", - "}" -]; - -PIXI.shaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - - "uniform vec2 projectionVector;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "void main(void) {", - "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" -]; - -/* - * the triangle strip shader.. - */ - -PIXI.stripShaderFragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform float alpha;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", - "gl_FragColor = gl_FragColor * alpha;", - "}" -]; - - -PIXI.stripShaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" -]; - -/* - * primitive shader.. - */ - -PIXI.primitiveShaderFragmentSrc = [ - "precision mediump float;", - "varying vec4 vColor;", - "void main(void) {", - "gl_FragColor = vColor;", - "}" -]; - -PIXI.primitiveShaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec4 aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "uniform float alpha;", - "varying vec4 vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vColor = aColor * alpha;", - "}" -]; - -PIXI.shaderStack = []; - -PIXI.initPrimitiveShader = function() -{ - var gl = PIXI.gl; - - var shaderProgram = PIXI.compileProgram(PIXI.primitiveShaderVertexSrc, PIXI.primitiveShaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); - - - //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - //gl.enableVertexAttribArray(shaderProgram.colorAttribute); -//gl.enableVertexAttribArray(program.textureCoordAttribute); - - shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); - - PIXI.primitiveProgram = shaderProgram; - - -} - -PIXI.initDefaultShader = function() -{ - PIXI.defaultShader = new PIXI.PixiShader(); - PIXI.defaultShader.init(); - PIXI.activateShader(PIXI.defaultShader); - /* - PIXI.shaderStack.push(PIXI.defaultShader); - PIXI.current*/ -} - -PIXI.initDefaultStripShader = function() -{ - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.stripShaderVertexSrc, PIXI.stripShaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); - shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); - - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.stripShaderProgram = shaderProgram; -} - -PIXI.CompileVertexShader = function(gl, shaderSrc) -{ - return PIXI._CompileShader(gl, shaderSrc, gl.VERTEX_SHADER); -} - -PIXI.CompileFragmentShader = function(gl, shaderSrc) -{ - return PIXI._CompileShader(gl, shaderSrc, gl.FRAGMENT_SHADER); -} - -PIXI._CompileShader = function(gl, shaderSrc, shaderType) -{ - var src = shaderSrc.join("\n"); - var shader = gl.createShader(shaderType); - gl.shaderSource(shader, src); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - alert(gl.getShaderInfoLog(shader)); - return null; - } - - return shader; -} - - -PIXI.compileProgram = function(vertexSrc, fragmentSrc) -{ - var gl = PIXI.gl; - var fragmentShader = PIXI.CompileFragmentShader(gl, fragmentSrc); - var vertexShader = PIXI.CompileVertexShader(gl, vertexSrc); - - var shaderProgram = gl.createProgram(); - - gl.attachShader(shaderProgram, vertexShader); - gl.attachShader(shaderProgram, fragmentShader); - gl.linkProgram(shaderProgram); - - if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { - alert("Could not initialise shaders"); - } - - return shaderProgram; -} - -PIXI.activateShader = function(shader) -{ - PIXI.shaderStack.push(shader); - - //console.log(">>>") - var gl = PIXI.gl; - - var shaderProgram = shader.program; - - // map uniforms.. - gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - - shader.syncUniforms(); - - PIXI.currentShader = shaderProgram; -} - - -PIXI.popShader = function() -{ - var gl = PIXI.gl; - // activate last program.. - var lastProgram = PIXI.shaderStack.pop(); - - var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; - - gl.useProgram(shaderProgram); - - PIXI.currentShader = shaderProgram; -} - -PIXI.activatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.primitiveProgram); - - //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); - //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); - gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); - - //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); - //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); -} - -PIXI.deactivatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.currentShader); - - gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); - //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); - //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -PIXI.PixiShader = function() -{ - // the webGL program.. - this.program; - - this.fragmentSrc = [ - "precision lowp float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", - "}" - ]; - -} - -PIXI.PixiShader.prototype.init = function() -{ - var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) - - var gl = PIXI.gl; - - gl.useProgram(program); - - // get the default shader bits! - program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); - program.colorAttribute = gl.getAttribLocation(program, "aColor"); - program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); - - program.projectionVector = gl.getUniformLocation(program, "projectionVector"); - program.samplerUniform = gl.getUniformLocation(program, "uSampler"); - - // add those custom shaders! - for (var key in this.uniforms) - { - // get the uniform locations.. - program[key] = gl.getUniformLocation(program, key); - } - - this.program = program; -} - -PIXI.PixiShader.prototype.syncUniforms = function() -{ - var gl = PIXI.gl; - - for (var key in this.uniforms) - { - //var - var type = this.uniforms[key].type; - - // need to grow this! - if(type == "f") - { - gl.uniform1f(this.program[key], this.uniforms[key].value); - } - else if(type == "mat4") - { - gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); - } - } - -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A set of functions used by the webGL renderer to draw the primitive graphics data - * - * @class CanvasGraphics - */ -PIXI.WebGLGraphics = function() -{ - -} - -/** - * Renders the graphics object - * - * @static - * @private - * @method renderGraphics - * @param graphics {Graphics} - * @param projection {Object} - */ -PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) -{ - var gl = PIXI.gl; - - if(!graphics._webGL)graphics._webGL = {points:[], indices:[], lastIndex:0, - buffer:gl.createBuffer(), - indexBuffer:gl.createBuffer()}; - - if(graphics.dirty) - { - graphics.dirty = false; - - if(graphics.clearDirty) - { - graphics.clearDirty = false; - - graphics._webGL.lastIndex = 0; - graphics._webGL.points = []; - graphics._webGL.indices = []; - - } - - PIXI.WebGLGraphics.updateGraphics(graphics); - } - - - PIXI.activatePrimitiveShader(); - - // This could be speeded up fo sure! - var m = PIXI.mat3.clone(graphics.worldTransform); - - PIXI.mat3.transpose(m); - - // set the matrix transform for the - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - gl.uniformMatrix3fv(PIXI.primitiveProgram.translationMatrix, false, m); - - gl.uniform2f(PIXI.primitiveProgram.projectionVector, projection.x, projection.y); - - gl.uniform1f(PIXI.primitiveProgram.alpha, graphics.worldAlpha); - - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - - // WHY DOES THIS LINE NEED TO BE THERE??? - //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - // its not even used.. but need to be set or it breaks? - // only on pc though.. - - gl.vertexAttribPointer(PIXI.primitiveProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 4 * 6, 0); - gl.vertexAttribPointer(PIXI.primitiveProgram.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4); - - // set the index buffer! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); - - gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); - - PIXI.deactivatePrimitiveShader(); - - // return to default shader... -// PIXI.activateShader(PIXI.defaultShader); -} - -/** - * Updates the graphics object - * - * @static - * @private - * @method updateGraphics - * @param graphics {Graphics} - */ -PIXI.WebGLGraphics.updateGraphics = function(graphics) -{ - for (var i=graphics._webGL.lastIndex; i < graphics.graphicsData.length; i++) - { - var data = graphics.graphicsData[i]; - - if(data.type == PIXI.Graphics.POLY) - { - if(data.fill) - { - if(data.points.length>3) - PIXI.WebGLGraphics.buildPoly(data, graphics._webGL); - } - - if(data.lineWidth > 0) - { - PIXI.WebGLGraphics.buildLine(data, graphics._webGL); - } - } - else if(data.type == PIXI.Graphics.RECT) - { - PIXI.WebGLGraphics.buildRectangle(data, graphics._webGL); - } - else if(data.type == PIXI.Graphics.CIRC || data.type == PIXI.Graphics.ELIP) - { - PIXI.WebGLGraphics.buildCircle(data, graphics._webGL); - } - }; - - graphics._webGL.lastIndex = graphics.graphicsData.length; - - var gl = PIXI.gl; - - graphics._webGL.glPoints = new Float32Array(graphics._webGL.points); - - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - gl.bufferData(gl.ARRAY_BUFFER, graphics._webGL.glPoints, gl.STATIC_DRAW); - - graphics._webGL.glIndicies = new Uint16Array(graphics._webGL.indices); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.glIndicies, gl.STATIC_DRAW); -} - -/** - * Builds a rectangle to draw - * - * @static - * @private - * @method buildRectangle - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData) -{ - // --- // - // need to convert points to a nice regular data - // - var rectData = graphicsData.points; - var x = rectData[0]; - var y = rectData[1]; - var width = rectData[2]; - var height = rectData[3]; - - - if(graphicsData.fill) - { - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var verts = webGLData.points; - var indices = webGLData.indices; - - var vertPos = verts.length/6; - - // start - verts.push(x, y); - verts.push(r, g, b, alpha); - - verts.push(x + width, y); - verts.push(r, g, b, alpha); - - verts.push(x , y + height); - verts.push(r, g, b, alpha); - - verts.push(x + width, y + height); - verts.push(r, g, b, alpha); - - // insert 2 dead triangles.. - indices.push(vertPos, vertPos, vertPos+1, vertPos+2, vertPos+3, vertPos+3) - } - - if(graphicsData.lineWidth) - { - graphicsData.points = [x, y, - x + width, y, - x + width, y + height, - x, y + height, - x, y]; - - PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); - } - -} - -/** - * Builds a circle to draw - * - * @static - * @private - * @method buildCircle - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData) -{ - // --- // - // need to convert points to a nice regular data - // - var rectData = graphicsData.points; - var x = rectData[0]; - var y = rectData[1]; - var width = rectData[2]; - var height = rectData[3]; - - var totalSegs = 40; - var seg = (Math.PI * 2) / totalSegs ; - - if(graphicsData.fill) - { - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var verts = webGLData.points; - var indices = webGLData.indices; - - var vecPos = verts.length/6; - - indices.push(vecPos); - - for (var i=0; i < totalSegs + 1 ; i++) - { - verts.push(x,y, r, g, b, alpha); - - verts.push(x + Math.sin(seg * i) * width, - y + Math.cos(seg * i) * height, - r, g, b, alpha); - - indices.push(vecPos++, vecPos++); - }; - - indices.push(vecPos-1); - } - - if(graphicsData.lineWidth) - { - graphicsData.points = []; - - for (var i=0; i < totalSegs + 1; i++) - { - graphicsData.points.push(x + Math.sin(seg * i) * width, - y + Math.cos(seg * i) * height) - }; - - PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); - } - -} - -/** - * Builds a line to draw - * - * @static - * @private - * @method buildLine - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) -{ - // TODO OPTIMISE! - - var wrap = true; - var points = graphicsData.points; - if(points.length == 0)return; - - // get first and last point.. figure out the middle! - var firstPoint = new PIXI.Point( points[0], points[1] ); - var lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - - // if the first point is the last point - goona have issues :) - if(firstPoint.x == lastPoint.x && firstPoint.y == lastPoint.y) - { - points.pop(); - points.pop(); - - lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - - var midPointX = lastPoint.x + (firstPoint.x - lastPoint.x) *0.5; - var midPointY = lastPoint.y + (firstPoint.y - lastPoint.y) *0.5; - - points.unshift(midPointX, midPointY); - points.push(midPointX, midPointY) - } - - var verts = webGLData.points; - var indices = webGLData.indices; - var length = points.length / 2; - var indexCount = points.length; - var indexStart = verts.length/6; - - // DRAW the Line - var width = graphicsData.lineWidth / 2; - - // sort color - var color = HEXtoRGB(graphicsData.lineColor); - var alpha = graphicsData.lineAlpha; - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var p1x, p1y, p2x, p2y, p3x, p3y; - var perpx, perpy, perp2x, perp2y, perp3x, perp3y; - var ipx, ipy; - var a1, b1, c1, a2, b2, c2; - var denom, pdist, dist; - - p1x = points[0]; - p1y = points[1]; - - p2x = points[2]; - p2y = points[3]; - - perpx = -(p1y - p2y); - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - // start - verts.push(p1x - perpx , p1y - perpy, - r, g, b, alpha); - - verts.push(p1x + perpx , p1y + perpy, - r, g, b, alpha); - - for (var i = 1; i < length-1; i++) - { - p1x = points[(i-1)*2]; - p1y = points[(i-1)*2 + 1]; - - p2x = points[(i)*2] - p2y = points[(i)*2 + 1] - - p3x = points[(i+1)*2]; - p3y = points[(i+1)*2 + 1]; - - perpx = -(p1y - p2y); - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - perp2x = -(p2y - p3y); - perp2y = p2x - p3x; - - dist = Math.sqrt(perp2x*perp2x + perp2y*perp2y); - perp2x /= dist; - perp2y /= dist; - perp2x *= width; - perp2y *= width; - - a1 = (-perpy + p1y) - (-perpy + p2y); - b1 = (-perpx + p2x) - (-perpx + p1x); - c1 = (-perpx + p1x) * (-perpy + p2y) - (-perpx + p2x) * (-perpy + p1y); - a2 = (-perp2y + p3y) - (-perp2y + p2y); - b2 = (-perp2x + p2x) - (-perp2x + p3x); - c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y); - - denom = a1*b2 - a2*b1; - - if (denom == 0) { - denom+=1; - } - - px = (b1*c2 - b2*c1)/denom; - py = (a2*c1 - a1*c2)/denom; - - pdist = (px -p2x) * (px -p2x) + (py -p2y) + (py -p2y); - - if(pdist > 140 * 140) - { - perp3x = perpx - perp2x; - perp3y = perpy - perp2y; - - dist = Math.sqrt(perp3x*perp3x + perp3y*perp3y); - perp3x /= dist; - perp3y /= dist; - perp3x *= width; - perp3y *= width; - - verts.push(p2x - perp3x, p2y -perp3y); - verts.push(r, g, b, alpha); - - verts.push(p2x + perp3x, p2y +perp3y); - verts.push(r, g, b, alpha); - - verts.push(p2x - perp3x, p2y -perp3y); - verts.push(r, g, b, alpha); - - indexCount++; - } - else - { - verts.push(px , py); - verts.push(r, g, b, alpha); - - verts.push(p2x - (px-p2x), p2y - (py - p2y)); - verts.push(r, g, b, alpha); - } - } - - p1x = points[(length-2)*2] - p1y = points[(length-2)*2 + 1] - - p2x = points[(length-1)*2] - p2y = points[(length-1)*2 + 1] - - perpx = -(p1y - p2y) - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - verts.push(p2x - perpx , p2y - perpy) - verts.push(r, g, b, alpha); - - verts.push(p2x + perpx , p2y + perpy) - verts.push(r, g, b, alpha); - - indices.push(indexStart); - - for (var i=0; i < indexCount; i++) - { - indices.push(indexStart++); - }; - - indices.push(indexStart-1); -} - -/** - * Builds a polygon to draw - * - * @static - * @private - * @method buildPoly - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData) -{ - var points = graphicsData.points; - if(points.length < 6)return; - - // get first and last point.. figure out the middle! - var verts = webGLData.points; - var indices = webGLData.indices; - - var length = points.length / 2; - - // sort color - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var triangles = PIXI.PolyK.Triangulate(points); - - var vertPos = verts.length / 6; - - for (var i=0; i < triangles.length; i+=3) - { - indices.push(triangles[i] + vertPos); - indices.push(triangles[i] + vertPos); - indices.push(triangles[i+1] + vertPos); - indices.push(triangles[i+2] +vertPos); - indices.push(triangles[i+2] + vertPos); - }; - - for (var i = 0; i < length; i++) - { - verts.push(points[i * 2], points[i * 2 + 1], - r, g, b, alpha); - }; -} - -function HEXtoRGB(hex) { - return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; -} - - - - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI._defaultFrame = new PIXI.Rectangle(0,0,1,1); - -// an instance of the gl context.. -// only one at the moment :/ -PIXI.gl; - -/** - * the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer - * should be used for browsers support webGL. This Render works by automatically managing webGLBatchs. - * So no need for Sprite Batch's or Sprite Cloud's - * Dont forget to add the view to your DOM or you will not see anything :) - * - * @class WebGLRenderer - * @constructor - * @param width=0 {Number} the width of the canvas view - * @param height=0 {Number} the height of the canvas view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) - * - */ -PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) -{ - // do a catch.. only 1 webGL renderer.. - - this.transparent = !!transparent; - - this.width = width || 800; - this.height = height || 600; - - this.view = view || document.createElement( 'canvas' ); - this.view.width = this.width; - this.view.height = this.height; - - // deal with losing context.. - var scope = this; - this.view.addEventListener('webglcontextlost', function(event) { scope.handleContextLost(event); }, false) - this.view.addEventListener('webglcontextrestored', function(event) { scope.handleContextRestored(event); }, false) - - this.batchs = []; - - try - { - PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { - alpha: this.transparent, - antialias:!!antialias, // SPEED UP?? - premultipliedAlpha:false, - stencil:true - }); - } - catch (e) - { - throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); - } - - PIXI.initDefaultShader(); - PIXI.initPrimitiveShader(); - PIXI.initDefaultStripShader(); - - -// PIXI.activateDefaultShader(); - - var gl = this.gl; - PIXI.WebGLRenderer.gl = gl; - - this.batch = new PIXI.WebGLBatch(gl); - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - - gl.enable(gl.BLEND); - gl.colorMask(true, true, true, this.transparent); - - PIXI.projection = new PIXI.Point(400, 300); - - this.resize(this.width, this.height); - this.contextLost = false; - - PIXI.activateShader(PIXI.defaultShader); - - this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); - -} - -// constructor -PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; - -/** - * Gets a new WebGLBatch from the pool - * - * @static - * @method getBatch - * @return {WebGLBatch} - * @private - */ -PIXI.WebGLRenderer.getBatch = function() -{ - if(PIXI._batchs.length == 0) - { - return new PIXI.WebGLBatch(PIXI.WebGLRenderer.gl); - } - else - { - return PIXI._batchs.pop(); - } -} - -/** - * Puts a batch back into the pool - * - * @static - * @method returnBatch - * @param batch {WebGLBatch} The batch to return - * @private - */ -PIXI.WebGLRenderer.returnBatch = function(batch) -{ - batch.clean(); - PIXI._batchs.push(batch); -} - -/** - * Renders the stage to its webGL view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.WebGLRenderer.prototype.render = function(stage) -{ - if(this.contextLost)return; - - - // if rendering a new stage clear the batchs.. - if(this.__stage !== stage) - { - // TODO make this work - // dont think this is needed any more? - this.__stage = stage; - this.stageRenderGroup.setRenderable(stage); - } - - // TODO not needed now... - // update children if need be - // best to remove first! - /*for (var i=0; i < stage.__childrenRemoved.length; i++) - { - var group = stage.__childrenRemoved[i].__renderGroup - if(group)group.removeDisplayObject(stage.__childrenRemoved[i]); - }*/ - - // update any textures - PIXI.WebGLRenderer.updateTextures(); - - // update the scene graph - PIXI.visibleCount++; - stage.updateTransform(); - - var gl = this.gl; - - // -- Does this need to be set every frame? -- // - gl.colorMask(true, true, true, this.transparent); - gl.viewport(0, 0, this.width, this.height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); - gl.clear(gl.COLOR_BUFFER_BIT); - - // HACK TO TEST - - this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; - this.stageRenderGroup.render(PIXI.projection); - - // interaction - // run interaction! - if(stage.interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - - // after rendering lets confirm all frames that have been uodated.. - if(PIXI.Texture.frameUpdates.length > 0) - { - for (var i=0; i < PIXI.Texture.frameUpdates.length; i++) - { - PIXI.Texture.frameUpdates[i].updateFrame = false; - }; - - PIXI.Texture.frameUpdates = []; - } -} - -/** - * Updates the textures loaded into this webgl renderer - * - * @static - * @method updateTextures - * @private - */ -PIXI.WebGLRenderer.updateTextures = function() -{ - //TODO break this out into a texture manager... - for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); - PIXI.texturesToUpdate = []; - PIXI.texturesToDestroy = []; -} - -/** - * Updates a loaded webgl texture - * - * @static - * @method updateTexture - * @param texture {Texture} The texture to update - * @private - */ -PIXI.WebGLRenderer.updateTexture = function(texture) -{ - //TODO break this out into a texture manager... - var gl = PIXI.gl; - - if(!texture._glTexture) - { - texture._glTexture = gl.createTexture(); - } - - if(texture.hasLoaded) - { - gl.bindTexture(gl.TEXTURE_2D, texture._glTexture); - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - - // reguler... - - if(!texture._powerOf2) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - } - - gl.bindTexture(gl.TEXTURE_2D, null); - } -} - -/** - * Destroys a loaded webgl texture - * - * @method destroyTexture - * @param texture {Texture} The texture to update - * @private - */ -PIXI.WebGLRenderer.destroyTexture = function(texture) -{ - //TODO break this out into a texture manager... - var gl = PIXI.gl; - - if(texture._glTexture) - { - texture._glTexture = gl.createTexture(); - gl.deleteTexture(gl.TEXTURE_2D, texture._glTexture); - } -} - -/** - * resizes the webGL view to the specified width and height - * - * @method resize - * @param width {Number} the new width of the webGL view - * @param height {Number} the new height of the webGL view - */ -PIXI.WebGLRenderer.prototype.resize = function(width, height) -{ - this.width = width; - this.height = height; - - this.view.width = width; - this.view.height = height; - - this.gl.viewport(0, 0, this.width, this.height); - - //var projectionMatrix = this.projectionMatrix; - - PIXI.projection.x = this.width/2; - PIXI.projection.y = this.height/2; - -// projectionMatrix[0] = 2/this.width; -// projectionMatrix[5] = -2/this.height; -// projectionMatrix[12] = -1; -// projectionMatrix[13] = 1; -} - -/** - * Handles a lost webgl context - * - * @method handleContextLost - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextLost = function(event) -{ - event.preventDefault(); - this.contextLost = true; -} - -/** - * Handles a restored webgl context - * - * @method handleContextRestored - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextRestored = function(event) -{ - this.gl = this.view.getContext("experimental-webgl", { - alpha: true - }); - - this.initShaders(); - - for(var key in PIXI.TextureCache) - { - var texture = PIXI.TextureCache[key].baseTexture; - texture._glTexture = null; - PIXI.WebGLRenderer.updateTexture(texture); - }; - - for (var i=0; i < this.batchs.length; i++) - { - this.batchs[i].restoreLostContext(this.gl)// - this.batchs[i].dirty = true; - }; - - PIXI._restoreBatchs(this.gl); - - this.contextLost = false; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI._batchs = []; - -/** - * @private - */ -PIXI._getBatch = function(gl) -{ - if(PIXI._batchs.length == 0) - { - return new PIXI.WebGLBatch(gl); - } - else - { - return PIXI._batchs.pop(); - } -} - -/** - * @private - */ -PIXI._returnBatch = function(batch) -{ - batch.clean(); - PIXI._batchs.push(batch); -} - -/** - * @private - */ -PIXI._restoreBatchs = function(gl) -{ - for (var i=0; i < PIXI._batchs.length; i++) - { - PIXI._batchs[i].restoreLostContext(gl); - }; -} - -/** - * A WebGLBatch Enables a group of sprites to be drawn using the same settings. - * if a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch. - * All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites - * in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled - * automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster - * the webGL renderer will run. - * - * @class WebGLBatch - * @constructor - * @param gl {WebGLContext} an instance of the webGL context - */ -PIXI.WebGLBatch = function(gl) -{ - this.gl = gl; - - this.size = 0; - - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); - this.blendMode = PIXI.blendModes.NORMAL; - this.dynamicSize = 1; -} - -// constructor -PIXI.WebGLBatch.prototype.constructor = PIXI.WebGLBatch; - -/** - * Cleans the batch so that is can be returned to an object pool and reused - * - * @method clean - */ -PIXI.WebGLBatch.prototype.clean = function() -{ - this.verticies = []; - this.uvs = []; - this.indices = []; - this.colors = []; - this.dynamicSize = 1; - this.texture = null; - this.last = null; - this.size = 0; - this.head; - this.tail; -} - -/** - * Recreates the buffers in the event of a context loss - * - * @method restoreLostContext - * @param gl {WebGLContext} - */ -PIXI.WebGLBatch.prototype.restoreLostContext = function(gl) -{ - this.gl = gl; - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); -} - -/** - * inits the batch's texture and blend mode based if the supplied sprite - * - * @method init - * @param sprite {Sprite} the first sprite to be added to the batch. Only sprites with - * the same base texture and blend mode will be allowed to be added to this batch - */ -PIXI.WebGLBatch.prototype.init = function(sprite) -{ - sprite.batch = this; - this.dirty = true; - this.blendMode = sprite.blendMode; - this.texture = sprite.texture.baseTexture; - this.head = sprite; - this.tail = sprite; - this.size = 1; - - this.growBatch(); -} - -/** - * inserts a sprite before the specified sprite - * - * @method insertBefore - * @param sprite {Sprite} the sprite to be added - * @param nextSprite {nextSprite} the first sprite will be inserted before this sprite - */ -PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) -{ - this.size++; - - sprite.batch = this; - this.dirty = true; - var tempPrev = nextSprite.__prev; - nextSprite.__prev = sprite; - sprite.__next = nextSprite; - - if(tempPrev) - { - sprite.__prev = tempPrev; - tempPrev.__next = sprite; - } - else - { - this.head = sprite; - } -} - -/** - * inserts a sprite after the specified sprite - * - * @method insertAfter - * @param sprite {Sprite} the sprite to be added - * @param previousSprite {Sprite} the first sprite will be inserted after this sprite - */ -PIXI.WebGLBatch.prototype.insertAfter = function(sprite, previousSprite) -{ - this.size++; - - sprite.batch = this; - this.dirty = true; - - var tempNext = previousSprite.__next; - previousSprite.__next = sprite; - sprite.__prev = previousSprite; - - if(tempNext) - { - sprite.__next = tempNext; - tempNext.__prev = sprite; - } - else - { - this.tail = sprite - } -} - -/** - * removes a sprite from the batch - * - * @method remove - * @param sprite {Sprite} the sprite to be removed - */ -PIXI.WebGLBatch.prototype.remove = function(sprite) -{ - this.size--; - - if(this.size == 0) - { - sprite.batch = null; - sprite.__prev = null; - sprite.__next = null; - return; - } - - if(sprite.__prev) - { - sprite.__prev.__next = sprite.__next; - } - else - { - this.head = sprite.__next; - this.head.__prev = null; - } - - if(sprite.__next) - { - sprite.__next.__prev = sprite.__prev; - } - else - { - this.tail = sprite.__prev; - this.tail.__next = null - } - - sprite.batch = null; - sprite.__next = null; - sprite.__prev = null; - this.dirty = true; -} - -/** - * Splits the batch into two with the specified sprite being the start of the new batch. - * - * @method split - * @param sprite {Sprite} the sprite that indicates where the batch should be split - * @return {WebGLBatch} the new batch - */ -PIXI.WebGLBatch.prototype.split = function(sprite) -{ - this.dirty = true; - - var batch = new PIXI.WebGLBatch(this.gl); - batch.init(sprite); - batch.texture = this.texture; - batch.tail = this.tail; - - this.tail = sprite.__prev; - this.tail.__next = null; - - sprite.__prev = null; - // return a splite batch! - - // TODO this size is wrong! - // need to recalculate :/ problem with a linked list! - // unless it gets calculated in the "clean"? - - // need to loop through items as there is no way to know the length on a linked list :/ - var tempSize = 0; - while(sprite) - { - tempSize++; - sprite.batch = batch; - sprite = sprite.__next; - } - - batch.size = tempSize; - this.size -= tempSize; - - return batch; -} - -/** - * Merges two batchs together - * - * @method merge - * @param batch {WebGLBatch} the batch that will be merged - */ -PIXI.WebGLBatch.prototype.merge = function(batch) -{ - this.dirty = true; - - this.tail.__next = batch.head; - batch.head.__prev = this.tail; - - this.size += batch.size; - - this.tail = batch.tail; - - var sprite = batch.head; - while(sprite) - { - sprite.batch = this; - sprite = sprite.__next; - } -} - -/** - * Grows the size of the batch. As the elements in the batch cannot have a dynamic size this - * function is used to increase the size of the batch. It also creates a little extra room so - * that the batch does not need to be resized every time a sprite is added - * - * @method growBatch - */ -PIXI.WebGLBatch.prototype.growBatch = function() -{ - var gl = this.gl; - if( this.size == 1) - { - this.dynamicSize = 1; - } - else - { - this.dynamicSize = this.size * 1.5 - } - // grow verts - this.verticies = new Float32Array(this.dynamicSize * 8); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); - - this.uvs = new Float32Array( this.dynamicSize * 8 ); - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); - - this.dirtyUVS = true; - - this.colors = new Float32Array( this.dynamicSize * 4 ); - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); - - this.dirtyColors = true; - - this.indices = new Uint16Array(this.dynamicSize * 6); - var length = this.indices.length/6; - - for (var i=0; i < length; i++) - { - var index2 = i * 6; - var index3 = i * 4; - this.indices[index2 + 0] = index3 + 0; - this.indices[index2 + 1] = index3 + 1; - this.indices[index2 + 2] = index3 + 2; - this.indices[index2 + 3] = index3 + 0; - this.indices[index2 + 4] = index3 + 2; - this.indices[index2 + 5] = index3 + 3; - }; - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); -} - -/** - * Refresh's all the data in the batch and sync's it with the webGL buffers - * - * @method refresh - */ -PIXI.WebGLBatch.prototype.refresh = function() -{ - var gl = this.gl; - - if (this.dynamicSize < this.size) - { - this.growBatch(); - } - - var indexRun = 0; - var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index; - var a, b, c, d, tx, ty; - - var displayObject = this.head; - - while(displayObject) - { - index = indexRun * 8; - - var texture = displayObject.texture; - - var frame = texture.frame; - var tw = texture.baseTexture.width; - var th = texture.baseTexture.height; - - this.uvs[index + 0] = frame.x / tw; - this.uvs[index +1] = frame.y / th; - - this.uvs[index +2] = (frame.x + frame.width) / tw; - this.uvs[index +3] = frame.y / th; - - this.uvs[index +4] = (frame.x + frame.width) / tw; - this.uvs[index +5] = (frame.y + frame.height) / th; - - this.uvs[index +6] = frame.x / tw; - this.uvs[index +7] = (frame.y + frame.height) / th; - - displayObject.updateFrame = false; - - colorIndex = indexRun * 4; - this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; - - displayObject = displayObject.__next; - - indexRun ++; - } - - this.dirtyUVS = true; - this.dirtyColors = true; -} - -/** - * Updates all the relevant geometry and uploads the data to the GPU - * - * @method update - */ -PIXI.WebGLBatch.prototype.update = function() -{ - var gl = this.gl; - var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index, index2, index3 - - var a, b, c, d, tx, ty; - - var indexRun = 0; - - var displayObject = this.head; - - while(displayObject) - { - if(displayObject.vcount === PIXI.visibleCount) - { - width = displayObject.texture.frame.width; - height = displayObject.texture.frame.height; - - // TODO trim?? - aX = displayObject.anchor.x;// - displayObject.texture.trim.x - aY = displayObject.anchor.y; //- displayObject.texture.trim.y - w0 = width * (1-aX); - w1 = width * -aX; - - h0 = height * (1-aY); - h1 = height * -aY; - - index = indexRun * 8; - - worldTransform = displayObject.worldTransform; - - a = worldTransform[0]; - b = worldTransform[3]; - c = worldTransform[1]; - d = worldTransform[4]; - tx = worldTransform[2]; - ty = worldTransform[5]; - - this.verticies[index + 0 ] = a * w1 + c * h1 + tx; - this.verticies[index + 1 ] = d * h1 + b * w1 + ty; - - this.verticies[index + 2 ] = a * w0 + c * h1 + tx; - this.verticies[index + 3 ] = d * h1 + b * w0 + ty; - - this.verticies[index + 4 ] = a * w0 + c * h0 + tx; - this.verticies[index + 5 ] = d * h0 + b * w0 + ty; - - this.verticies[index + 6] = a * w1 + c * h0 + tx; - this.verticies[index + 7] = d * h0 + b * w1 + ty; - - if(displayObject.updateFrame || displayObject.texture.updateFrame) - { - this.dirtyUVS = true; - - var texture = displayObject.texture; - - var frame = texture.frame; - var tw = texture.baseTexture.width; - var th = texture.baseTexture.height; - - this.uvs[index + 0] = frame.x / tw; - this.uvs[index +1] = frame.y / th; - - this.uvs[index +2] = (frame.x + frame.width) / tw; - this.uvs[index +3] = frame.y / th; - - this.uvs[index +4] = (frame.x + frame.width) / tw; - this.uvs[index +5] = (frame.y + frame.height) / th; - - this.uvs[index +6] = frame.x / tw; - this.uvs[index +7] = (frame.y + frame.height) / th; - - displayObject.updateFrame = false; - } - - // TODO this probably could do with some optimisation.... - if(displayObject.cacheAlpha != displayObject.worldAlpha) - { - displayObject.cacheAlpha = displayObject.worldAlpha; - - var colorIndex = indexRun * 4; - this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; - this.dirtyColors = true; - } - } - else - { - index = indexRun * 8; - - this.verticies[index + 0 ] = 0; - this.verticies[index + 1 ] = 0; - - this.verticies[index + 2 ] = 0; - this.verticies[index + 3 ] = 0; - - this.verticies[index + 4 ] = 0; - this.verticies[index + 5 ] = 0; - - this.verticies[index + 6] = 0; - this.verticies[index + 7] = 0; - } - - indexRun++; - displayObject = displayObject.__next; - } -} - -/** - * Draws the batch to the frame buffer - * - * @method render - */ -PIXI.WebGLBatch.prototype.render = function(start, end) -{ - start = start || 0; - - if(end == undefined)end = this.size; - - if(this.dirty) - { - this.refresh(); - this.dirty = false; - } - - if (this.size == 0)return; - - this.update(); - var gl = this.gl; - - //TODO optimize this! - - var shaderProgram = PIXI.currentShader; - - //gl.useProgram(shaderProgram); - - // update the verts.. - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - // ok.. - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - // update the uvs - var isDefault = (shaderProgram == PIXI.shaderProgram) - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - - if(this.dirtyUVS) - { - this.dirtyUVS = false; - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvs); - } - - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this.texture._glTexture); - - // update color! - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - - if(this.dirtyColors) - { - this.dirtyColors = false; - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.colors); - } - - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - var len = end - start; - - // DRAW THAT this! - gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A WebGLBatch Enables a group of sprites to be drawn using the same settings. - * if a group of sprites all have the same baseTexture and blendMode then they can be - * grouped into a batch. All the sprites in a batch can then be drawn in one go by the - * GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch - * even if the batch only contains one sprite. Batching is handled automatically by the - * webGL renderer. A good tip is: the smaller the number of batchs there are, the faster - * the webGL renderer will run. - * - * @class WebGLBatch - * @contructor - * @param gl {WebGLContext} An instance of the webGL context - */ -PIXI.WebGLRenderGroup = function(gl) -{ - this.gl = gl; - this.root; - - this.backgroundColor; - this.batchs = []; - this.toRemove = []; -} - -// constructor -PIXI.WebGLRenderGroup.prototype.constructor = PIXI.WebGLRenderGroup; - -/** - * Add a display object to the webgl renderer - * - * @method setRenderable - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.setRenderable = function(displayObject) -{ - // has this changed?? - if(this.root)this.removeDisplayObjectAndChildren(this.root); - - displayObject.worldVisible = displayObject.visible; - - // soooooo // - // to check if any batchs exist already?? - - // TODO what if its already has an object? should remove it - this.root = displayObject; - this.addDisplayObjectAndChildren(displayObject); -} - -/** - * Renders the stage to its webgl view - * - * @method render - * @param projection {Object} - */ -PIXI.WebGLRenderGroup.prototype.render = function(projection) -{ - PIXI.WebGLRenderer.updateTextures(); - - var gl = this.gl; - - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - // will render all the elements in the group - var renderable; - for (var i=0; i < this.batchs.length; i++) - { - - renderable = this.batchs[i]; - if(renderable instanceof PIXI.WebGLBatch) - { - this.batchs[i].render(); - continue; - } - - // non sprite batch.. - var worldVisible = renderable.vcount === PIXI.visibleCount; - - if(renderable instanceof PIXI.TilingSprite) - { - if(worldVisible)this.renderTilingSprite(renderable, projection); - } - else if(renderable instanceof PIXI.Strip) - { - if(worldVisible)this.renderStrip(renderable, projection); - } - else if(renderable instanceof PIXI.Graphics) - { - if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); - } - else if(renderable instanceof PIXI.FilterBlock) - { - this.handleFilterBlock(renderable, projection); - } - } - -} - -/** - * Renders a specific displayObject - * - * @method renderSpecific - * @param displayObject {DisplayObject} - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection) -{ - PIXI.WebGLRenderer.updateTextures(); - - var gl = this.gl; - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - - // to do! - // render part of the scene... - - var startIndex; - var startBatchIndex; - - var endIndex; - var endBatchIndex; - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.first; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - var startBatch = nextRenderable.batch; - - if(nextRenderable instanceof PIXI.Sprite) - { - startBatch = nextRenderable.batch; - - var head = startBatch.head; - var next = head; - - // ok now we have the batch.. need to find the start index! - if(head == nextRenderable) - { - startIndex = 0; - } - else - { - startIndex = 1; - - while(head.__next != nextRenderable) - { - startIndex++; - head = head.__next; - } - } - } - else - { - startBatch = nextRenderable; - } - - // Get the LAST renderable object - var lastRenderable = displayObject; - var endBatch; - var lastItem = displayObject; - while(lastItem.children.length > 0) - { - lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem.last; - } - - if(lastRenderable instanceof PIXI.Sprite) - { - endBatch = lastRenderable.batch; - - var head = endBatch.head; - - if(head == lastRenderable) - { - endIndex = 0; - } - else - { - endIndex = 1; - - while(head.__next != lastRenderable) - { - endIndex++; - head = head.__next; - } - } - } - else - { - endBatch = lastRenderable; - } - - // TODO - need to fold this up a bit! - - if(startBatch == endBatch) - { - if(startBatch instanceof PIXI.WebGLBatch) - { - startBatch.render(startIndex, endIndex+1); - } - else - { - this.renderSpecial(startBatch, projection); - } - return; - } - - // now we have first and last! - startBatchIndex = this.batchs.indexOf(startBatch); - endBatchIndex = this.batchs.indexOf(endBatch); - - // DO the first batch - if(startBatch instanceof PIXI.WebGLBatch) - { - startBatch.render(startIndex); - } - else - { - this.renderSpecial(startBatch, projection); - } - - // DO the middle batchs.. - for (var i=startBatchIndex+1; i < endBatchIndex; i++) - { - renderable = this.batchs[i]; - - if(renderable instanceof PIXI.WebGLBatch) - { - this.batchs[i].render(); - } - else - { - this.renderSpecial(renderable, projection); - } - } - - // DO the last batch.. - if(endBatch instanceof PIXI.WebGLBatch) - { - endBatch.render(0, endIndex+1); - } - else - { - this.renderSpecial(endBatch, projection); - } -} - -/** - * Renders a specific renderable - * - * @method renderSpecial - * @param renderable {DisplayObject} - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) -{ - var sta = PIXI.shaderStack.length; - - var worldVisible = renderable.vcount === PIXI.visibleCount - - if(renderable instanceof PIXI.TilingSprite) - { - if(worldVisible)this.renderTilingSprite(renderable, projection); - } - else if(renderable instanceof PIXI.Strip) - { - if(worldVisible)this.renderStrip(renderable, projection); - } - else if(renderable instanceof PIXI.CustomRenderable) - { - if(worldVisible) renderable.renderWebGL(this, projection); - } - else if(renderable instanceof PIXI.Graphics) - { - if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); - } - else if(renderable instanceof PIXI.FilterBlock) - { - this.handleFilterBlock(renderable, projection); - } -} - -PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) -{ - /* - * for now only masks are supported.. - */ - var gl = PIXI.gl; - - if(renderable.open) - { - if(renderable.data instanceof Array) - { - var filter = renderable.data[0]; - - if(!filter.shader) - { - var shader = new PIXI.PixiShader(); - - shader.fragmentSrc = filter.fragmentSrc; - shader.uniforms = filter.uniforms; - shader.init(); - - filter.shader = shader - } - - PIXI.activateShader(filter.shader); - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - } - else - { - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); - - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - } - else - { - if(renderable.data instanceof Array) - { - PIXI.popShader(); - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - } - else - { - gl.disable(gl.STENCIL_TEST); - } - } -} - -/** - * Updates a webgl texture - * - * @method updateTexture - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject) -{ - - // TODO definitely can optimse this function.. - - this.removeObject(displayObject); - - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - var previousRenderable = displayObject.first; - while(previousRenderable != this.root) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.last; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - - this.insertObject(displayObject, previousRenderable, nextRenderable); -} - -/** - * Adds filter blocks - * - * @method addFilterBlocks - * @param start {FilterBlock} - * @param end {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) -{ - start.__renderGroup = this; - end.__renderGroup = this; - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - var previousRenderable = start; - while(previousRenderable != this.root.first) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - this.insertAfter(start, previousRenderable); - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var previousRenderable2 = end; - while(previousRenderable2 != this.root.first) - { - previousRenderable2 = previousRenderable2._iPrev; - if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; - } - this.insertAfter(end, previousRenderable2); -} - -/** - * Remove filter blocks - * - * @method removeFilterBlocks - * @param start {FilterBlock} - * @param end {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeFilterBlocks = function(start, end) -{ - this.removeObject(start); - this.removeObject(end); -} - -/** - * Adds a display object and children to the webgl context - * - * @method addDisplayObjectAndChildren - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayObject) -{ - if(displayObject.__renderGroup)displayObject.__renderGroup.removeDisplayObjectAndChildren(displayObject); - - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - - var previousRenderable = displayObject.first; - while(previousRenderable != this.root.first) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.last; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - - // one the display object hits this. we can break the loop - - var tempObject = displayObject.first; - var testObject = displayObject.last._iNext; - do - { - tempObject.__renderGroup = this; - - if(tempObject.renderable) - { - - this.insertObject(tempObject, previousRenderable, nextRenderable); - previousRenderable = tempObject; - } - - tempObject = tempObject._iNext; - } - while(tempObject != testObject) -} - -/** - * Removes a display object and children to the webgl context - * - * @method removeDisplayObjectAndChildren - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren = function(displayObject) -{ - if(displayObject.__renderGroup != this)return; - -// var displayObject = displayObject.first; - var lastObject = displayObject.last; - do - { - displayObject.__renderGroup = null; - if(displayObject.renderable)this.removeObject(displayObject); - displayObject = displayObject._iNext; - } - while(displayObject) -} - -/** - * Inserts a displayObject into the linked list - * - * @method insertObject - * @param displayObject {DisplayObject} - * @param previousObject {DisplayObject} - * @param nextObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousObject, nextObject) -{ - // while looping below THE OBJECT MAY NOT HAVE BEEN ADDED - var previousSprite = previousObject; - var nextSprite = nextObject; - - /* - * so now we have the next renderable and the previous renderable - * - */ - if(displayObject instanceof PIXI.Sprite) - { - var previousBatch - var nextBatch - - if(previousSprite instanceof PIXI.Sprite) - { - previousBatch = previousSprite.batch; - if(previousBatch) - { - if(previousBatch.texture == displayObject.texture.baseTexture && previousBatch.blendMode == displayObject.blendMode) - { - previousBatch.insertAfter(displayObject, previousSprite); - return; - } - } - } - else - { - // TODO reword! - previousBatch = previousSprite; - } - - if(nextSprite) - { - if(nextSprite instanceof PIXI.Sprite) - { - nextBatch = nextSprite.batch; - - //batch may not exist if item was added to the display list but not to the webGL - if(nextBatch) - { - if(nextBatch.texture == displayObject.texture.baseTexture && nextBatch.blendMode == displayObject.blendMode) - { - nextBatch.insertBefore(displayObject, nextSprite); - return; - } - else - { - if(nextBatch == previousBatch) - { - // THERE IS A SPLIT IN THIS BATCH! // - var splitBatch = previousBatch.split(nextSprite); - // COOL! - // add it back into the array - /* - * OOPS! - * seems the new sprite is in the middle of a batch - * lets split it.. - */ - var batch = PIXI.WebGLRenderer.getBatch(); - - var index = this.batchs.indexOf( previousBatch ); - batch.init(displayObject); - this.batchs.splice(index+1, 0, batch, splitBatch); - - return; - } - } - } - } - else - { - // TODO re-word! - - nextBatch = nextSprite; - } - } - - /* - * looks like it does not belong to any batch! - * but is also not intersecting one.. - * time to create anew one! - */ - - var batch = PIXI.WebGLRenderer.getBatch(); - batch.init(displayObject); - - if(previousBatch) // if this is invalid it means - { - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, batch); - } - else - { - this.batchs.push(batch); - } - - return; - } - else if(displayObject instanceof PIXI.TilingSprite) - { - - // add to a batch!! - this.initTilingSprite(displayObject); - // this.batchs.push(displayObject); - - } - else if(displayObject instanceof PIXI.Strip) - { - // add to a batch!! - this.initStrip(displayObject); - // this.batchs.push(displayObject); - } - else if(displayObject)// instanceof PIXI.Graphics) - { - //displayObject.initWebGL(this); - - // add to a batch!! - //this.initStrip(displayObject); - //this.batchs.push(displayObject); - } - - this.insertAfter(displayObject, previousSprite); - - // insert and SPLIT! - -} - -/** - * Inserts a displayObject into the linked list - * - * @method insertAfter - * @param item {DisplayObject} - * @param displayObject {DisplayObject} The object to insert - * @private - */ -PIXI.WebGLRenderGroup.prototype.insertAfter = function(item, displayObject) -{ - if(displayObject instanceof PIXI.Sprite) - { - var previousBatch = displayObject.batch; - - if(previousBatch) - { - // so this object is in a batch! - - // is it not? need to split the batch - if(previousBatch.tail == displayObject) - { - // is it tail? insert in to batchs - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, item); - } - else - { - // TODO MODIFY ADD / REMOVE CHILD TO ACCOUNT FOR FILTERS (also get prev and next) // - - // THERE IS A SPLIT IN THIS BATCH! // - var splitBatch = previousBatch.split(displayObject.__next); - - // COOL! - // add it back into the array - /* - * OOPS! - * seems the new sprite is in the middle of a batch - * lets split it.. - */ - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, item, splitBatch); - } - } - else - { - this.batchs.push(item); - } - } - else - { - var index = this.batchs.indexOf( displayObject ); - this.batchs.splice(index+1, 0, item); - } -} - -/** - * Removes a displayObject from the linked list - * - * @method removeObject - * @param displayObject {DisplayObject} The object to remove - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) -{ - // loop through children.. - // display object // - - // add a child from the render group.. - // remove it and all its children! - //displayObject.cacheVisible = false;//displayObject.visible; - - /* - * removing is a lot quicker.. - * - */ - var batchToRemove; - - if(displayObject instanceof PIXI.Sprite) - { - // should always have a batch! - var batch = displayObject.batch; - if(!batch)return; // this means the display list has been altered befre rendering - - batch.remove(displayObject); - - if(batch.size==0) - { - batchToRemove = batch; - } - } - else - { - batchToRemove = displayObject; - } - - /* - * Looks like there is somthing that needs removing! - */ - if(batchToRemove) - { - var index = this.batchs.indexOf( batchToRemove ); - if(index == -1)return;// this means it was added then removed before rendered - - // ok so.. check to see if you adjacent batchs should be joined. - // TODO may optimise? - if(index == 0 || index == this.batchs.length-1) - { - // wha - eva! just get of the empty batch! - this.batchs.splice(index, 1); - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - - return; - } - - if(this.batchs[index-1] instanceof PIXI.WebGLBatch && this.batchs[index+1] instanceof PIXI.WebGLBatch) - { - if(this.batchs[index-1].texture == this.batchs[index+1].texture && this.batchs[index-1].blendMode == this.batchs[index+1].blendMode) - { - //console.log("MERGE") - this.batchs[index-1].merge(this.batchs[index+1]); - - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - PIXI.WebGLRenderer.returnBatch(this.batchs[index+1]); - this.batchs.splice(index, 2); - return; - } - } - - this.batchs.splice(index, 1); - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - } -} - - -/** - * Initializes a tiling sprite - * - * @method initTilingSprite - * @param sprite {TilingSprite} The tiling sprite to initialize - * @private - */ -PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) -{ - var gl = this.gl; - - // make the texture tilable.. - - sprite.verticies = new Float32Array([0, 0, - sprite.width, 0, - sprite.width, sprite.height, - 0, sprite.height]); - - sprite.uvs = new Float32Array([0, 0, - 1, 0, - 1, 1, - 0, 1]); - - sprite.colors = new Float32Array([1,1,1,1]); - - sprite.indices = new Uint16Array([0, 1, 3,2])//, 2]); - - sprite._vertexBuffer = gl.createBuffer(); - sprite._indexBuffer = gl.createBuffer(); - sprite._uvBuffer = gl.createBuffer(); - sprite._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.verticies, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.uvs, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.colors, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sprite._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sprite.indices, gl.STATIC_DRAW); - -// return ( (x > 0) && ((x & (x - 1)) == 0) ); - - if(sprite.texture.baseTexture._glTexture) - { - gl.bindTexture(gl.TEXTURE_2D, sprite.texture.baseTexture._glTexture); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - sprite.texture.baseTexture._powerOf2 = true; - } - else - { - sprite.texture.baseTexture._powerOf2 = true; - } -} - -/** - * Renders a Strip - * - * @method renderStrip - * @param strip {Strip} The strip to render - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) -{ - var gl = this.gl; - var shaderProgram = PIXI.stripShaderProgram; - - - gl.useProgram(shaderProgram); - - var m = PIXI.mat3.clone(strip.worldTransform); - - PIXI.mat3.transpose(m); - - // set the matrix transform for the - gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); - gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); - -/* - if(strip.blendMode == PIXI.blendModes.NORMAL) - { - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - } - else - { - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR); - } - */ - - - if(!strip.dirty) - { - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, strip.verticies) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - } - else - { - strip.dirty = false; - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); - - } - - gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - - gl.useProgram(PIXI.currentProgram); -} - -/** - * Renders a TilingSprite - * - * @method renderTilingSprite - * @param sprite {TilingSprite} The tiling sprite to render - * @param projectionMatrix {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderTilingSprite = function(sprite, projectionMatrix) -{ - var gl = this.gl; - var shaderProgram = PIXI.shaderProgram; - - var tilePosition = sprite.tilePosition; - var tileScale = sprite.tileScale; - - var offsetX = tilePosition.x/sprite.texture.baseTexture.width; - var offsetY = tilePosition.y/sprite.texture.baseTexture.height; - - var scaleX = (sprite.width / sprite.texture.baseTexture.width) / tileScale.x; - var scaleY = (sprite.height / sprite.texture.baseTexture.height) / tileScale.y; - - sprite.uvs[0] = 0 - offsetX; - sprite.uvs[1] = 0 - offsetY; - - sprite.uvs[2] = (1 * scaleX) -offsetX; - sprite.uvs[3] = 0 - offsetY; - - sprite.uvs[4] = (1 *scaleX) - offsetX; - sprite.uvs[5] = (1 *scaleY) - offsetY; - - sprite.uvs[6] = 0 - offsetX; - sprite.uvs[7] = (1 *scaleY) - offsetY; - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, sprite.uvs) - - this.renderStrip(sprite, projectionMatrix); -} - -/** - * Initializes a strip to be rendered - * - * @method initStrip - * @param strip {Strip} The strip to initialize - * @private - */ -PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) -{ - // build the strip! - var gl = this.gl; - var shaderProgram = this.shaderProgram; - - strip._vertexBuffer = gl.createBuffer(); - strip._indexBuffer = gl.createBuffer(); - strip._uvBuffer = gl.createBuffer(); - strip._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW); - - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * the CanvasRenderer draws the stage and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. - * Dont forget to add the view to your DOM or you will not see anything :) - * - * @class CanvasRenderer - * @constructor - * @param width=0 {Number} the width of the canvas view - * @param height=0 {Number} the height of the canvas view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - */ -PIXI.CanvasRenderer = function(width, height, view, transparent) -{ - this.transparent = transparent; - - /** - * The width of the canvas view - * - * @property width - * @type Number - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @property height - * @type Number - * @default 600 - */ - this.height = height || 600; - - /** - * The canvas element that the everything is drawn to - * - * @property view - * @type Canvas - */ - this.view = view || document.createElement( 'canvas' ); - - /** - * The canvas context that the everything is drawn to - * @property context - * @type Canvas 2d Context - */ - this.context = this.view.getContext("2d"); - - this.refresh = true; - // hack to enable some hardware acceleration! - //this.view.style["transform"] = "translatez(0)"; - - this.view.width = this.width; - this.view.height = this.height; - this.count = 0; -} - -// constructor -PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; - -/** - * Renders the stage to its canvas view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.CanvasRenderer.prototype.render = function(stage) -{ - - //stage.__childrenAdded = []; - //stage.__childrenRemoved = []; - - // update textures if need be - PIXI.texturesToUpdate = []; - PIXI.texturesToDestroy = []; - - PIXI.visibleCount++; - stage.updateTransform(); - - // update the background color - if(this.view.style.backgroundColor!=stage.backgroundColorString && !this.transparent)this.view.style.backgroundColor = stage.backgroundColorString; - - this.context.setTransform(1,0,0,1,0,0); - this.context.clearRect(0, 0, this.width, this.height) - this.renderDisplayObject(stage); - //as - - // run interaction! - if(stage.interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - - // remove frame updates.. - if(PIXI.Texture.frameUpdates.length > 0) - { - PIXI.Texture.frameUpdates = []; - } - - -} - -/** - * resizes the canvas view to the specified width and height - * - * @method resize - * @param width {Number} the new width of the canvas view - * @param height {Number} the new height of the canvas view - */ -PIXI.CanvasRenderer.prototype.resize = function(width, height) -{ - this.width = width; - this.height = height; - - this.view.width = width; - this.view.height = height; -} - -/** - * Renders a display object - * - * @method renderDisplayObject - * @param displayObject {DisplayObject} The displayObject to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) -{ - // no loger recurrsive! - var transform; - var context = this.context; - - context.globalCompositeOperation = 'source-over'; - - // one the display object hits this. we can break the loop - var testObject = displayObject.last._iNext; - displayObject = displayObject.first; - - do - { - transform = displayObject.worldTransform; - - if(!displayObject.visible) - { - displayObject = displayObject.last._iNext; - continue; - } - - if(!displayObject.renderable) - { - displayObject = displayObject._iNext; - continue; - } - - if(displayObject instanceof PIXI.Sprite) - { - - var frame = displayObject.texture.frame; - - if(frame && frame.width && frame.height) - { - context.globalAlpha = displayObject.worldAlpha; - - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); - - context.drawImage(displayObject.texture.baseTexture.source, - frame.x, - frame.y, - frame.width, - frame.height, - (displayObject.anchor.x) * -frame.width, - (displayObject.anchor.y) * -frame.height, - frame.width, - frame.height); - } - } - else if(displayObject instanceof PIXI.Strip) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - this.renderStrip(displayObject); - } - else if(displayObject instanceof PIXI.TilingSprite) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - this.renderTilingSprite(displayObject); - } - else if(displayObject instanceof PIXI.CustomRenderable) - { - displayObject.renderCanvas(this); - } - else if(displayObject instanceof PIXI.Graphics) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - PIXI.CanvasGraphics.renderGraphics(displayObject, context); - } - else if(displayObject instanceof PIXI.FilterBlock) - { - if(PIXI.FilterBlock.data instanceof PIXI.Graphics) - { - if(displayObject.open) - { - context.save(); - - var cacheAlpha = displayObject.mask.alpha; - var maskTransform = displayObject.mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - displayObject.mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); - context.clip(); - - displayObject.mask.worldAlpha = cacheAlpha; - } - else - { - context.restore(); - } - } - else - { - // only masks supported right now! - } - } - // count++ - displayObject = displayObject._iNext; - - - } - while(displayObject != testObject) - - -} - -/** - * Renders a flat strip - * - * @method renderStripFlat - * @param strip {Strip} The Strip to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip) -{ - var context = this.context; - var verticies = strip.verticies; - var uvs = strip.uvs; - - var length = verticies.length/2; - this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - - // draw some triangles! - var index = i*2; - - var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; - var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - }; - - context.fillStyle = "#FF0000"; - context.fill(); - context.closePath(); -} - -/** - * Renders a tiling sprite - * - * @method renderTilingSprite - * @param sprite {TilingSprite} The tilingsprite to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) -{ - var context = this.context; - - context.globalAlpha = sprite.worldAlpha; - - if(!sprite.__tilePattern) sprite.__tilePattern = context.createPattern(sprite.texture.baseTexture.source, "repeat"); - - context.beginPath(); - - var tilePosition = sprite.tilePosition; - var tileScale = sprite.tileScale; - - // offset - context.scale(tileScale.x,tileScale.y); - context.translate(tilePosition.x, tilePosition.y); - - context.fillStyle = sprite.__tilePattern; - context.fillRect(-tilePosition.x,-tilePosition.y,sprite.width / tileScale.x, sprite.height / tileScale.y); - - context.scale(1/tileScale.x, 1/tileScale.y); - context.translate(-tilePosition.x, -tilePosition.y); - - context.closePath(); -} - -/** - * Renders a strip - * - * @method renderStrip - * @param strip {Strip} The Strip to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderStrip = function(strip) -{ - var context = this.context; - - // draw triangles!! - var verticies = strip.verticies; - var uvs = strip.uvs; - - var length = verticies.length/2; - this.count++; - for (var i=1; i < length-2; i++) - { - - // draw some triangles! - var index = i*2; - - var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; - var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - - var u0 = uvs[index] * strip.texture.width, u1 = uvs[index+2] * strip.texture.width, u2 = uvs[index+4]* strip.texture.width; - var v0 = uvs[index+1]* strip.texture.height, v1 = uvs[index+3] * strip.texture.height, v2 = uvs[index+5]* strip.texture.height; - - - 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 delta_a = x0*v1 + v0*x2 + x1*v2 - v1*x2 - v0*x1 - x0*v2; - var delta_b = u0*x1 + x0*u2 + u1*x2 - x1*u2 - x0*u1 - u0*x2; - var delta_c = u0*v1*x2 + v0*x1*u2 + x0*u1*v2 - x0*v1*u2 - v0*u1*x2 - u0*x1*v2; - var delta_d = y0*v1 + v0*y2 + y1*v2 - v1*y2 - v0*y1 - y0*v2; - var delta_e = u0*y1 + y0*u2 + u1*y2 - y1*u2 - y0*u1 - u0*y2; - var delta_f = u0*v1*y2 + v0*y1*u2 + y0*u1*v2 - y0*v1*u2 - v0*u1*y2 - u0*y1*v2; - - - - - context.transform(delta_a/delta, delta_d/delta, - delta_b/delta, delta_e/delta, - delta_c/delta, delta_f/delta); - - context.drawImage(strip.texture.baseTexture.source, 0, 0); - context.restore(); - }; - -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * A set of functions used by the canvas renderer to draw the primitive graphics data - * - * @class CanvasGraphics - */ -PIXI.CanvasGraphics = function() -{ - -} - - -/* - * Renders the graphics object - * - * @static - * @private - * @method renderGraphics - * @param graphics {Graphics} - * @param context {Context2D} - */ -PIXI.CanvasGraphics.renderGraphics = function(graphics, context) -{ - var worldAlpha = graphics.worldAlpha; - - for (var i=0; i < graphics.graphicsData.length; i++) - { - var data = graphics.graphicsData[i]; - var points = data.points; - - context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); - - context.lineWidth = data.lineWidth; - - if(data.type == PIXI.Graphics.POLY) - { - context.beginPath(); - - context.moveTo(points[0], points[1]); - - for (var j=1; j < points.length/2; j++) - { - context.lineTo(points[j * 2], points[j * 2 + 1]); - } - - // if the first and last point are the same close the path - much neater :) - if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) - { - context.closePath(); - } - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - else if(data.type == PIXI.Graphics.RECT) - { - - if(data.fillColor || data.fillColor === 0) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fillRect(points[0], points[1], points[2], points[3]); - - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.strokeRect(points[0], points[1], points[2], points[3]); - } - - } - else if(data.type == PIXI.Graphics.CIRC) - { - // TODO - need to be Undefined! - context.beginPath(); - context.arc(points[0], points[1], points[2],0,2*Math.PI); - context.closePath(); - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - else if(data.type == PIXI.Graphics.ELIP) - { - - // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - - var elipseData = data.points; - - var w = elipseData[2] * 2; - var h = elipseData[3] * 2; - - var x = elipseData[0] - w/2; - var y = elipseData[1] - h/2; - - context.beginPath(); - - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - - context.moveTo(x, ym); - context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - - context.closePath(); - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - - }; -} - -/* - * Renders a graphics mask - * - * @static - * @private - * @method renderGraphicsMask - * @param graphics {Graphics} - * @param context {Context2D} - */ -PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) -{ - var worldAlpha = graphics.worldAlpha; - - var len = graphics.graphicsData.length; - if(len > 1) - { - len = 1; - console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") - } - - for (var i=0; i < 1; i++) - { - var data = graphics.graphicsData[i]; - var points = data.points; - - if(data.type == PIXI.Graphics.POLY) - { - context.beginPath(); - context.moveTo(points[0], points[1]); - - for (var j=1; j < points.length/2; j++) - { - context.lineTo(points[j * 2], points[j * 2 + 1]); - } - - // if the first and last point are the same close the path - much neater :) - if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) - { - context.closePath(); - } - - } - else if(data.type == PIXI.Graphics.RECT) - { - context.beginPath(); - context.rect(points[0], points[1], points[2], points[3]); - context.closePath(); - } - else if(data.type == PIXI.Graphics.CIRC) - { - // TODO - need to be Undefined! - context.beginPath(); - context.arc(points[0], points[1], points[2],0,2*Math.PI); - context.closePath(); - } - else if(data.type == PIXI.Graphics.ELIP) - { - - // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - var elipseData = data.points; - - var w = elipseData[2] * 2; - var h = elipseData[3] * 2; - - var x = elipseData[0] - w/2; - var y = elipseData[1] - h/2; - - context.beginPath(); - - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - - context.moveTo(x, ym); - context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - context.closePath(); - } - - - }; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. - * It is important to know that with the webGL renderer only simple polys can be filled at this stage - * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png - * - * @class Graphics - * @extends DisplayObjectContainer - * @constructor - */ -PIXI.Graphics = function() -{ - PIXI.DisplayObjectContainer.call( this ); - - this.renderable = true; - - /** - * The alpha of the fill of this graphics object - * - * @property fillAlpha - * @type Number - */ - this.fillAlpha = 1; - - /** - * The width of any lines drawn - * - * @property lineWidth - * @type Number - */ - this.lineWidth = 0; - - /** - * The color of any lines drawn - * - * @property lineColor - * @type String - */ - this.lineColor = "black"; - - /** - * Graphics data - * - * @property graphicsData - * @type Array - * @private - */ - this.graphicsData = []; - - /** - * Current path - * - * @property currentPath - * @type Object - * @private - */ - this.currentPath = {points:[]}; -} - -// constructor -PIXI.Graphics.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Graphics.prototype.constructor = PIXI.Graphics; - -/** - * Specifies a line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method. - * - * @method lineStyle - * @param lineWidth {Number} width of the line to draw, will update the object's stored style - * @param color {Number} color of the line to draw, will update the object's stored style - * @param alpha {Number} alpha of the line to draw, will update the object's stored style - */ -PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.lineWidth = lineWidth || 0; - this.lineColor = color || 0; - this.lineAlpha = (alpha == undefined) ? 1 : alpha; - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - - this.graphicsData.push(this.currentPath); -} - -/** - * Moves the current drawing position to (x, y). - * - * @method moveTo - * @param x {Number} the X coord to move to - * @param y {Number} the Y coord to move to - */ -PIXI.Graphics.prototype.moveTo = function(x, y) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - - this.currentPath.points.push(x, y); - - this.graphicsData.push(this.currentPath); -} - -/** - * Draws a line using the current line style from the current drawing position to (x, y); - * the current drawing position is then set to (x, y). - * - * @method lineTo - * @param x {Number} the X coord to draw to - * @param y {Number} the Y coord to draw to - */ -PIXI.Graphics.prototype.lineTo = function(x, y) -{ - this.currentPath.points.push(x, y); - this.dirty = true; -} - -/** - * Specifies a simple one-color fill that subsequent calls to other Graphics methods - * (such as lineTo() or drawCircle()) use when drawing. - * - * @method beginFill - * @param color {uint} the color of the fill - * @param alpha {Number} the alpha - */ -PIXI.Graphics.prototype.beginFill = function(color, alpha) -{ - this.filling = true; - this.fillColor = color || 0; - this.fillAlpha = (alpha == undefined) ? 1 : alpha; -} - -/** - * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. - * - * @method endFill - */ -PIXI.Graphics.prototype.endFill = function() -{ - this.filling = false; - this.fillColor = null; - this.fillAlpha = 1; -} - -/** - * @method drawRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - */ -PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, width, height], type:PIXI.Graphics.RECT}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Draws a circle. - * - * @method drawCircle - * @param x {Number} The X coord of the center of the circle - * @param y {Number} The Y coord of the center of the circle - * @param radius {Number} The radius of the circle - */ -PIXI.Graphics.prototype.drawCircle = function( x, y, radius) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Draws an elipse. - * - * @method drawElipse - * @param x {Number} - * @param y {Number} - * @param width {Number} - * @param height {Number} - */ -PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, width, height], type:PIXI.Graphics.ELIP}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @method clear - */ -PIXI.Graphics.prototype.clear = function() -{ - this.lineWidth = 0; - this.filling = false; - - this.dirty = true; - this.clearDirty = true; - this.graphicsData = []; -} - -// SOME TYPES: -PIXI.Graphics.POLY = 0; -PIXI.Graphics.RECT = 1; -PIXI.Graphics.CIRC = 2; -PIXI.Graphics.ELIP = 3; - -/** - * @author Mat Groves http://matgroves.com/ - */ - -PIXI.Strip = function(texture, width, height) -{ - PIXI.DisplayObjectContainer.call( this ); - this.texture = texture; - this.blendMode = PIXI.blendModes.NORMAL; - - try - { - this.uvs = new Float32Array([0, 1, - 1, 1, - 1, 0, 0,1]); - - this.verticies = new Float32Array([0, 0, - 0,0, - 0,0, 0, - 0, 0]); - - this.colors = new Float32Array([1, 1, 1, 1]); - - this.indices = new Uint16Array([0, 1, 2, 3]); - } - catch(error) - { - this.uvs = [0, 1, - 1, 1, - 1, 0, 0,1]; - - this.verticies = [0, 0, - 0,0, - 0,0, 0, - 0, 0]; - - this.colors = [1, 1, 1, 1]; - - this.indices = [0, 1, 2, 3]; - } - - - /* - this.uvs = new Float32Array() - this.verticies = new Float32Array() - this.colors = new Float32Array() - this.indices = new Uint16Array() -*/ - this.width = width; - this.height = height; - - // load the texture! - if(texture.baseTexture.hasLoaded) - { - this.width = this.texture.frame.width; - this.height = this.texture.frame.height; - this.updateFrame = true; - } - else - { - this.onTextureUpdateBind = this.onTextureUpdate.bind(this); - this.texture.addEventListener( 'update', this.onTextureUpdateBind ); - } - - this.renderable = true; -} - -// constructor -PIXI.Strip.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Strip.prototype.constructor = PIXI.Strip; - -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; -} - -PIXI.Strip.prototype.onTextureUpdate = function(event) -{ - this.updateFrame = true; -} -// some helper functions.. - - -/** - * @author Mat Groves http://matgroves.com/ - */ - - -PIXI.Rope = function(texture, points) -{ - PIXI.Strip.call( this, texture ); - this.points = points; - - try - { - this.verticies = new Float32Array( points.length * 4); - this.uvs = new Float32Array( points.length * 4); - this.colors = new Float32Array( points.length * 2); - this.indices = new Uint16Array( points.length * 2); - } - catch(error) - { - this.verticies = verticies - - this.uvs = uvs - this.colors = colors - this.indices = indices - } - - this.refresh(); -} - - -// constructor -PIXI.Rope.prototype = Object.create( PIXI.Strip.prototype ); -PIXI.Rope.prototype.constructor = PIXI.Rope; - -PIXI.Rope.prototype.refresh = function() -{ - var points = this.points; - if(points.length < 1)return; - - var uvs = this.uvs - var indices = this.indices; - var colors = this.colors; - - var lastPoint = points[0]; - var nextPoint; - var perp = {x:0, y:0}; - var point = points[0]; - - this.count-=0.2; - - - uvs[0] = 0 - uvs[1] = 1 - uvs[2] = 0 - uvs[3] = 1 - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length; - - for (var i = 1; i < total; i++) - { - - var point = points[i]; - var index = i * 4; - // time to do some smart drawing! - var 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; - } -} - -PIXI.Rope.prototype.updateTransform = function() -{ - - var points = this.points; - if(points.length < 1)return; - - var verticies = this.verticies - - var lastPoint = points[0]; - var nextPoint; - var perp = {x:0, y:0}; - var point = points[0]; - - this.count-=0.2; - - verticies[0] = point.x + perp.x - verticies[1] = point.y + perp.y //+ 200 - verticies[2] = point.x - perp.x - verticies[3] = point.y - perp.y//+200 - // time to do some smart drawing! - - var total = points.length; - - for (var i = 1; i < total; i++) - { - - var point = points[i]; - var 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; - - var ratio = (1 - (i / (total-1))) * 10; - if(ratio > 1)ratio = 1; - - var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); - var 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; - - verticies[index] = point.x + perp.x - verticies[index+1] = point.y + perp.y - verticies[index+2] = point.x - perp.x - verticies[index+3] = point.y - perp.y - - lastPoint = point; - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); -} - -PIXI.Rope.prototype.setTexture = function(texture) -{ - // stop current texture - this.texture = texture; - this.updateFrame = true; -} - - - - - -/** - * @author Mat Groves http://matgroves.com/ - */ - -/** - * A tiling sprite is a fast way of rendering a tiling image - * - * @class TilingSprite - * @extends DisplayObjectContainer - * @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.DisplayObjectContainer.call( this ); - - /** - * The texture that the sprite is using - * - * @property texture - * @type Texture - */ - this.texture = texture; - - /** - * The width of the tiling sprite - * - * @property width - * @type Number - */ - this.width = width; - - /** - * The height of the tiling sprite - * - * @property height - * @type Number - */ - this.height = height; - - /** - * The scaling of the image that is being tiled - * - * @property tileScale - * @type Point - */ - this.tileScale = 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); - - this.renderable = true; - - this.blendMode = PIXI.blendModes.NORMAL -} - -// constructor -PIXI.TilingSprite.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite; - -/** - * Sets the texture of the tiling sprite - * - * @method setTexture - * @param texture {Texture} The PIXI texture that is displayed by the sprite - */ -PIXI.TilingSprite.prototype.setTexture = function(texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - - // stop current texture - this.texture = texture; - this.updateFrame = true; -} - -/** - * When the texture is updated, this event will fire to update the frame - * - * @method onTextureUpdate - * @param event - * @private - */ -PIXI.TilingSprite.prototype.onTextureUpdate = function(event) -{ - this.updateFrame = true; -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * - * Awesome JS run time provided by EsotericSoftware - * https://github.com/EsotericSoftware/spine-runtimes - * - */ - -/** - * 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)) { - continue; - } - var spriteName = attachment.rendererObject.name; - var sprite = this.createSprite(slot, attachment.rendererObject); - slot.currentSprite = sprite; - slot.currentSpriteName = spriteName; - slotContainer.addChild(sprite); - } -}; - -PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); -PIXI.Spine.prototype.constructor = PIXI.Spine; - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.Spine.prototype.updateTransform = function () { - this.lastTime = this.lastTime || Date.now(); - var timeDelta = (Date.now() - this.lastTime) * 0.001; - this.lastTime = Date.now(); - this.state.update(timeDelta); - 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 instanceof spine.RegionAttachment)) { - slotContainer.visible = false; - continue; - } - - 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.rendererObject); - slotContainer.addChild(sprite); - } - slot.currentSprite = slot.sprites[spriteName]; - slot.currentSpriteName = spriteName; - } - } - slotContainer.visible = true; - - 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 * Math.PI / 180); - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -}; - - -PIXI.Spine.prototype.createSprite = function (slot, descriptor) { - var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); - sprite.scale = descriptor.scale; - sprite.rotation = descriptor.rotation; - sprite.anchor.x = sprite.anchor.y = 0.5; - - slot.sprites = slot.sprites || {}; - slot.sprites[descriptor.name] = sprite; - return sprite; -}; - -/* - * Awesome JS run time provided by EsotericSoftware - * - * https://github.com/EsotericSoftware/spine-runtimes - * - */ - -var spine = {}; - -spine.BoneData = function (name, parent) { - this.name = name; - this.parent = parent; -}; -spine.BoneData.prototype = { - length: 0, - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1 -}; - -spine.SlotData = function (name, boneData) { - this.name = name; - this.boneData = boneData; -}; -spine.SlotData.prototype = { - r: 1, g: 1, b: 1, a: 1, - attachmentName: null -}; - -spine.Bone = function (boneData, parent) { - this.data = boneData; - this.parent = parent; - this.setToSetupPose(); -}; -spine.Bone.yDown = false; -spine.Bone.prototype = { - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1, - m00: 0, m01: 0, worldX: 0, // a b x - m10: 0, m11: 0, worldY: 0, // c d y - worldRotation: 0, - worldScaleX: 1, worldScaleY: 1, - updateWorldTransform: function (flipX, flipY) { - var parent = this.parent; - if (parent != null) { - this.worldX = this.x * parent.m00 + this.y * parent.m01 + parent.worldX; - this.worldY = this.x * parent.m10 + this.y * parent.m11 + parent.worldY; - this.worldScaleX = parent.worldScaleX * this.scaleX; - this.worldScaleY = parent.worldScaleY * this.scaleY; - this.worldRotation = parent.worldRotation + this.rotation; - } else { - this.worldX = this.x; - this.worldY = this.y; - this.worldScaleX = this.scaleX; - this.worldScaleY = this.scaleY; - this.worldRotation = this.rotation; - } - var radians = this.worldRotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - this.m00 = cos * this.worldScaleX; - this.m10 = sin * this.worldScaleX; - this.m01 = -sin * this.worldScaleY; - this.m11 = cos * this.worldScaleY; - if (flipX) { - this.m00 = -this.m00; - this.m01 = -this.m01; - } - if (flipY) { - this.m10 = -this.m10; - this.m11 = -this.m11; - } - if (spine.Bone.yDown) { - this.m10 = -this.m10; - this.m11 = -this.m11; - } - }, - setToSetupPose: function () { - var data = this.data; - this.x = data.x; - this.y = data.y; - this.rotation = data.rotation; - this.scaleX = data.scaleX; - this.scaleY = data.scaleY; - } -}; - -spine.Slot = function (slotData, skeleton, bone) { - this.data = slotData; - this.skeleton = skeleton; - this.bone = bone; - this.setToSetupPose(); -}; -spine.Slot.prototype = { - r: 1, g: 1, b: 1, a: 1, - _attachmentTime: 0, - attachment: null, - setAttachment: function (attachment) { - this.attachment = attachment; - this._attachmentTime = this.skeleton.time; - }, - setAttachmentTime: function (time) { - this._attachmentTime = this.skeleton.time - time; - }, - getAttachmentTime: function () { - return this.skeleton.time - this._attachmentTime; - }, - setToSetupPose: function () { - var data = this.data; - this.r = data.r; - this.g = data.g; - this.b = data.b; - this.a = data.a; - - var slotDatas = this.skeleton.data.slots; - for (var i = 0, n = slotDatas.length; i < n; i++) { - if (slotDatas[i] == data) { - this.setAttachment(!data.attachmentName ? null : this.skeleton.getAttachmentBySlotIndex(i, data.attachmentName)); - break; - } - } - } -}; - -spine.Skin = function (name) { - this.name = name; - this.attachments = {}; -}; -spine.Skin.prototype = { - addAttachment: function (slotIndex, name, attachment) { - this.attachments[slotIndex + ":" + name] = attachment; - }, - getAttachment: function (slotIndex, name) { - return this.attachments[slotIndex + ":" + name]; - }, - _attachAll: function (skeleton, oldSkin) { - for (var key in oldSkin.attachments) { - var colon = key.indexOf(":"); - var slotIndex = parseInt(key.substring(0, colon)); - var name = key.substring(colon + 1); - var slot = skeleton.slots[slotIndex]; - if (slot.attachment && slot.attachment.name == name) { - var attachment = this.getAttachment(slotIndex, name); - if (attachment) slot.setAttachment(attachment); - } - } - } -}; - -spine.Animation = function (name, timelines, duration) { - this.name = name; - this.timelines = timelines; - this.duration = duration; -}; -spine.Animation.prototype = { - apply: function (skeleton, time, loop) { - if (loop && this.duration != 0) time %= this.duration; - var timelines = this.timelines; - for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, time, 1); - }, - mix: function (skeleton, time, loop, alpha) { - if (loop && this.duration != 0) time %= this.duration; - var timelines = this.timelines; - for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, time, alpha); - } -}; - -spine.binarySearch = function (values, target, step) { - var low = 0; - var high = Math.floor(values.length / step) - 2; - if (high == 0) return step; - var current = high >>> 1; - while (true) { - if (values[(current + 1) * step] <= target) - low = current + 1; - else - high = current; - if (low == high) return (low + 1) * step; - current = (low + high) >>> 1; - } -}; -spine.linearSearch = function (values, target, step) { - for (var i = 0, last = values.length - step; i <= last; i += step) - if (values[i] > target) return i; - return -1; -}; - -spine.Curves = function (frameCount) { - this.curves = []; // dfx, dfy, ddfx, ddfy, dddfx, dddfy, ... - this.curves.length = (frameCount - 1) * 6; -}; -spine.Curves.prototype = { - setLinear: function (frameIndex) { - this.curves[frameIndex * 6] = 0/*LINEAR*/; - }, - setStepped: function (frameIndex) { - this.curves[frameIndex * 6] = -1/*STEPPED*/; - }, - /** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next. - * cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of - * the difference between the keyframe's values. */ - setCurve: function (frameIndex, cx1, cy1, cx2, cy2) { - var subdiv_step = 1 / 10/*BEZIER_SEGMENTS*/; - var subdiv_step2 = subdiv_step * subdiv_step; - var subdiv_step3 = subdiv_step2 * subdiv_step; - var pre1 = 3 * subdiv_step; - var pre2 = 3 * subdiv_step2; - var pre4 = 6 * subdiv_step2; - var pre5 = 6 * subdiv_step3; - var tmp1x = -cx1 * 2 + cx2; - var tmp1y = -cy1 * 2 + cy2; - var tmp2x = (cx1 - cx2) * 3 + 1; - var tmp2y = (cy1 - cy2) * 3 + 1; - var i = frameIndex * 6; - var curves = this.curves; - curves[i] = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; - curves[i + 1] = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; - curves[i + 2] = tmp1x * pre4 + tmp2x * pre5; - curves[i + 3] = tmp1y * pre4 + tmp2y * pre5; - curves[i + 4] = tmp2x * pre5; - curves[i + 5] = tmp2y * pre5; - }, - getCurvePercent: function (frameIndex, percent) { - percent = percent < 0 ? 0 : (percent > 1 ? 1 : percent); - var curveIndex = frameIndex * 6; - var curves = this.curves; - var dfx = curves[curveIndex]; - if (!dfx/*LINEAR*/) return percent; - if (dfx == -1/*STEPPED*/) return 0; - var dfy = curves[curveIndex + 1]; - var ddfx = curves[curveIndex + 2]; - var ddfy = curves[curveIndex + 3]; - var dddfx = curves[curveIndex + 4]; - var dddfy = curves[curveIndex + 5]; - var x = dfx, y = dfy; - var i = 10/*BEZIER_SEGMENTS*/ - 2; - while (true) { - if (x >= percent) { - var lastX = x - dfx; - var lastY = y - dfy; - return lastY + (y - lastY) * (percent - lastX) / (x - lastX); - } - if (i == 0) break; - i--; - dfx += ddfx; - dfy += ddfy; - ddfx += dddfx; - ddfy += dddfy; - x += dfx; - y += dfy; - } - return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1. - } -}; - -spine.RotateTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, angle, ... - this.frames.length = frameCount * 2; -}; -spine.RotateTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 2; - }, - setFrame: function (frameIndex, time, angle) { - frameIndex *= 2; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = angle; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 2]) { // Time is after last frame. - var amount = bone.data.rotation + frames[frames.length - 1] - bone.rotation; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - bone.rotation += amount * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 2); - var lastFrameValue = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex - 2/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent); - - var amount = frames[frameIndex + 1/*FRAME_VALUE*/] - lastFrameValue; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - amount = bone.data.rotation + (lastFrameValue + amount * percent) - bone.rotation; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - bone.rotation += amount * alpha; - } -}; - -spine.TranslateTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, x, y, ... - this.frames.length = frameCount * 3; -}; -spine.TranslateTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 3; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 3; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = x; - this.frames[frameIndex + 2] = y; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 3]) { // Time is after last frame. - bone.x += (bone.data.x + frames[frames.length - 2] - bone.x) * alpha; - bone.y += (bone.data.y + frames[frames.length - 1] - bone.y) * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 3); - var lastFrameX = frames[frameIndex - 2]; - var lastFrameY = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); - - bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; - bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; - } -}; - -spine.ScaleTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, x, y, ... - this.frames.length = frameCount * 3; -}; -spine.ScaleTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 3; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 3; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = x; - this.frames[frameIndex + 2] = y; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 3]) { // Time is after last frame. - bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 3); - var lastFrameX = frames[frameIndex - 2]; - var lastFrameY = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); - - bone.scaleX += (bone.data.scaleX - 1 + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - 1 + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.scaleY) * alpha; - } -}; - -spine.ColorTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, r, g, b, a, ... - this.frames.length = frameCount * 5; -}; -spine.ColorTimeline.prototype = { - slotIndex: 0, - getFrameCount: function () { - return this.frames.length / 2; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 5; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = r; - this.frames[frameIndex + 2] = g; - this.frames[frameIndex + 3] = b; - this.frames[frameIndex + 4] = a; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var slot = skeleton.slots[this.slotIndex]; - - if (time >= frames[frames.length - 5]) { // Time is after last frame. - var i = frames.length - 1; - slot.r = frames[i - 3]; - slot.g = frames[i - 2]; - slot.b = frames[i - 1]; - slot.a = frames[i]; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 5); - var lastFrameR = frames[frameIndex - 4]; - var lastFrameG = frames[frameIndex - 3]; - var lastFrameB = frames[frameIndex - 2]; - var lastFrameA = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex - 5/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent); - - var r = lastFrameR + (frames[frameIndex + 1/*FRAME_R*/] - lastFrameR) * percent; - var g = lastFrameG + (frames[frameIndex + 2/*FRAME_G*/] - lastFrameG) * percent; - var b = lastFrameB + (frames[frameIndex + 3/*FRAME_B*/] - lastFrameB) * percent; - var a = lastFrameA + (frames[frameIndex + 4/*FRAME_A*/] - lastFrameA) * percent; - if (alpha < 1) { - slot.r += (r - slot.r) * alpha; - slot.g += (g - slot.g) * alpha; - slot.b += (b - slot.b) * alpha; - slot.a += (a - slot.a) * alpha; - } else { - slot.r = r; - slot.g = g; - slot.b = b; - slot.a = a; - } - } -}; - -spine.AttachmentTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, ... - this.frames.length = frameCount; - this.attachmentNames = []; // time, ... - this.attachmentNames.length = frameCount; -}; -spine.AttachmentTimeline.prototype = { - slotIndex: 0, - getFrameCount: function () { - return this.frames.length; - }, - setFrame: function (frameIndex, time, attachmentName) { - this.frames[frameIndex] = time; - this.attachmentNames[frameIndex] = attachmentName; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var frameIndex; - if (time >= frames[frames.length - 1]) // Time is after last frame. - frameIndex = frames.length - 1; - else - frameIndex = spine.binarySearch(frames, time, 1) - 1; - - var attachmentName = this.attachmentNames[frameIndex]; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); - } -}; - -spine.SkeletonData = function () { - this.bones = []; - this.slots = []; - this.skins = []; - this.animations = []; -}; -spine.SkeletonData.prototype = { - defaultSkin: null, - /** @return May be null. */ - findBone: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].name == boneName) return bones[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findBoneIndex: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].name == boneName) return i; - return -1; - }, - /** @return May be null. */ - findSlot: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) { - if (slots[i].name == slotName) return slot[i]; - } - return null; - }, - /** @return -1 if the bone was not found. */ - findSlotIndex: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].name == slotName) return i; - return -1; - }, - /** @return May be null. */ - findSkin: function (skinName) { - var skins = this.skins; - for (var i = 0, n = skins.length; i < n; i++) - if (skins[i].name == skinName) return skins[i]; - return null; - }, - /** @return May be null. */ - findAnimation: function (animationName) { - var animations = this.animations; - for (var i = 0, n = animations.length; i < n; i++) - if (animations[i].name == animationName) return animations[i]; - return null; - } -}; - -spine.Skeleton = function (skeletonData) { - this.data = skeletonData; - - this.bones = []; - for (var i = 0, n = skeletonData.bones.length; i < n; i++) { - var boneData = skeletonData.bones[i]; - var parent = !boneData.parent ? null : this.bones[skeletonData.bones.indexOf(boneData.parent)]; - this.bones.push(new spine.Bone(boneData, parent)); - } - - this.slots = []; - this.drawOrder = []; - for (var i = 0, n = skeletonData.slots.length; i < n; i++) { - var slotData = skeletonData.slots[i]; - var bone = this.bones[skeletonData.bones.indexOf(slotData.boneData)]; - var slot = new spine.Slot(slotData, this, bone); - this.slots.push(slot); - this.drawOrder.push(slot); - } -}; -spine.Skeleton.prototype = { - x: 0, y: 0, - skin: null, - r: 1, g: 1, b: 1, a: 1, - time: 0, - flipX: false, flipY: false, - /** Updates the world transform for each bone. */ - updateWorldTransform: function () { - var flipX = this.flipX; - var flipY = this.flipY; - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - bones[i].updateWorldTransform(flipX, flipY); - }, - /** Sets the bones and slots to their setup pose values. */ - setToSetupPose: function () { - this.setBonesToSetupPose(); - this.setSlotsToSetupPose(); - }, - setBonesToSetupPose: function () { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - bones[i].setToSetupPose(); - }, - setSlotsToSetupPose: function () { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - slots[i].setToSetupPose(i); - }, - /** @return May return null. */ - getRootBone: function () { - return this.bones.length == 0 ? null : this.bones[0]; - }, - /** @return May be null. */ - findBone: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].data.name == boneName) return bones[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findBoneIndex: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].data.name == boneName) return i; - return -1; - }, - /** @return May be null. */ - findSlot: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].data.name == slotName) return slots[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findSlotIndex: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].data.name == slotName) return i; - return -1; - }, - setSkinByName: function (skinName) { - var skin = this.data.findSkin(skinName); - if (!skin) throw "Skin not found: " + skinName; - this.setSkin(skin); - }, - /** Sets the skin used to look up attachments not found in the {@link SkeletonData#getDefaultSkin() default skin}. Attachments - * from the new skin are attached if the corresponding attachment from the old skin was attached. - * @param newSkin May be null. */ - setSkin: function (newSkin) { - if (this.skin && newSkin) newSkin._attachAll(this, this.skin); - this.skin = newSkin; - }, - /** @return May be null. */ - getAttachmentBySlotName: function (slotName, attachmentName) { - return this.getAttachmentBySlotIndex(this.data.findSlotIndex(slotName), attachmentName); - }, - /** @return May be null. */ - getAttachmentBySlotIndex: function (slotIndex, attachmentName) { - if (this.skin) { - var attachment = this.skin.getAttachment(slotIndex, attachmentName); - if (attachment) return attachment; - } - if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); - return null; - }, - /** @param attachmentName May be null. */ - setAttachment: function (slotName, attachmentName) { - var slots = this.slots; - for (var i = 0, n = slots.size; i < n; i++) { - var slot = slots[i]; - if (slot.data.name == slotName) { - var attachment = null; - if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); - if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; - } - slot.setAttachment(attachment); - return; - } - } - throw "Slot not found: " + slotName; - }, - update: function (delta) { - time += delta; - } -}; - -spine.AttachmentType = { - region: 0 -}; - -spine.RegionAttachment = function () { - this.offset = []; - this.offset.length = 8; - this.uvs = []; - this.uvs.length = 8; -}; -spine.RegionAttachment.prototype = { - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1, - width: 0, height: 0, - rendererObject: null, - regionOffsetX: 0, regionOffsetY: 0, - regionWidth: 0, regionHeight: 0, - regionOriginalWidth: 0, regionOriginalHeight: 0, - setUVs: function (u, v, u2, v2, rotate) { - var uvs = this.uvs; - if (rotate) { - uvs[2/*X2*/] = u; - uvs[3/*Y2*/] = v2; - uvs[4/*X3*/] = u; - uvs[5/*Y3*/] = v; - uvs[6/*X4*/] = u2; - uvs[7/*Y4*/] = v; - uvs[0/*X1*/] = u2; - uvs[1/*Y1*/] = v2; - } else { - uvs[0/*X1*/] = u; - uvs[1/*Y1*/] = v2; - uvs[2/*X2*/] = u; - uvs[3/*Y2*/] = v; - uvs[4/*X3*/] = u2; - uvs[5/*Y3*/] = v; - uvs[6/*X4*/] = u2; - uvs[7/*Y4*/] = v2; - } - }, - updateOffset: function () { - var regionScaleX = this.width / this.regionOriginalWidth * this.scaleX; - var regionScaleY = this.height / this.regionOriginalHeight * this.scaleY; - var localX = -this.width / 2 * this.scaleX + this.regionOffsetX * regionScaleX; - var localY = -this.height / 2 * this.scaleY + this.regionOffsetY * regionScaleY; - var localX2 = localX + this.regionWidth * regionScaleX; - var localY2 = localY + this.regionHeight * regionScaleY; - var radians = this.rotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - var localXCos = localX * cos + this.x; - var localXSin = localX * sin; - var localYCos = localY * cos + this.y; - var localYSin = localY * sin; - var localX2Cos = localX2 * cos + this.x; - var localX2Sin = localX2 * sin; - var localY2Cos = localY2 * cos + this.y; - var localY2Sin = localY2 * sin; - var offset = this.offset; - offset[0/*X1*/] = localXCos - localYSin; - offset[1/*Y1*/] = localYCos + localXSin; - offset[2/*X2*/] = localXCos - localY2Sin; - offset[3/*Y2*/] = localY2Cos + localXSin; - offset[4/*X3*/] = localX2Cos - localY2Sin; - offset[5/*Y3*/] = localY2Cos + localX2Sin; - offset[6/*X4*/] = localX2Cos - localYSin; - offset[7/*Y4*/] = localYCos + localX2Sin; - }, - computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; - y += bone.worldY; - var m00 = bone.m00; - var m01 = bone.m01; - var m10 = bone.m10; - var m11 = bone.m11; - var offset = this.offset; - vertices[0/*X1*/] = offset[0/*X1*/] * m00 + offset[1/*Y1*/] * m01 + x; - vertices[1/*Y1*/] = offset[0/*X1*/] * m10 + offset[1/*Y1*/] * m11 + y; - vertices[2/*X2*/] = offset[2/*X2*/] * m00 + offset[3/*Y2*/] * m01 + x; - vertices[3/*Y2*/] = offset[2/*X2*/] * m10 + offset[3/*Y2*/] * m11 + y; - vertices[4/*X3*/] = offset[4/*X3*/] * m00 + offset[5/*X3*/] * m01 + x; - vertices[5/*X3*/] = offset[4/*X3*/] * m10 + offset[5/*X3*/] * m11 + y; - vertices[6/*X4*/] = offset[6/*X4*/] * m00 + offset[7/*Y4*/] * m01 + x; - vertices[7/*Y4*/] = offset[6/*X4*/] * m10 + offset[7/*Y4*/] * m11 + y; - } -} - -spine.AnimationStateData = function (skeletonData) { - this.skeletonData = skeletonData; - this.animationToMixTime = {}; -}; -spine.AnimationStateData.prototype = { - defaultMix: 0, - setMixByName: function (fromName, toName, duration) { - var from = this.skeletonData.findAnimation(fromName); - if (!from) throw "Animation not found: " + fromName; - var to = this.skeletonData.findAnimation(toName); - if (!to) throw "Animation not found: " + toName; - this.setMix(from, to, duration); - }, - setMix: function (from, to, duration) { - this.animationToMixTime[from.name + ":" + to.name] = duration; - }, - getMix: function (from, to) { - var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : this.defaultMix; - } -}; - -spine.AnimationState = function (stateData) { - this.data = stateData; - this.queue = []; -}; -spine.AnimationState.prototype = { - current: null, - previous: null, - currentTime: 0, - previousTime: 0, - currentLoop: false, - previousLoop: false, - mixTime: 0, - mixDuration: 0, - update: function (delta) { - this.currentTime += delta; - this.previousTime += delta; - this.mixTime += delta; - - if (this.queue.length > 0) { - var entry = this.queue[0]; - if (this.currentTime >= entry.delay) { - this._setAnimation(entry.animation, entry.loop); - this.queue.shift(); - } - } - }, - apply: function (skeleton) { - if (!this.current) return; - if (this.previous) { - this.previous.apply(skeleton, this.previousTime, this.previousLoop); - var alpha = this.mixTime / this.mixDuration; - if (alpha >= 1) { - alpha = 1; - this.previous = null; - } - this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else - this.current.apply(skeleton, this.currentTime, this.currentLoop); - }, - clearAnimation: function () { - this.previous = null; - this.current = null; - this.queue.length = 0; - }, - _setAnimation: function (animation, loop) { - this.previous = null; - if (animation && this.current) { - this.mixDuration = this.data.getMix(this.current, animation); - if (this.mixDuration > 0) { - this.mixTime = 0; - this.previous = this.current; - this.previousTime = this.currentTime; - this.previousLoop = this.currentLoop; - } - } - this.current = animation; - this.currentLoop = loop; - this.currentTime = 0; - }, - /** @see #setAnimation(Animation, Boolean) */ - setAnimationByName: function (animationName, loop) { - var animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw "Animation not found: " + animationName; - this.setAnimation(animation, loop); - }, - /** Set the current animation. Any queued animations are cleared and the current animation time is set to 0. - * @param animation May be null. */ - setAnimation: function (animation, loop) { - this.queue.length = 0; - this._setAnimation(animation, loop); - }, - /** @see #addAnimation(Animation, Boolean, Number) */ - addAnimationByName: function (animationName, loop, delay) { - var animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw "Animation not found: " + animationName; - this.addAnimation(animation, loop, delay); - }, - /** Adds an animation to be played delay seconds after the current or last queued animation. - * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */ - addAnimation: function (animation, loop, delay) { - var entry = {}; - entry.animation = animation; - entry.loop = loop; - - if (!delay || delay <= 0) { - var previousAnimation = this.queue.length == 0 ? this.current : this.queue[this.queue.length - 1].animation; - if (previousAnimation != null) - delay = previousAnimation.duration - this.data.getMix(previousAnimation, animation) + (delay || 0); - else - delay = 0; - } - entry.delay = delay; - - this.queue.push(entry); - }, - /** Returns true if no animation is set or if the current time is greater than the animation duration, regardless of looping. */ - isComplete: function () { - return !this.current || this.currentTime >= this.current.duration; - } -}; - -spine.SkeletonJson = function (attachmentLoader) { - this.attachmentLoader = attachmentLoader; -}; -spine.SkeletonJson.prototype = { - scale: 1, - readSkeletonData: function (root) { - var skeletonData = new spine.SkeletonData(); - - // Bones. - var bones = root["bones"]; - for (var i = 0, n = bones.length; i < n; i++) { - var boneMap = bones[i]; - var parent = null; - if (boneMap["parent"]) { - parent = skeletonData.findBone(boneMap["parent"]); - if (!parent) throw "Parent bone not found: " + boneMap["parent"]; - } - var boneData = new spine.BoneData(boneMap["name"], parent); - boneData.length = (boneMap["length"] || 0) * this.scale; - boneData.x = (boneMap["x"] || 0) * this.scale; - boneData.y = (boneMap["y"] || 0) * this.scale; - boneData.rotation = (boneMap["rotation"] || 0); - boneData.scaleX = boneMap["scaleX"] || 1; - boneData.scaleY = boneMap["scaleY"] || 1; - skeletonData.bones.push(boneData); - } - - // Slots. - var slots = root["slots"]; - for (var i = 0, n = slots.length; i < n; i++) { - var slotMap = slots[i]; - var boneData = skeletonData.findBone(slotMap["bone"]); - if (!boneData) throw "Slot bone not found: " + slotMap["bone"]; - var slotData = new spine.SlotData(slotMap["name"], boneData); - - var color = slotMap["color"]; - if (color) { - slotData.r = spine.SkeletonJson.toColor(color, 0); - slotData.g = spine.SkeletonJson.toColor(color, 1); - slotData.b = spine.SkeletonJson.toColor(color, 2); - slotData.a = spine.SkeletonJson.toColor(color, 3); - } - - slotData.attachmentName = slotMap["attachment"]; - - skeletonData.slots.push(slotData); - } - - // Skins. - var skins = root["skins"]; - for (var skinName in skins) { - if (!skins.hasOwnProperty(skinName)) continue; - var skinMap = skins[skinName]; - var skin = new spine.Skin(skinName); - for (var slotName in skinMap) { - if (!skinMap.hasOwnProperty(slotName)) continue; - var slotIndex = skeletonData.findSlotIndex(slotName); - var slotEntry = skinMap[slotName]; - for (var attachmentName in slotEntry) { - if (!slotEntry.hasOwnProperty(attachmentName)) continue; - var attachment = this.readAttachment(skin, attachmentName, slotEntry[attachmentName]); - if (attachment != null) skin.addAttachment(slotIndex, attachmentName, attachment); - } - } - skeletonData.skins.push(skin); - if (skin.name == "default") skeletonData.defaultSkin = skin; - } - - // Animations. - var animations = root["animations"]; - for (var animationName in animations) { - if (!animations.hasOwnProperty(animationName)) continue; - this.readAnimation(animationName, animations[animationName], skeletonData); - } - - return skeletonData; - }, - readAttachment: function (skin, name, map) { - name = map["name"] || name; - - var type = spine.AttachmentType[map["type"] || "region"]; - - if (type == spine.AttachmentType.region) { - var attachment = new spine.RegionAttachment(); - attachment.x = (map["x"] || 0) * this.scale; - attachment.y = (map["y"] || 0) * this.scale; - attachment.scaleX = map["scaleX"] || 1; - attachment.scaleY = map["scaleY"] || 1; - attachment.rotation = map["rotation"] || 0; - attachment.width = (map["width"] || 32) * this.scale; - attachment.height = (map["height"] || 32) * this.scale; - attachment.updateOffset(); - - attachment.rendererObject = {}; - attachment.rendererObject.name = name; - attachment.rendererObject.scale = {}; - attachment.rendererObject.scale.x = attachment.scaleX; - attachment.rendererObject.scale.y = attachment.scaleY; - attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; - return attachment; - } - - throw "Unknown attachment type: " + type; - }, - - readAnimation: function (name, map, skeletonData) { - var timelines = []; - var duration = 0; - - var bones = map["bones"]; - for (var boneName in bones) { - if (!bones.hasOwnProperty(boneName)) continue; - var boneIndex = skeletonData.findBoneIndex(boneName); - if (boneIndex == -1) throw "Bone not found: " + boneName; - var boneMap = bones[boneName]; - - for (var timelineName in boneMap) { - if (!boneMap.hasOwnProperty(timelineName)) continue; - var values = boneMap[timelineName]; - if (timelineName == "rotate") { - var timeline = new spine.RotateTimeline(values.length); - timeline.boneIndex = boneIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - timeline.setFrame(frameIndex, valueMap["time"], valueMap["angle"]); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 2 - 2]); - - } else if (timelineName == "translate" || timelineName == "scale") { - var timeline; - var timelineScale = 1; - if (timelineName == "scale") - timeline = new spine.ScaleTimeline(values.length); - else { - timeline = new spine.TranslateTimeline(values.length); - timelineScale = this.scale; - } - timeline.boneIndex = boneIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - var x = (valueMap["x"] || 0) * timelineScale; - var y = (valueMap["y"] || 0) * timelineScale; - timeline.setFrame(frameIndex, valueMap["time"], x, y); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - - } else - throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; - } - } - var slots = map["slots"]; - for (var slotName in slots) { - if (!slots.hasOwnProperty(slotName)) continue; - var slotMap = slots[slotName]; - var slotIndex = skeletonData.findSlotIndex(slotName); - - for (var timelineName in slotMap) { - if (!slotMap.hasOwnProperty(timelineName)) continue; - var values = slotMap[timelineName]; - if (timelineName == "color") { - var timeline = new spine.ColorTimeline(values.length); - timeline.slotIndex = slotIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - var color = valueMap["color"]; - var r = spine.SkeletonJson.toColor(color, 0); - var g = spine.SkeletonJson.toColor(color, 1); - var b = spine.SkeletonJson.toColor(color, 2); - var a = spine.SkeletonJson.toColor(color, 3); - timeline.setFrame(frameIndex, valueMap["time"], r, g, b, a); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 5 - 5]); - - } else if (timelineName == "attachment") { - var timeline = new spine.AttachmentTimeline(values.length); - timeline.slotIndex = slotIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); - - } else - throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; - } - } - skeletonData.animations.push(new spine.Animation(name, timelines, duration)); - } -}; -spine.SkeletonJson.readCurve = function (timeline, frameIndex, valueMap) { - var curve = valueMap["curve"]; - if (!curve) return; - if (curve == "stepped") - timeline.curves.setStepped(frameIndex); - else if (curve instanceof Array) - timeline.curves.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); -}; -spine.SkeletonJson.toColor = function (hexString, colorIndex) { - if (hexString.length != 8) throw "Color hexidecimal length must be 8, recieved: " + hexString; - return parseInt(hexString.substring(colorIndex * 2, 2), 16) / 255; -}; - -spine.Atlas = function (atlasText, textureLoader) { - this.textureLoader = textureLoader; - this.pages = []; - this.regions = []; - - var reader = new spine.AtlasReader(atlasText); - var tuple = []; - tuple.length = 4; - var page = null; - while (true) { - var line = reader.readLine(); - if (line == null) break; - line = reader.trim(line); - if (line.length == 0) - page = null; - else if (!page) { - page = new spine.AtlasPage(); - page.name = line; - - page.format = spine.Atlas.Format[reader.readValue()]; - - reader.readTuple(tuple); - page.minFilter = spine.Atlas.TextureFilter[tuple[0]]; - page.magFilter = spine.Atlas.TextureFilter[tuple[1]]; - - var direction = reader.readValue(); - page.uWrap = spine.Atlas.TextureWrap.clampToEdge; - page.vWrap = spine.Atlas.TextureWrap.clampToEdge; - if (direction == "x") - page.uWrap = spine.Atlas.TextureWrap.repeat; - else if (direction == "y") - page.vWrap = spine.Atlas.TextureWrap.repeat; - else if (direction == "xy") - page.uWrap = page.vWrap = spine.Atlas.TextureWrap.repeat; - - textureLoader.load(page, line); - - this.pages.push(page); - - } else { - var region = new spine.AtlasRegion(); - region.name = line; - region.page = page; - - region.rotate = reader.readValue() == "true"; - - reader.readTuple(tuple); - var x = parseInt(tuple[0]); - var y = parseInt(tuple[1]); - - reader.readTuple(tuple); - var width = parseInt(tuple[0]); - var height = parseInt(tuple[1]); - - region.u = x / page.width; - region.v = y / page.height; - if (region.rotate) { - region.u2 = (x + height) / page.width; - region.v2 = (y + width) / page.height; - } else { - region.u2 = (x + width) / page.width; - region.v2 = (y + height) / page.height; - } - region.x = x; - region.y = y; - region.width = Math.abs(width); - region.height = Math.abs(height); - - if (reader.readTuple(tuple) == 4) { // split is optional - region.splits = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; - - if (reader.readTuple(tuple) == 4) { // pad is optional, but only present with splits - region.pads = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; - - reader.readTuple(tuple); - } - } - - region.originalWidth = parseInt(tuple[0]); - region.originalHeight = parseInt(tuple[1]); - - reader.readTuple(tuple); - region.offsetX = parseInt(tuple[0]); - region.offsetY = parseInt(tuple[1]); - - region.index = parseInt(reader.readValue()); - - this.regions.push(region); - } - } -}; -spine.Atlas.prototype = { - findRegion: function (name) { - var regions = this.regions; - for (var i = 0, n = regions.length; i < n; i++) - if (regions[i].name == name) return regions[i]; - return null; - }, - dispose: function () { - var pages = this.pages; - for (var i = 0, n = pages.length; i < n; i++) - this.textureLoader.unload(pages[i].rendererObject); - }, - updateUVs: function (page) { - var regions = this.regions; - for (var i = 0, n = regions.length; i < n; i++) { - var region = regions[i]; - if (region.page != page) continue; - region.u = region.x / page.width; - region.v = region.y / page.height; - if (region.rotate) { - region.u2 = (region.x + region.height) / page.width; - region.v2 = (region.y + region.width) / page.height; - } else { - region.u2 = (region.x + region.width) / page.width; - region.v2 = (region.y + region.height) / page.height; - } - } - } -}; - -spine.Atlas.Format = { - alpha: 0, - intensity: 1, - luminanceAlpha: 2, - rgb565: 3, - rgba4444: 4, - rgb888: 5, - rgba8888: 6 -}; - -spine.Atlas.TextureFilter = { - nearest: 0, - linear: 1, - mipMap: 2, - mipMapNearestNearest: 3, - mipMapLinearNearest: 4, - mipMapNearestLinear: 5, - mipMapLinearLinear: 6 -}; - -spine.Atlas.TextureWrap = { - mirroredRepeat: 0, - clampToEdge: 1, - repeat: 2 -}; - -spine.AtlasPage = function () {}; -spine.AtlasPage.prototype = { - name: null, - format: null, - minFilter: null, - magFilter: null, - uWrap: null, - vWrap: null, - rendererObject: null, - width: 0, - height: 0 -}; - -spine.AtlasRegion = function () {}; -spine.AtlasRegion.prototype = { - page: null, - name: null, - x: 0, y: 0, - width: 0, height: 0, - u: 0, v: 0, u2: 0, v2: 0, - offsetX: 0, offsetY: 0, - originalWidth: 0, originalHeight: 0, - index: 0, - rotate: false, - splits: null, - pads: null, -}; - -spine.AtlasReader = function (text) { - this.lines = text.split(/\r\n|\r|\n/); -}; -spine.AtlasReader.prototype = { - index: 0, - trim: function (value) { - return value.replace(/^\s+|\s+$/g, ""); - }, - readLine: function () { - if (this.index >= this.lines.length) return null; - return this.lines[this.index++]; - }, - readValue: function () { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) throw "Invalid line: " + line; - return this.trim(line.substring(colon + 1)); - }, - /** Returns the number of tuple values read (2 or 4). */ - readTuple: function (tuple) { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) throw "Invalid line: " + line; - var i = 0, lastMatch= colon + 1; - for (; i < 3; i++) { - var comma = line.indexOf(",", lastMatch); - if (comma == -1) { - if (i == 0) throw "Invalid line: " + line; - break; - } - tuple[i] = this.trim(line.substr(lastMatch, comma - lastMatch)); - lastMatch = comma + 1; - } - tuple[i] = this.trim(line.substring(lastMatch)); - return i + 1; - } -} - -spine.AtlasAttachmentLoader = function (atlas) { - this.atlas = atlas; -} -spine.AtlasAttachmentLoader.prototype = { - newAttachment: function (skin, type, name) { - switch (type) { - case spine.AttachmentType.region: - var region = this.atlas.findRegion(name); - if (!region) throw "Region not found in atlas: " + name + " (" + type + ")"; - var attachment = new spine.RegionAttachment(name); - attachment.rendererObject = region; - attachment.setUVs(region.u, region.v, region.u2, region.v2, region.rotate); - attachment.regionOffsetX = region.offsetX; - attachment.regionOffsetY = region.offsetY; - attachment.regionWidth = region.width; - attachment.regionHeight = region.height; - attachment.regionOriginalWidth = region.originalWidth; - attachment.regionOriginalHeight = region.originalHeight; - return attachment; - } - throw "Unknown attachment type: " + type; - } -} - -PIXI.AnimCache = {}; -spine.Bone.yDown = true; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * This object is one that will allow you to specify custom rendering functions based on render type - * - * @class CustomRenderable - * @extends DisplayObject - * @constructor - */ -PIXI.CustomRenderable = function() -{ - PIXI.DisplayObject.call( this ); - -} - -// constructor -PIXI.CustomRenderable.prototype = Object.create( PIXI.DisplayObject.prototype ); -PIXI.CustomRenderable.prototype.constructor = PIXI.CustomRenderable; - -/** - * If this object is being rendered by a CanvasRenderer it will call this callback - * - * @method renderCanvas - * @param renderer {CanvasRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.renderCanvas = function(renderer) -{ - // override! -} - -/** - * If this object is being rendered by a WebGLRenderer it will call this callback to initialize - * - * @method initWebGL - * @param renderer {WebGLRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.initWebGL = function(renderer) -{ - // override! -} - -/** - * If this object is being rendered by a WebGLRenderer it will call this callback - * - * @method renderWebGL - * @param renderer {WebGLRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.renderWebGL = function(renderGroup, projectionMatrix) -{ - // not sure if both needed? but ya have for now! - // override! -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.BaseTextureCache = {}; -PIXI.texturesToUpdate = []; -PIXI.texturesToDestroy = []; - -/** - * A texture stores the information that represents an image. All textures have a base texture - * - * @class BaseTexture - * @uses EventTarget - * @constructor - * @param source {String} the source object (image or canvas) - */ -PIXI.BaseTexture = function(source) -{ - PIXI.EventTarget.call( this ); - - /** - * [read-only] The width of the base texture set when the image has loaded - * - * @property width - * @type Number - * @readOnly - */ - this.width = 100; - - /** - * [read-only] The height of the base texture set when the image has loaded - * - * @property height - * @type Number - * @readOnly - */ - this.height = 100; - - /** - * [read-only] Describes if the base texture has loaded or not - * - * @property hasLoaded - * @type Boolean - * @readOnly - */ - this.hasLoaded = false; - - /** - * The source that is loaded to create the texture - * - * @property source - * @type Image - */ - this.source = source; - - if(!source)return; - - if(this.source instanceof Image || this.source instanceof HTMLImageElement) - { - if(this.source.complete) - { - this.hasLoaded = true; - this.width = this.source.width; - this.height = this.source.height; - - PIXI.texturesToUpdate.push(this); - } - else - { - - var scope = this; - this.source.onload = function(){ - - scope.hasLoaded = true; - scope.width = scope.source.width; - scope.height = scope.source.height; - - // add it to somewhere... - PIXI.texturesToUpdate.push(scope); - scope.dispatchEvent( { type: 'loaded', content: scope } ); - } - // this.image.src = imageUrl; - } - } - else - { - this.hasLoaded = true; - this.width = this.source.width; - this.height = this.source.height; - - PIXI.texturesToUpdate.push(this); - } - - this._powerOf2 = false; -} - -PIXI.BaseTexture.prototype.constructor = PIXI.BaseTexture; - -/** - * Destroys this base texture - * - * @method destroy - */ -PIXI.BaseTexture.prototype.destroy = function() -{ - if(this.source instanceof Image) - { - this.source.src = null; - } - this.source = null; - PIXI.texturesToDestroy.push(this); -} - -/** - * Helper function that returns a base texture based on an image url - * If the image is not in the base texture cache it will be created and loaded - * - * @static - * @method fromImage - * @param imageUrl {String} The image url of the texture - * @return BaseTexture - */ -PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) -{ - var baseTexture = PIXI.BaseTextureCache[imageUrl]; - if(!baseTexture) - { - // new Image() breaks tex loading in some versions of Chrome. - // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); - if (crossorigin) - { - image.crossOrigin = ''; - } - image.src = imageUrl; - baseTexture = new PIXI.BaseTexture(image); - PIXI.BaseTextureCache[imageUrl] = baseTexture; - } - - return baseTexture; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.TextureCache = {}; -PIXI.FrameCache = {}; - -/** - * A texture stores the information that represents an image or part of an image. It cannot be added - * to the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used - * - * @class Texture - * @uses EventTarget - * @constructor - * @param baseTexture {BaseTexture} The base texture source to create the texture from - * @param frame {Rectangle} The rectangle frame of the texture to show - */ -PIXI.Texture = function(baseTexture, frame) -{ - PIXI.EventTarget.call( this ); - - if(!frame) - { - this.noFrame = true; - frame = new PIXI.Rectangle(0,0,1,1); - } - - if(baseTexture instanceof PIXI.Texture) - baseTexture = baseTexture.baseTexture; - - /** - * The base texture of this texture - * - * @property baseTexture - * @type BaseTexture - */ - this.baseTexture = baseTexture; - - /** - * The frame specifies the region of the base texture that this texture uses - * - * @property frame - * @type Rectangle - */ - this.frame = frame; - - /** - * The trim point - * - * @property trim - * @type Point - */ - this.trim = new PIXI.Point(); - - this.scope = this; - - if(baseTexture.hasLoaded) - { - if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); - //console.log(frame) - - this.setFrame(frame); - } - else - { - var scope = this; - baseTexture.addEventListener( 'loaded', function(){ scope.onBaseTextureLoaded()} ); - } -} - -PIXI.Texture.prototype.constructor = PIXI.Texture; - -/** - * Called when the base texture is loaded - * - * @method onBaseTextureLoaded - * @param event - * @private - */ -PIXI.Texture.prototype.onBaseTextureLoaded = function(event) -{ - var baseTexture = this.baseTexture; - baseTexture.removeEventListener( 'loaded', this.onLoaded ); - - if(this.noFrame)this.frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); - this.noFrame = false; - this.width = this.frame.width; - this.height = this.frame.height; - - this.scope.dispatchEvent( { type: 'update', content: this } ); -} - -/** - * Destroys this texture - * - * @method destroy - * @param destroyBase {Boolean} Whether to destroy the base texture as well - */ -PIXI.Texture.prototype.destroy = function(destroyBase) -{ - if(destroyBase)this.baseTexture.destroy(); -} - -/** - * Specifies the rectangle region of the baseTexture - * - * @method setFrame - * @param frame {Rectangle} The frame of the texture to set it to - */ -PIXI.Texture.prototype.setFrame = function(frame) -{ - this.frame = frame; - this.width = frame.width; - this.height = frame.height; - - if(frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height) - { - throw new Error("Texture Error: frame does not fit inside the base Texture dimensions " + this); - } - - this.updateFrame = true; - - PIXI.Texture.frameUpdates.push(this); - //this.dispatchEvent( { type: 'update', content: this } ); -} - -/** - * Helper function that returns a texture based on an image url - * If the image is not in the texture cache it will be created and loaded - * - * @static - * @method fromImage - * @param imageUrl {String} The image url of the texture - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - * @return Texture - */ -PIXI.Texture.fromImage = function(imageUrl, crossorigin) -{ - var texture = PIXI.TextureCache[imageUrl]; - - if(!texture) - { - texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); - PIXI.TextureCache[imageUrl] = texture; - } - - return texture; -} - -/** - * Helper function that returns a texture based on a frame id - * If the frame id is not in the texture cache an error will be thrown - * - * @static - * @method fromFrame - * @param frameId {String} The frame id of the texture - * @return Texture - */ -PIXI.Texture.fromFrame = function(frameId) -{ - var texture = PIXI.TextureCache[frameId]; - if(!texture)throw new Error("The frameId '"+ frameId +"' does not exist in the texture cache " + this); - return texture; -} - -/** - * Helper function that returns a texture based on a canvas element - * If the canvas is not in the texture cache it will be created and loaded - * - * @static - * @method fromCanvas - * @param canvas {Canvas} The canvas element source of the texture - * @return Texture - */ -PIXI.Texture.fromCanvas = function(canvas) -{ - var baseTexture = new PIXI.BaseTexture(canvas); - return new PIXI.Texture(baseTexture); -} - - -/** - * Adds a texture to the textureCache. - * - * @static - * @method addTextureToCache - * @param texture {Texture} - * @param id {String} the id that the texture will be stored against. - */ -PIXI.Texture.addTextureToCache = function(texture, id) -{ - PIXI.TextureCache[id] = texture; -} - -/** - * Remove a texture from the textureCache. - * - * @static - * @method removeTextureFromCache - * @param id {String} the id of the texture to be removed - * @return {Texture} the texture that was removed - */ -PIXI.Texture.removeTextureFromCache = function(id) -{ - var texture = PIXI.TextureCache[id] - PIXI.TextureCache[id] = null; - return texture; -} - -// this is more for webGL.. it contains updated frames.. -PIXI.Texture.frameUpdates = []; - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - A RenderTexture is a special texture that allows any pixi displayObject to be rendered to it. - - __Hint__: All DisplayObjects (exmpl. Sprites) that renders on RenderTexture should be preloaded. - Otherwise black rectangles will be drawn instead. - - RenderTexture takes snapshot of DisplayObject passed to render method. If DisplayObject is passed to render method, position and rotation of it will be ignored. For example: - - var renderTexture = new PIXI.RenderTexture(800, 600); - var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - sprite.position.x = 800/2; - sprite.position.y = 600/2; - sprite.anchor.x = 0.5; - sprite.anchor.y = 0.5; - renderTexture.render(sprite); - - Sprite in this case will be rendered to 0,0 position. To render this sprite at center DisplayObjectContainer should be used: - - var doc = new PIXI.DisplayObjectContainer(); - doc.addChild(sprite); - renderTexture.render(doc); // Renders to center of renderTexture - - @class RenderTexture - @extends Texture - @constructor - @param width {Number} The width of the render texture - @param height {Number} The height of the render texture - */ -PIXI.RenderTexture = function(width, height) -{ - PIXI.EventTarget.call( this ); - - this.width = width || 100; - this.height = height || 100; - - this.indetityMatrix = PIXI.mat3.create(); - - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); - - if(PIXI.gl) - { - this.initWebGL(); - } - else - { - this.initCanvas(); - } -} - -PIXI.RenderTexture.prototype = Object.create( PIXI.Texture.prototype ); -PIXI.RenderTexture.prototype.constructor = PIXI.RenderTexture; - -/** - * Initializes the webgl data for this texture - * - * @method initWebGL - * @private - */ -PIXI.RenderTexture.prototype.initWebGL = function() -{ - var gl = PIXI.gl; - this.glFramebuffer = gl.createFramebuffer(); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - - this.glFramebuffer.width = this.width; - this.glFramebuffer.height = this.height; - - this.baseTexture = new PIXI.BaseTexture(); - - this.baseTexture.width = this.width; - this.baseTexture.height = this.height; - - this.baseTexture._glTexture = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - - this.baseTexture.isRender = true; - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.baseTexture._glTexture, 0); - - // create a projection matrix.. - this.projection = new PIXI.Point(this.width/2 , this.height/2); - - // set the correct render function.. - this.render = this.renderWebGL; - - -} - - -PIXI.RenderTexture.prototype.resize = function(width, height) -{ - - this.width = width; - this.height = height; - - if(PIXI.gl) - { - this.projection.x = this.width/2 - this.projection.y = this.height/2; - - var gl = PIXI.gl; - gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - } - else - { - - this.frame.width = this.width - this.frame.height = this.height; - this.renderer.resize(this.width, this.height); - } -} - -/** - * Initializes the canvas data for this texture - * - * @method initCanvas - * @private - */ -PIXI.RenderTexture.prototype.initCanvas = function() -{ - this.renderer = new PIXI.CanvasRenderer(this.width, this.height, null, 0); - - this.baseTexture = new PIXI.BaseTexture(this.renderer.view); - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); - - this.render = this.renderCanvas; -} - -/** - * This function will draw the display object to the texture. - * - * @method renderWebGL - * @param displayObject {DisplayObject} The display object to render this texture on - * @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn - * @private - */ -PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, clear) -{ - var gl = PIXI.gl; - - // enable the alpha color mask.. - gl.colorMask(true, true, true, true); - - gl.viewport(0, 0, this.width, this.height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - - if(clear) - { - gl.clearColor(0,0,0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - } - - // THIS WILL MESS WITH HIT TESTING! - var children = displayObject.children; - - //TODO -? create a new one??? dont think so! - var originalWorldTransform = displayObject.worldTransform; - displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; - // modify to flip... - displayObject.worldTransform[4] = -1; - displayObject.worldTransform[5] = this.projection.y * 2; - - - if(position) - { - displayObject.worldTransform[2] = position.x; - displayObject.worldTransform[5] -= position.y; - } - - PIXI.visibleCount++; - displayObject.vcount = PIXI.visibleCount; - - for(var i=0,j=children.length; i} assetURLs an array of image/sprite sheet urls that you would like loaded - * supported. Supported image formats include "jpeg", "jpg", "png", "gif". Supported - * sprite sheet data formats only include "JSON" at this time. Supported bitmap font - * data formats include "xml" and "fnt". - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.AssetLoader = function(assetURLs, crossorigin) -{ - PIXI.EventTarget.call(this); - - /** - * The array of asset URLs that are going to be loaded - * - * @property assetURLs - * @type Array - */ - this.assetURLs = assetURLs; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * Maps file extension to loader types - * - * @property loadersByType - * @type Object - */ - this.loadersByType = { - "jpg": PIXI.ImageLoader, - "jpeg": PIXI.ImageLoader, - "png": PIXI.ImageLoader, - "gif": PIXI.ImageLoader, - "json": PIXI.JsonLoader, - "anim": PIXI.SpineLoader, - "xml": PIXI.BitmapFontLoader, - "fnt": PIXI.BitmapFontLoader - }; - - -}; - -/** - * Fired when an item has loaded - * @event onProgress - */ - -/** - * Fired when all the assets have loaded - * @event onComplete - */ - -// constructor -PIXI.AssetLoader.prototype.constructor = PIXI.AssetLoader; - -/** - * Starts loading the assets sequentially - * - * @method load - */ -PIXI.AssetLoader.prototype.load = function() -{ - var scope = this; - - this.loadCount = this.assetURLs.length; - - for (var i=0; i < this.assetURLs.length; i++) - { - var fileName = this.assetURLs[i]; - var fileType = fileName.split(".").pop().toLowerCase(); - - var loaderClass = this.loadersByType[fileType]; - if(!loaderClass) - throw new Error(fileType + " is an unsupported file type"); - - var loader = new loaderClass(fileName, this.crossorigin); - - loader.addEventListener("loaded", function() - { - scope.onAssetLoaded(); - }); - loader.load(); - } -}; - -/** - * Invoked after each file is loaded - * - * @method onAssetLoaded - * @private - */ -PIXI.AssetLoader.prototype.onAssetLoaded = function() -{ - this.loadCount--; - this.dispatchEvent({type: "onProgress", content: this}); - if(this.onProgress) this.onProgress(); - - if(this.loadCount == 0) - { - this.dispatchEvent({type: "onComplete", content: this}); - if(this.onComplete) this.onComplete(); - } -}; - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The json file loader is used to load in JSON data and parsing it - * When loaded this class will dispatch a "loaded" event - * If load failed this class will dispatch a "error" event - * - * @class JsonLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the JSON file - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.JsonLoader = function (url, crossorigin) { - PIXI.EventTarget.call(this); - - /** - * The url of the bitmap font data - * - * @property url - * @type String - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * [read-only] The base url of the bitmap font data - * - * @property baseUrl - * @type String - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ""); - - /** - * [read-only] Whether the data has loaded yet - * - * @property loaded - * @type Boolean - * @readOnly - */ - this.loaded = false; - -}; - -// constructor -PIXI.JsonLoader.prototype.constructor = PIXI.JsonLoader; - -/** - * Loads the JSON data - * - * @method load - */ -PIXI.JsonLoader.prototype.load = function () { - this.ajaxRequest = new AjaxRequest(); - var scope = this; - this.ajaxRequest.onreadystatechange = function () { - scope.onJSONLoaded(); - }; - - this.ajaxRequest.open("GET", this.url, true); - if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/json"); - this.ajaxRequest.send(null); -}; - -/** - * Invoke when JSON file is loaded - * - * @method onJSONLoaded - * @private - */ -PIXI.JsonLoader.prototype.onJSONLoaded = function () { - if (this.ajaxRequest.readyState == 4) { - if (this.ajaxRequest.status == 200 || window.location.href.indexOf("http") == -1) { - this.json = JSON.parse(this.ajaxRequest.responseText); - - if(this.json.frames) - { - // sprite sheet - var scope = this; - var textureUrl = this.baseUrl + this.json.meta.image; - var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); - var frameData = this.json.frames; - - this.texture = image.texture.baseTexture; - image.addEventListener("loaded", function (event) { - scope.onLoaded(); - }); - - for (var i in frameData) { - var rect = frameData[i].frame; - if (rect) { - PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) { - //var realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) - // calculate the offset! - } - } - } - - image.load(); - - } - else if(this.json.bones) - { - // spine animation - var spineJsonParser = new spine.SkeletonJson(); - var skeletonData = spineJsonParser.readSkeletonData(this.json); - PIXI.AnimCache[this.url] = skeletonData; - this.onLoaded(); - } - else - { - this.onLoaded(); - } - } - else - { - this.onError(); - } - } -}; - -/** - * Invoke when json file loaded - * - * @method onLoaded - * @private - */ -PIXI.JsonLoader.prototype.onLoaded = function () { - this.loaded = true; - this.dispatchEvent({ - type: "loaded", - content: this - }); -}; - -/** - * Invoke when error occured - * - * @method onError - * @private - */ -PIXI.JsonLoader.prototype.onError = function () { - this.dispatchEvent({ - type: "error", - content: this - }); -}; -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The sprite sheet loader is used to load in JSON sprite sheet data - * To generate the data you can use http://www.codeandweb.com/texturepacker and publish the "JSON" format - * There is a free version so thats nice, although the paid version is great value for money. - * It is highly recommended to use Sprite sheets (also know as texture atlas") as it means sprite"s can be batched and drawn together for highly increased rendering speed. - * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() - * This loader will also load the image file that the Spritesheet points to as well as the data. - * When loaded this class will dispatch a "loaded" event - * - * @class SpriteSheetLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the sprite sheet JSON file - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ - -PIXI.SpriteSheetLoader = function (url, crossorigin) { - /* - * i use texture packer to load the assets.. - * http://www.codeandweb.com/texturepacker - * make sure to set the format as "JSON" - */ - PIXI.EventTarget.call(this); - - /** - * The url of the bitmap font data - * - * @property url - * @type String - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * [read-only] The base url of the bitmap font data - * - * @property baseUrl - * @type String - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ""); - - /** - * The texture being loaded - * - * @property texture - * @type Texture - */ - this.texture = null; - - /** - * The frames of the sprite sheet - * - * @property frames - * @type Object - */ - this.frames = {}; -}; - -// constructor -PIXI.SpriteSheetLoader.prototype.constructor = PIXI.SpriteSheetLoader; - -/** - * This will begin loading the JSON file - * - * @method load - */ -PIXI.SpriteSheetLoader.prototype.load = function () { - var scope = this; - var jsonLoader = new PIXI.JsonLoader(this.url, this.crossorigin); - jsonLoader.addEventListener("loaded", function (event) { - scope.json = event.content.json; - scope.onJSONLoaded(); - }); - jsonLoader.load(); -}; - -/** - * Invoke when JSON file is loaded - * - * @method onJSONLoaded - * @private - */ -PIXI.SpriteSheetLoader.prototype.onJSONLoaded = function () { - var scope = this; - var textureUrl = this.baseUrl + this.json.meta.image; - var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); - var frameData = this.json.frames; - - this.texture = image.texture.baseTexture; - image.addEventListener("loaded", function (event) { - scope.onLoaded(); - }); - - for (var i in frameData) { - var rect = frameData[i].frame; - if (rect) { - PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) { - //var realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) - // calculate the offset! - } - } - } - - image.load(); -}; -/** - * Invoke when all files are loaded (json and texture) - * - * @method onLoaded - * @private - */ -PIXI.SpriteSheetLoader.prototype.onLoaded = function () { - this.dispatchEvent({ - type: "loaded", - content: this - }); -}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The image loader class is responsible for loading images file formats ("jpeg", "jpg", "png" and "gif") - * Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() - * When loaded this class will dispatch a 'loaded' event - * - * @class ImageLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the image - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.ImageLoader = function(url, crossorigin) -{ - PIXI.EventTarget.call(this); - - /** - * The texture being loaded - * - * @property texture - * @type Texture - */ - this.texture = PIXI.Texture.fromImage(url, crossorigin); - - /** - * if the image is loaded with loadFramedSpriteSheet - * frames will contain the sprite sheet frames - * - */ - this.frames = []; -}; - -// constructor -PIXI.ImageLoader.prototype.constructor = PIXI.ImageLoader; - -/** - * Loads image or takes it from cache - * - * @method load - */ -PIXI.ImageLoader.prototype.load = function() -{ - if(!this.texture.baseTexture.hasLoaded) - { - var scope = this; - this.texture.baseTexture.addEventListener("loaded", function() - { - scope.onLoaded(); - }); - } - else - { - this.onLoaded(); - } -}; - -/** - * Invoked when image file is loaded or it is already cached and ready to use - * - * @method onLoaded - * @private - */ -PIXI.ImageLoader.prototype.onLoaded = function() -{ - this.dispatchEvent({type: "loaded", content: this}); -}; - -/** - * Loads image and split it to uniform sized frames - * - * - * @method loadFramedSpriteSheet - * @param frameWidth {Number} with of each frame - * @param frameHeight {Number} height of each frame - * @param textureName {String} if given, the frames will be cached in - format - */ -PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) -{ - this.frames = []; - var cols = Math.floor(this.texture.width / frameWidth); - var rows = Math.floor(this.texture.height / frameHeight); - - var i=0; - for (var y=0; y + + diff --git a/examples/example 7 - Transparent Background/pixi.js b/examples/example 7 - Transparent Background/pixi.js deleted file mode 100644 index 6d567a2..0000000 --- a/examples/example 7 - Transparent Background/pixi.js +++ /dev/null @@ -1,10649 +0,0 @@ -/** - * @license - * Pixi.JS - v1.3.0 - * Copyright (c) 2012, Mat Groves - * http://goodboydigital.com/ - * - * Compiled: 2013-09-30 - * - * Pixi.JS is licensed under the MIT License. - * http://www.opensource.org/licenses/mit-license.php - */ -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -(function(){ - - var root = this; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * @module PIXI - */ -var PIXI = PIXI || {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The Point object represents a location in a two-dimensional coordinate system, where x represents the horizontal axis and y represents the vertical axis. - * - * @class Point - * @constructor - * @param x {Number} position of the point - * @param y {Number} position of the point - */ -PIXI.Point = function(x, y) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; -} - -/** - * Creates a clone of this point - * - * @method clone - * @return {Point} a copy of the point - */ -PIXI.Point.prototype.clone = function() -{ - return new PIXI.Point(this.x, this.y); -} - -// constructor -PIXI.Point.prototype.constructor = PIXI.Point; - - -/** - * @author Mat Groves http://matgroves.com/ - */ - -/** - * the Rectangle object is an area defined by its position, as indicated by its top-left corner point (x, y) and by its width and its height. - * - * @class Rectangle - * @constructor - * @param x {Number} The X coord of the upper-left corner of the rectangle - * @param y {Number} The Y coord of the upper-left corner of the rectangle - * @param width {Number} The overall width of this rectangle - * @param height {Number} The overall height of this rectangle - */ -PIXI.Rectangle = function(x, y, width, height) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property width - * @type Number - * @default 0 - */ - this.width = width || 0; - - /** - * @property height - * @type Number - * @default 0 - */ - this.height = height || 0; -} - -/** - * Creates a clone of this Rectangle - * - * @method clone - * @return {Rectangle} a copy of the rectangle - */ -PIXI.Rectangle.prototype.clone = function() -{ - return new PIXI.Rectangle(this.x, this.y, this.width, this.height); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this Rectangle - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this Rectangle - */ -PIXI.Rectangle.prototype.contains = function(x, y) -{ - if(this.width <= 0 || this.height <= 0) - return false; - - var x1 = this.x; - if(x >= x1 && x <= x1 + this.width) - { - var y1 = this.y; - - if(y >= y1 && y <= y1 + this.height) - { - return true; - } - } - - return false; -} - -// constructor -PIXI.Rectangle.prototype.constructor = PIXI.Rectangle; - - -/** - * @author Adrien Brault - */ - -/** - * @class Polygon - * @constructor - * @param points* {Array|Array|Point...|Number...} This can be an array of Points that form the polygon, - * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be - * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the - * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are - * Numbers. - */ -PIXI.Polygon = function(points) -{ - //if points isn't an array, use arguments as the array - if(!(points instanceof Array)) - points = Array.prototype.slice.call(arguments); - - //if this is a flat array of numbers, convert it to points - if(typeof points[0] === 'number') { - var p = []; - for(var i = 0, il = points.length; i < il; i+=2) { - p.push( - new PIXI.Point(points[i], points[i + 1]) - ); - } - - points = p; - } - - this.points = points; -} - -/** - * Creates a clone of this polygon - * - * @method clone - * @return {Polygon} a copy of the polygon - */ -PIXI.Polygon.prototype.clone = function() -{ - var points = []; - for (var i=0; i y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); - - if(intersect) inside = !inside; - } - - return inside; -} - -// constructor -PIXI.Polygon.prototype.constructor = PIXI.Polygon; - -/** - * @author Chad Engler - */ - -/** - * The Circle object can be used to specify a hit area for displayobjects - * - * @class Circle - * @constructor - * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle - * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle - * @param radius {Number} The radius of the circle - */ -PIXI.Circle = function(x, y, radius) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property radius - * @type Number - * @default 0 - */ - this.radius = radius || 0; -} - -/** - * Creates a clone of this Circle instance - * - * @method clone - * @return {Circle} a copy of the polygon - */ -PIXI.Circle.prototype.clone = function() -{ - return new PIXI.Circle(this.x, this.y, this.radius); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this circle - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this polygon - */ -PIXI.Circle.prototype.contains = function(x, y) -{ - if(this.radius <= 0) - return false; - - var dx = (this.x - x), - dy = (this.y - y), - r2 = this.radius * this.radius; - - dx *= dx; - dy *= dy; - - return (dx + dy <= r2); -} - -// constructor -PIXI.Circle.prototype.constructor = PIXI.Circle; - - -/** - * @author Chad Engler - */ - -/** - * The Ellipse object can be used to specify a hit area for displayobjects - * - * @class Ellipse - * @constructor - * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse - * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse - * @param width {Number} The overall width of this ellipse - * @param height {Number} The overall height of this ellipse - */ -PIXI.Ellipse = function(x, y, width, height) -{ - /** - * @property x - * @type Number - * @default 0 - */ - this.x = x || 0; - - /** - * @property y - * @type Number - * @default 0 - */ - this.y = y || 0; - - /** - * @property width - * @type Number - * @default 0 - */ - this.width = width || 0; - - /** - * @property height - * @type Number - * @default 0 - */ - this.height = height || 0; -} - -/** - * Creates a clone of this Ellipse instance - * - * @method clone - * @return {Ellipse} a copy of the ellipse - */ -PIXI.Ellipse.prototype.clone = function() -{ - return new PIXI.Ellipse(this.x, this.y, this.width, this.height); -} - -/** - * Checks if the x, and y coords passed to this function are contained within this ellipse - * - * @method contains - * @param x {Number} The X coord of the point to test - * @param y {Number} The Y coord of the point to test - * @return {Boolean} if the x/y coords are within this ellipse - */ -PIXI.Ellipse.prototype.contains = function(x, y) -{ - if(this.width <= 0 || this.height <= 0) - return false; - - //normalize the coords to an ellipse with center 0,0 - //and a radius of 0.5 - var normx = ((x - this.x) / this.width) - 0.5, - normy = ((y - this.y) / this.height) - 0.5; - - normx *= normx; - normy *= normy; - - return (normx + normy < 0.25); -} - -PIXI.Ellipse.getBounds = function() -{ - return new PIXI.Rectangle(this.x, this.y, this.width, this.height); -} - -// constructor -PIXI.Ellipse.prototype.constructor = PIXI.Ellipse; - - - -/* - * A lighter version of the rad gl-matrix created by Brandon Jones, Colin MacKenzie IV - * you both rock! - */ - -function determineMatrixArrayType() { - PIXI.Matrix = (typeof Float32Array !== 'undefined') ? Float32Array : Array; - return PIXI.Matrix; -} - -determineMatrixArrayType(); - -PIXI.mat3 = {}; - -PIXI.mat3.create = function() -{ - var matrix = new PIXI.Matrix(9); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 1; - matrix[5] = 0; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 1; - - return matrix; -} - - -PIXI.mat3.identity = function(matrix) -{ - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 1; - matrix[5] = 0; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 1; - - return matrix; -} - - -PIXI.mat4 = {}; - -PIXI.mat4.create = function() -{ - var matrix = new PIXI.Matrix(16); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 0; - matrix[5] = 1; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = 1; - matrix[11] = 0; - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; - - return matrix; -} - -PIXI.mat3.multiply = function (mat, mat2, dest) -{ - if (!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[0], a01 = mat[1], a02 = mat[2], - a10 = mat[3], a11 = mat[4], a12 = mat[5], - a20 = mat[6], a21 = mat[7], a22 = mat[8], - - b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], - b10 = mat2[3], b11 = mat2[4], b12 = mat2[5], - b20 = mat2[6], b21 = mat2[7], b22 = mat2[8]; - - dest[0] = b00 * a00 + b01 * a10 + b02 * a20; - dest[1] = b00 * a01 + b01 * a11 + b02 * a21; - dest[2] = b00 * a02 + b01 * a12 + b02 * a22; - - dest[3] = b10 * a00 + b11 * a10 + b12 * a20; - dest[4] = b10 * a01 + b11 * a11 + b12 * a21; - dest[5] = b10 * a02 + b11 * a12 + b12 * a22; - - dest[6] = b20 * a00 + b21 * a10 + b22 * a20; - dest[7] = b20 * a01 + b21 * a11 + b22 * a21; - dest[8] = b20 * a02 + b21 * a12 + b22 * a22; - - return dest; -} - -PIXI.mat3.clone = function(mat) -{ - var matrix = new PIXI.Matrix(9); - - matrix[0] = mat[0]; - matrix[1] = mat[1]; - matrix[2] = mat[2]; - matrix[3] = mat[3]; - matrix[4] = mat[4]; - matrix[5] = mat[5]; - matrix[6] = mat[6]; - matrix[7] = mat[7]; - matrix[8] = mat[8]; - - return matrix; -} - -PIXI.mat3.transpose = function (mat, dest) -{ - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) { - var a01 = mat[1], a02 = mat[2], - a12 = mat[5]; - - mat[1] = mat[3]; - mat[2] = mat[6]; - mat[3] = a01; - mat[5] = mat[7]; - mat[6] = a02; - mat[7] = a12; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[3]; - dest[2] = mat[6]; - dest[3] = mat[1]; - dest[4] = mat[4]; - dest[5] = mat[7]; - dest[6] = mat[2]; - dest[7] = mat[5]; - dest[8] = mat[8]; - return dest; -} - -PIXI.mat3.toMat4 = function (mat, dest) -{ - if (!dest) { dest = PIXI.mat4.create(); } - - dest[15] = 1; - dest[14] = 0; - dest[13] = 0; - dest[12] = 0; - - dest[11] = 0; - dest[10] = mat[8]; - dest[9] = mat[7]; - dest[8] = mat[6]; - - dest[7] = 0; - dest[6] = mat[5]; - dest[5] = mat[4]; - dest[4] = mat[3]; - - dest[3] = 0; - dest[2] = mat[2]; - dest[1] = mat[1]; - dest[0] = mat[0]; - - return dest; -} - - -///// - - -PIXI.mat4.create = function() -{ - var matrix = new PIXI.Matrix(16); - - matrix[0] = 1; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; - matrix[4] = 0; - matrix[5] = 1; - matrix[6] = 0; - matrix[7] = 0; - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = 1; - matrix[11] = 0; - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; - - return matrix; -} - -PIXI.mat4.transpose = function (mat, dest) -{ - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (!dest || mat === dest) - { - var a01 = mat[1], a02 = mat[2], a03 = mat[3], - a12 = mat[6], a13 = mat[7], - a23 = mat[11]; - - mat[1] = mat[4]; - mat[2] = mat[8]; - mat[3] = mat[12]; - mat[4] = a01; - mat[6] = mat[9]; - mat[7] = mat[13]; - mat[8] = a02; - mat[9] = a12; - mat[11] = mat[14]; - mat[12] = a03; - mat[13] = a13; - mat[14] = a23; - return mat; - } - - dest[0] = mat[0]; - dest[1] = mat[4]; - dest[2] = mat[8]; - dest[3] = mat[12]; - dest[4] = mat[1]; - dest[5] = mat[5]; - dest[6] = mat[9]; - dest[7] = mat[13]; - dest[8] = mat[2]; - dest[9] = mat[6]; - dest[10] = mat[10]; - dest[11] = mat[14]; - dest[12] = mat[3]; - dest[13] = mat[7]; - dest[14] = mat[11]; - dest[15] = mat[15]; - return dest; -} - -PIXI.mat4.multiply = function (mat, mat2, dest) -{ - if (!dest) { dest = mat; } - - // Cache the matrix values (makes for huge speed increases!) - var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; - var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; - var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; - var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; - - // Cache only the current line of the second matrix - var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; - dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[4]; - b1 = mat2[5]; - b2 = mat2[6]; - b3 = mat2[7]; - dest[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[8]; - b1 = mat2[9]; - b2 = mat2[10]; - b3 = mat2[11]; - dest[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = mat2[12]; - b1 = mat2[13]; - b2 = mat2[14]; - b3 = mat2[15]; - dest[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - dest[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - dest[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - dest[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - return dest; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The base class for all objects that are rendered on the screen. - * - * @class DisplayObject - * @constructor - */ -PIXI.DisplayObject = function() -{ - this.last = this; - this.first = this; - /** - * The coordinate of the object relative to the local coordinates of the parent. - * - * @property position - * @type Point - */ - this.position = new PIXI.Point(); - - /** - * The scale factor of the object. - * - * @property scale - * @type Point - */ - this.scale = new PIXI.Point(1,1);//{x:1, y:1}; - - /** - * The pivot point of the displayObject that it rotates around - * - * @property pivot - * @type Point - */ - this.pivot = new PIXI.Point(0,0); - - /** - * The rotation of the object in radians. - * - * @property rotation - * @type Number - */ - this.rotation = 0; - - /** - * The opacity of the object. - * - * @property alpha - * @type Number - */ - this.alpha = 1; - - /** - * The visibility of the object. - * - * @property visible - * @type Boolean - */ - this.visible = true; - - /** - * This is the defined area that will pick up mouse / touch events. It is null by default. - * Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children) - * - * @property hitArea - * @type Rectangle|Circle|Ellipse|Polygon - */ - this.hitArea = null; - - /** - * This is used to indicate if the displayObject should display a mouse hand cursor on rollover - * - * @property buttonMode - * @type Boolean - */ - this.buttonMode = false; - - /** - * Can this object be rendered - * - * @property renderable - * @type Boolean - */ - this.renderable = false; - - /** - * [read-only] The display object container that contains this display object. - * - * @property parent - * @type DisplayObjectContainer - * @readOnly - */ - this.parent = null; - - /** - * [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage. - * - * @property stage - * @type Stage - * @readOnly - */ - this.stage = null; - - /** - * [read-only] The multiplied alpha of the displayobject - * - * @property worldAlpha - * @type Number - * @readOnly - */ - this.worldAlpha = 1; - - /** - * [read-only] Whether or not the object is interactive, do not toggle directly! use the `interactive` property - * - * @property _interactive - * @type Boolean - * @readOnly - * @private - */ - this._interactive = false; - - /** - * [read-only] Current transform of the object based on world (parent) factors - * - * @property worldTransform - * @type Mat3 - * @readOnly - * @private - */ - this.worldTransform = PIXI.mat3.create()//mat3.identity(); - - /** - * [read-only] Current transform of the object locally - * - * @property localTransform - * @type Mat3 - * @readOnly - * @private - */ - this.localTransform = PIXI.mat3.create()//mat3.identity(); - - /** - * [NYI] Unkown - * - * @property color - * @type Array<> - * @private - */ - this.color = []; - - /** - * [NYI] Holds whether or not this object is dynamic, for rendering optimization - * - * @property dynamic - * @type Boolean - * @private - */ - this.dynamic = true; - - // chach that puppy! - this._sr = 0; - this._cr = 1; - - /* - * MOUSE Callbacks - */ - - /** - * A callback that is used when the users clicks on the displayObject with their mouse - * @method click - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user clicks the mouse down over the sprite - * @method mousedown - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject - * for this callback to be fired the mouse must have been pressed down over the displayObject - * @method mouseup - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject - * for this callback to be fired, The touch must have started over the displayObject - * @method mouseupoutside - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the users mouse rolls over the displayObject - * @method mouseover - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the users mouse leaves the displayObject - * @method mouseout - * @param interactionData {InteractionData} - */ - - - /* - * TOUCH Callbacks - */ - - /** - * A callback that is used when the users taps on the sprite with their finger - * basically a touch version of click - * @method tap - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user touch's over the displayObject - * @method touchstart - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases a touch over the displayObject - * @method touchend - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the touch that was over the displayObject - * for this callback to be fired, The touch must have started over the sprite - * @method touchendoutside - * @param interactionData {InteractionData} - */ -} - -// constructor -PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject; - -/** - * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default - * Instead of using this function you can now simply set the interactive property to true or false - * - * @method setInteractive - * @param interactive {Boolean} - * @deprecated Simply set the `interactive` property directly - */ -PIXI.DisplayObject.prototype.setInteractive = function(interactive) -{ - this.interactive = interactive; -} - -/** - * Indicates if the sprite will have touch and mouse interactivity. It is false by default - * - * @property interactive - * @type Boolean - * @default false - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'interactive', { - get: function() { - return this._interactive; - }, - set: function(value) { - this._interactive = value; - - // TODO more to be done here.. - // need to sort out a re-crawl! - if(this.stage)this.stage.dirty = true; - } -}); - -/** - * Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. - * In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. - * To remove a mask, set this property to null. - * - * @property mask - * @type Graphics - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { - get: function() { - return this._mask; - }, - set: function(value) { - - - if(value) - { - if(this._mask) - { - value.start = this._mask.start; - value.end = this._mask.end; - } - else - { - this.addFilter(value); - value.renderable = false; - } - } - else - { - this.removeFilter(this._mask); - this._mask.renderable = true; - } - - this._mask = value; - } -}); - -/** - * Sets the filters for the displayObject. Currently there's a few limitations. - * 1: At the moment only one filter can be applied at a time.. - * 2: They cannot be nested. - * 3: There's no padding yet. - * 4: this is a webGL only feature. - * @property filters - * @type Array - */ -Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { - get: function() { - return this._filters; - }, - set: function(value) { - - //if(value == ) - if(value) - { - if(this._filters)this.removeFilter(this._filters); - this.addFilter(value) - } - else - { - if(this._filters)this.removeFilter(this._filters); - } - - this._filters = value; - } -}); - -/* - * Adds a filter to this displayObject - * - * @method addFilter - * @param mask {Graphics} the graphics object to use as a filter - * @private - */ -PIXI.DisplayObject.prototype.addFilter = function(data) -{ - //if(this.filter)return; - //this.filter = true; - - // insert a filter block.. - // TODO Onject pool thease bad boys.. - var start = new PIXI.FilterBlock(); - var end = new PIXI.FilterBlock(); - - data.start = start; - data.end = end; - - start.data = data; - end.data = data; - - start.first = start.last = this; - end.first = end.last = this; - - start.open = true; - - /* - * insert start - */ - - var childFirst = start - var childLast = start - var nextObject; - var previousObject; - - previousObject = this.first._iPrev; - - if(previousObject) - { - nextObject = previousObject._iNext; - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - } - else - { - nextObject = this; - } - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - - // now insert the end filter block.. - - /* - * insert end filter - */ - var childFirst = end - var childLast = end - var nextObject = null; - var previousObject = null; - - previousObject = this.last; - nextObject = previousObject._iNext; - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - var updateLast = this; - - var prevLast = this.last; - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = end; - } - updateLast = updateLast.parent; - } - - this.first = start; - - // if webGL... - if(this.__renderGroup) - { - this.__renderGroup.addFilterBlocks(start, end); - } - -} - -/* - * Removes the filter to this displayObject - * - * @method removeFilter - * @private - */ -PIXI.DisplayObject.prototype.removeFilter = function(data) -{ - //if(!this.filter)return; - //this.filter = false; - console.log("YUOIO") - // modify the list.. - var startBlock = data.start; - - - var nextObject = startBlock._iNext; - var previousObject = startBlock._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - if(previousObject)previousObject._iNext = nextObject; - - this.first = startBlock._iNext; - - // remove the end filter - var lastBlock = data.end; - - var nextObject = lastBlock._iNext; - var previousObject = lastBlock._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - - // this is always true too! - var tempLast = lastBlock._iPrev; - // need to make sure the parents last is updated too - var updateLast = this; - while(updateLast.last == lastBlock) - { - updateLast.last = tempLast; - updateLast = updateLast.parent; - if(!updateLast)break; - } - - // if webGL... - if(this.__renderGroup) - { - this.__renderGroup.removeFilterBlocks(startBlock, lastBlock); - } -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.DisplayObject.prototype.updateTransform = function() -{ - // TODO OPTIMIZE THIS!! with dirty - if(this.rotation !== this.rotationCache) - { - this.rotationCache = this.rotation; - this._sr = Math.sin(this.rotation); - this._cr = Math.cos(this.rotation); - } - - var localTransform = this.localTransform; - var parentTransform = this.parent.worldTransform; - var worldTransform = this.worldTransform; - //console.log(localTransform) - localTransform[0] = this._cr * this.scale.x; - localTransform[1] = -this._sr * this.scale.y - localTransform[3] = this._sr * this.scale.x; - localTransform[4] = this._cr * this.scale.y; - - // TODO --> do we even need a local matrix??? - - var px = this.pivot.x; - var py = this.pivot.y; - - // Cache the matrix values (makes for huge speed increases!) - var a00 = localTransform[0], a01 = localTransform[1], a02 = this.position.x - localTransform[0] * px - py * localTransform[1], - a10 = localTransform[3], a11 = localTransform[4], a12 = this.position.y - localTransform[4] * py - px * localTransform[3], - - b00 = parentTransform[0], b01 = parentTransform[1], b02 = parentTransform[2], - b10 = parentTransform[3], b11 = parentTransform[4], b12 = parentTransform[5]; - - localTransform[2] = a02 - localTransform[5] = a12 - - worldTransform[0] = b00 * a00 + b01 * a10; - worldTransform[1] = b00 * a01 + b01 * a11; - worldTransform[2] = b00 * a02 + b01 * a12 + b02; - - worldTransform[3] = b10 * a00 + b11 * a10; - worldTransform[4] = b10 * a01 + b11 * a11; - worldTransform[5] = b10 * a02 + b11 * a12 + b12; - - // because we are using affine transformation, we can optimise the matrix concatenation process.. wooo! - // mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform); - this.worldAlpha = this.alpha * this.parent.worldAlpha; - - this.vcount = PIXI.visibleCount; - -} - -PIXI.visibleCount = 0; -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * A DisplayObjectContainer represents a collection of display objects. - * It is the base class of all display objects that act as a container for other objects. - * - * @class DisplayObjectContainer - * @extends DisplayObject - * @constructor - */ -PIXI.DisplayObjectContainer = function() -{ - PIXI.DisplayObject.call( this ); - - /** - * [read-only] The of children of this container. - * - * @property children - * @type Array - * @readOnly - */ - this.children = []; -} - -// constructor -PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype ); -PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer; - -/** - * Adds a child to the container. - * - * @method addChild - * @param child {DisplayObject} The DisplayObject to add to the container - */ -PIXI.DisplayObjectContainer.prototype.addChild = function(child) -{ - if(child.parent != undefined) - { - - //// COULD BE THIS??? - child.parent.removeChild(child); - // return; - } - - child.parent = this; - - this.children.push(child); - - // update the stage refference.. - - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = this.stage; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // LINKED LIST // - - // modify the list.. - var childFirst = child.first - var childLast = child.last; - var nextObject; - var previousObject; - - // this could be wrong if there is a filter?? - if(this._filters) - { - previousObject = this.last._iPrev; - } - else - { - previousObject = this.last; - } - - nextObject = previousObject._iNext; - - // always true in this case - // need to make sure the parents last is updated too - var updateLast = this; - var prevLast = previousObject; - - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = child.last; - } - updateLast = updateLast.parent; - } - - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - // need to remove any render groups.. - if(this.__renderGroup) - { - // being used by a renderTexture.. if it exists then it must be from a render texture; - if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); - // add them to the new render group.. - this.__renderGroup.addDisplayObjectAndChildren(child); - } - -} - -/** - * Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown - * - * @method addChildAt - * @param child {DisplayObject} The child to add - * @param index {Number} The index to place the child in - */ -PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index) -{ - if(index >= 0 && index <= this.children.length) - { - if(child.parent != undefined) - { - child.parent.removeChild(child); - } - child.parent = this; - - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = this.stage; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // modify the list.. - var childFirst = child.first; - var childLast = child.last; - var nextObject; - var previousObject; - - if(index == this.children.length) - { - previousObject = this.last; - var updateLast = this; - var prevLast = this.last; - while(updateLast) - { - if(updateLast.last == prevLast) - { - updateLast.last = child.last; - } - updateLast = updateLast.parent; - } - } - else if(index == 0) - { - previousObject = this; - } - else - { - previousObject = this.children[index-1].last; - } - - nextObject = previousObject._iNext; - - // always true in this case - if(nextObject) - { - nextObject._iPrev = childLast; - childLast._iNext = nextObject; - } - - childFirst._iPrev = previousObject; - previousObject._iNext = childFirst; - - this.children.splice(index, 0, child); - // need to remove any render groups.. - if(this.__renderGroup) - { - // being used by a renderTexture.. if it exists then it must be from a render texture; - if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child); - // add them to the new render group.. - this.__renderGroup.addDisplayObjectAndChildren(child); - } - - } - else - { - throw new Error(child + " The index "+ index +" supplied is out of bounds " + this.children.length); - } -} - -/** - * [NYI] Swaps the depth of 2 displayObjects - * - * @method swapChildren - * @param child {DisplayObject} - * @param child2 {DisplayObject} - * @private - */ -PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2) -{ - /* - * this funtion needs to be recoded.. - * can be done a lot faster.. - */ - return; - - // need to fix this function :/ - /* - // TODO I already know this?? - var index = this.children.indexOf( child ); - var index2 = this.children.indexOf( child2 ); - - if ( index !== -1 && index2 !== -1 ) - { - // cool - - /* - if(this.stage) - { - // this is to satisfy the webGL batching.. - // TODO sure there is a nicer way to achieve this! - this.stage.__removeChild(child); - this.stage.__removeChild(child2); - - this.stage.__addChild(child); - this.stage.__addChild(child2); - } - - // swap the positions.. - this.children[index] = child2; - this.children[index2] = child; - - } - else - { - throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); - }*/ -} - -/** - * Returns the Child at the specified index - * - * @method getChildAt - * @param index {Number} The index to get the child from - */ -PIXI.DisplayObjectContainer.prototype.getChildAt = function(index) -{ - if(index >= 0 && index < this.children.length) - { - return this.children[index]; - } - else - { - throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this); - } -} - -/** - * Removes a child from the container. - * - * @method removeChild - * @param child {DisplayObject} The DisplayObject to remove - */ -PIXI.DisplayObjectContainer.prototype.removeChild = function(child) -{ - var index = this.children.indexOf( child ); - if ( index !== -1 ) - { - // unlink // - // modify the list.. - var childFirst = child.first; - var childLast = child.last; - - var nextObject = childLast._iNext; - var previousObject = childFirst._iPrev; - - if(nextObject)nextObject._iPrev = previousObject; - previousObject._iNext = nextObject; - - if(this.last == childLast) - { - var tempLast = childFirst._iPrev; - // need to make sure the parents last is updated too - var updateLast = this; - while(updateLast.last == childLast.last) - { - updateLast.last = tempLast; - updateLast = updateLast.parent; - if(!updateLast)break; - } - } - - childLast._iNext = null; - childFirst._iPrev = null; - - // update the stage reference.. - if(this.stage) - { - var tmpChild = child; - do - { - if(tmpChild.interactive)this.stage.dirty = true; - tmpChild.stage = null; - tmpChild = tmpChild._iNext; - } - while(tmpChild) - } - - // webGL trim - if(child.__renderGroup) - { - child.__renderGroup.removeDisplayObjectAndChildren(child); - } - - child.parent = undefined; - this.children.splice( index, 1 ); - } - else - { - throw new Error(child + " The supplied DisplayObject must be a child of the caller " + this); - } -} - -/* - * Updates the container's children's transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.DisplayObjectContainer.prototype.updateTransform = function() -{ - if(!this.visible)return; - - PIXI.DisplayObject.prototype.updateTransform.call( this ); - - for(var i=0,j=this.children.length; i} an array of {Texture} objects that make up the animation - */ -PIXI.MovieClip = function(textures) -{ - PIXI.Sprite.call(this, textures[0]); - - /** - * The array of textures that make up the animation - * - * @property textures - * @type Array - */ - this.textures = textures; - - /** - * The speed that the MovieClip will play at. Higher is faster, lower is slower - * - * @property animationSpeed - * @type Number - * @default 1 - */ - this.animationSpeed = 1; - - /** - * Whether or not the movie clip repeats after playing. - * - * @property loop - * @type Boolean - * @default true - */ - this.loop = true; - - /** - * Function to call when a MovieClip finishes playing - * - * @property onComplete - * @type Function - */ - this.onComplete = null; - - /** - * [read-only] The index MovieClips current frame (this may not have to be a whole number) - * - * @property currentFrame - * @type Number - * @default 0 - * @readOnly - */ - this.currentFrame = 0; - - /** - * [read-only] Indicates if the MovieClip is currently playing - * - * @property playing - * @type Boolean - * @readOnly - */ - this.playing = false; -} - -// constructor -PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype ); -PIXI.MovieClip.prototype.constructor = PIXI.MovieClip; - -/** -* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures -* assigned to the MovieClip. -* -* @property totalFrames -* @type Number -* @default 0 -* @readOnly -*/ -Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', { - get: function() { - - return this.textures.length; - } -}); - - -/** - * Stops the MovieClip - * - * @method stop - */ -PIXI.MovieClip.prototype.stop = function() -{ - this.playing = false; -} - -/** - * Plays the MovieClip - * - * @method play - */ -PIXI.MovieClip.prototype.play = function() -{ - this.playing = true; -} - -/** - * Stops the MovieClip and goes to a specific frame - * - * @method gotoAndStop - * @param frameNumber {Number} frame index to stop at - */ -PIXI.MovieClip.prototype.gotoAndStop = function(frameNumber) -{ - this.playing = false; - this.currentFrame = frameNumber; - var round = (this.currentFrame + 0.5) | 0; - this.setTexture(this.textures[round % this.textures.length]); -} - -/** - * Goes to a specific frame and begins playing the MovieClip - * - * @method gotoAndPlay - * @param frameNumber {Number} frame index to start at - */ -PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber) -{ - this.currentFrame = frameNumber; - this.playing = true; -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.MovieClip.prototype.updateTransform = function() -{ - PIXI.Sprite.prototype.updateTransform.call(this); - - if(!this.playing)return; - - this.currentFrame += this.animationSpeed; - - var round = (this.currentFrame + 0.5) | 0; - - if(this.loop || round < this.textures.length) - { - this.setTexture(this.textures[round % this.textures.length]); - } - else if(round >= this.textures.length) - { - this.gotoAndStop(this.textures.length - 1); - if(this.onComplete) - { - this.onComplete(); - } - } -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - - -PIXI.FilterBlock = function() -{ - this.visible = true; - this.renderable = true; -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.ColorMatrixFilter = function() -{ - // set the uniforms - this.uniforms = { - matrix: {type: 'mat4', value: [1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1]}, - }; - - this.fragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform float invert;", - "uniform mat4 matrix;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;", - "gl_FragColor = gl_FragColor * vColor;", - "}" - ]; - -} - - -Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { - get: function() { - return this.uniforms.matrix.value; - }, - set: function(value) { - this.uniforms.matrix.value = value; - } -}); -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Text Object will create a line(s) of text to split a line you can use "\n" - * - * @class Text - * @extends Sprite - * @constructor - * @param text {String} The copy that you would like the text to display - * @param [style] {Object} The style parameters - * @param [style.font] {String} default "bold 20pt Arial" The style and size of the font - * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - * @param [style.stroke] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" - * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) - * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used - * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap - */ -PIXI.Text = function(text, style) -{ - this.canvas = document.createElement("canvas"); - this.context = this.canvas.getContext("2d"); - PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas)); - - this.setText(text); - this.setStyle(style); - - this.updateText(); - this.dirty = false; -}; - -// constructor -PIXI.Text.prototype = Object.create(PIXI.Sprite.prototype); -PIXI.Text.prototype.constructor = PIXI.Text; - -/** - * Set the style of the text - * - * @method setStyle - * @param [style] {Object} The style parameters - * @param [style.font="bold 20pt Arial"] {String} The style and size of the font - * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00" - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - * @param [style.stroke="black"] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00" - * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke) - * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used - * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap - */ -PIXI.Text.prototype.setStyle = function(style) -{ - style = style || {}; - style.font = style.font || "bold 20pt Arial"; - style.fill = style.fill || "black"; - style.align = style.align || "left"; - style.stroke = style.stroke || "black"; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136 - style.strokeThickness = style.strokeThickness || 0; - style.wordWrap = style.wordWrap || false; - style.wordWrapWidth = style.wordWrapWidth || 100; - this.style = style; - this.dirty = true; -}; - -/** - * Set the copy for the text object. To split a line you can use "\n" - * - * @methos setText - * @param {String} text The copy that you would like the text to display - */ -PIXI.Text.prototype.setText = function(text) -{ - this.text = text.toString() || " "; - this.dirty = true; -}; - -/** - * Renders text - * - * @method updateText - * @private - */ -PIXI.Text.prototype.updateText = function() -{ - this.context.font = this.style.font; - - var outputText = this.text; - - // word wrap - // preserve original text - if(this.style.wordWrap)outputText = this.wordWrap(this.text); - - //split text into lines - var lines = outputText.split(/(?:\r\n|\r|\n)/); - - //calculate text width - var lineWidths = []; - var maxLineWidth = 0; - for (var i = 0; i < lines.length; i++) - { - var lineWidth = this.context.measureText(lines[i]).width; - lineWidths[i] = lineWidth; - maxLineWidth = Math.max(maxLineWidth, lineWidth); - } - this.canvas.width = maxLineWidth + this.style.strokeThickness; - - //calculate text height - var lineHeight = this.determineFontHeight("font: " + this.style.font + ";") + this.style.strokeThickness; - this.canvas.height = lineHeight * lines.length; - - //set canvas text styles - this.context.fillStyle = this.style.fill; - this.context.font = this.style.font; - - this.context.strokeStyle = this.style.stroke; - this.context.lineWidth = this.style.strokeThickness; - - this.context.textBaseline = "top"; - - //draw lines line by line - for (i = 0; i < lines.length; i++) - { - var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight); - - if(this.style.align == "right") - { - linePosition.x += maxLineWidth - lineWidths[i]; - } - else if(this.style.align == "center") - { - linePosition.x += (maxLineWidth - lineWidths[i]) / 2; - } - - if(this.style.stroke && this.style.strokeThickness) - { - this.context.strokeText(lines[i], linePosition.x, linePosition.y); - } - - if(this.style.fill) - { - this.context.fillText(lines[i], linePosition.x, linePosition.y); - } - } - - this.updateTexture(); -}; - -/** - * Updates texture size based on canvas size - * - * @method updateTexture - * @private - */ -PIXI.Text.prototype.updateTexture = function() -{ - this.texture.baseTexture.width = this.canvas.width; - this.texture.baseTexture.height = this.canvas.height; - this.texture.frame.width = this.canvas.width; - this.texture.frame.height = this.canvas.height; - - this._width = this.canvas.width; - this._height = this.canvas.height; - - PIXI.texturesToUpdate.push(this.texture.baseTexture); -}; - -/** - * Updates the transfor of this object - * - * @method updateTransform - * @private - */ -PIXI.Text.prototype.updateTransform = function() -{ - if(this.dirty) - { - this.updateText(); - this.dirty = false; - } - - PIXI.Sprite.prototype.updateTransform.call(this); -}; - -/* - * http://stackoverflow.com/users/34441/ellisbben - * great solution to the problem! - * - * @method determineFontHeight - * @param fontStyle {Object} - * @private - */ -PIXI.Text.prototype.determineFontHeight = function(fontStyle) -{ - // build a little reference dictionary so if the font style has been used return a - // cached version... - var result = PIXI.Text.heightCache[fontStyle]; - - if(!result) - { - var body = document.getElementsByTagName("body")[0]; - var dummy = document.createElement("div"); - var dummyText = document.createTextNode("M"); - dummy.appendChild(dummyText); - dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0'); - body.appendChild(dummy); - - result = dummy.offsetHeight; - PIXI.Text.heightCache[fontStyle] = result; - - body.removeChild(dummy); - } - - return result; -}; - -/** - * A Text Object will apply wordwrap - * - * @method wordWrap - * @param text {String} - * @private - */ -PIXI.Text.prototype.wordWrap = function(text) -{ - // search good wrap position - var searchWrapPos = function(ctx, text, start, end, wrapWidth) - { - var p = Math.floor((end-start) / 2) + start; - if(p == start) { - return 1; - } - - if(ctx.measureText(text.substring(0,p)).width <= wrapWidth) - { - if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth) - { - return p; - } - else - { - return arguments.callee(ctx, text, p, end, wrapWidth); - } - } - else - { - return arguments.callee(ctx, text, start, p, wrapWidth); - } - }; - - var lineWrap = function(ctx, text, wrapWidth) - { - if(ctx.measureText(text).width <= wrapWidth || text.length < 1) - { - return text; - } - var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth); - return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth); - }; - - var result = ""; - var lines = text.split("\n"); - for (var i = 0; i < lines.length; i++) - { - result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n"; - } - - return result; -}; - -/** - * Destroys this text object - * - * @method destroy - * @param destroyTexture {Boolean} - */ -PIXI.Text.prototype.destroy = function(destroyTexture) -{ - if(destroyTexture) - { - this.texture.destroy(); - } - -}; - -PIXI.Text.heightCache = {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n" - * You can generate the fnt files using - * http://www.angelcode.com/products/bmfont/ for windows or - * http://www.bmglyph.com/ for mac. - * - * @class BitmapText - * @extends DisplayObjectContainer - * @constructor - * @param text {String} The copy that you would like the text to display - * @param style {Object} The style parameters - * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - */ -PIXI.BitmapText = function(text, style) -{ - PIXI.DisplayObjectContainer.call(this); - - this.setText(text); - this.setStyle(style); - this.updateText(); - this.dirty = false - -}; - -// constructor -PIXI.BitmapText.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); -PIXI.BitmapText.prototype.constructor = PIXI.BitmapText; - -/** - * Set the copy for the text object - * - * @method setText - * @param text {String} The copy that you would like the text to display - */ -PIXI.BitmapText.prototype.setText = function(text) -{ - this.text = text || " "; - this.dirty = true; -}; - -/** - * Set the style of the text - * - * @method setStyle - * @param style {Object} The style parameters - * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously) - * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right") - */ -PIXI.BitmapText.prototype.setStyle = function(style) -{ - style = style || {}; - style.align = style.align || "left"; - this.style = style; - - var font = style.font.split(" "); - this.fontName = font[font.length - 1]; - this.fontSize = font.length >= 2 ? parseInt(font[font.length - 2], 10) : PIXI.BitmapText.fonts[this.fontName].size; - - this.dirty = true; -}; - -/** - * Renders text - * - * @method updateText - * @private - */ -PIXI.BitmapText.prototype.updateText = function() -{ - var data = PIXI.BitmapText.fonts[this.fontName]; - var pos = new PIXI.Point(); - var prevCharCode = null; - var chars = []; - var maxLineWidth = 0; - var lineWidths = []; - var line = 0; - var scale = this.fontSize / data.size; - for(var i = 0; i < this.text.length; i++) - { - var charCode = this.text.charCodeAt(i); - if(/(?:\r\n|\r|\n)/.test(this.text.charAt(i))) - { - lineWidths.push(pos.x); - maxLineWidth = Math.max(maxLineWidth, pos.x); - line++; - - pos.x = 0; - pos.y += data.lineHeight; - prevCharCode = null; - continue; - } - - var charData = data.chars[charCode]; - if(!charData) continue; - - if(prevCharCode && charData[prevCharCode]) - { - pos.x += charData.kerning[prevCharCode]; - } - chars.push({texture:charData.texture, line: line, charCode: charCode, position: new PIXI.Point(pos.x + charData.xOffset, pos.y + charData.yOffset)}); - pos.x += charData.xAdvance; - - prevCharCode = charCode; - } - - lineWidths.push(pos.x); - maxLineWidth = Math.max(maxLineWidth, pos.x); - - var lineAlignOffsets = []; - for(i = 0; i <= line; i++) - { - var alignOffset = 0; - if(this.style.align == "right") - { - alignOffset = maxLineWidth - lineWidths[i]; - } - else if(this.style.align == "center") - { - alignOffset = (maxLineWidth - lineWidths[i]) / 2; - } - lineAlignOffsets.push(alignOffset); - } - - for(i = 0; i < chars.length; i++) - { - var c = new PIXI.Sprite(chars[i].texture)//PIXI.Sprite.fromFrame(chars[i].charCode); - c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale; - c.position.y = chars[i].position.y * scale; - c.scale.x = c.scale.y = scale; - this.addChild(c); - } - - this.width = pos.x * scale; - this.height = (pos.y + data.lineHeight) * scale; -}; - -/** - * Updates the transfor of this object - * - * @method updateTransform - * @private - */ -PIXI.BitmapText.prototype.updateTransform = function() -{ - if(this.dirty) - { - while(this.children.length > 0) - { - this.removeChild(this.getChildAt(0)); - } - this.updateText(); - - this.dirty = false; - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -}; - -PIXI.BitmapText.fonts = {}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - /** - * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive - * This manager also supports multitouch. - * - * @class InteractionManager - * @constructor - * @param stage {Stage} The stage to handle interactions - */ -PIXI.InteractionManager = function(stage) -{ - /** - * a refference to the stage - * - * @property stage - * @type Stage - */ - this.stage = stage; - - /** - * the mouse data - * - * @property mouse - * @type InteractionData - */ - this.mouse = new PIXI.InteractionData(); - - /** - * an object that stores current touches (InteractionData) by id reference - * - * @property touchs - * @type Object - */ - this.touchs = {}; - - - - // helpers - this.tempPoint = new PIXI.Point(); - //this.tempMatrix = mat3.create(); - - this.mouseoverEnabled = true; - - //tiny little interactiveData pool! - this.pool = []; - - this.interactiveItems = []; - this.interactionDOMElement = null; - - //this will make it so that you dont have to call bind all the time - this.onMouseMove = this.onMouseMove.bind( this ); - this.onMouseDown = this.onMouseDown.bind(this); - this.onMouseOut = this.onMouseOut.bind(this); - this.onMouseUp = this.onMouseUp.bind(this); - - this.onTouchStart = this.onTouchStart.bind(this); - this.onTouchEnd = this.onTouchEnd.bind(this); - this.onTouchMove = this.onTouchMove.bind(this); - - - this.last = 0; -} - -// constructor -PIXI.InteractionManager.prototype.constructor = PIXI.InteractionManager; - -/** - * Collects an interactive sprite recursively to have their interactions managed - * - * @method collectInteractiveSprite - * @param displayObject {DisplayObject} the displayObject to collect - * @param iParent {DisplayObject} - * @private - */ -PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObject, iParent) -{ - var children = displayObject.children; - var length = children.length; - - /// make an interaction tree... {item.__interactiveParent} - for (var i = length-1; i >= 0; i--) - { - var child = children[i]; - -// if(child.visible) { - // push all interactive bits - if(child.interactive) - { - iParent.interactiveChildren = true; - //child.__iParent = iParent; - this.interactiveItems.push(child); - - if(child.children.length > 0) - { - this.collectInteractiveSprite(child, child); - } - } - else - { - child.__iParent = null; - - if(child.children.length > 0) - { - this.collectInteractiveSprite(child, iParent); - } - } -// } - } -} - -/** - * Sets the target for event delegation - * - * @method setTarget - * @param target {WebGLRenderer|CanvasRenderer} the renderer to bind events to - * @private - */ -PIXI.InteractionManager.prototype.setTarget = function(target) -{ - this.target = target; - - //check if the dom element has been set. If it has don't do anything - if( this.interactionDOMElement === null ) { - - this.setTargetDomElement( target.view ); - } - - document.body.addEventListener('mouseup', this.onMouseUp, true); -} - - -/** - * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM - * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element - * to receive those events - * - * @method setTargetDomElement - * @param domElement {DOMElement} the dom element which will receive mouse and touch events - * @private - */ -PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement) -{ - //remove previouse listeners - if( this.interactionDOMElement !== null ) - { - this.interactionDOMElement.style['-ms-content-zooming'] = ''; - this.interactionDOMElement.style['-ms-touch-action'] = ''; - - this.interactionDOMElement.removeEventListener('mousemove', this.onMouseMove, true); - this.interactionDOMElement.removeEventListener('mousedown', this.onMouseDown, true); - this.interactionDOMElement.removeEventListener('mouseout', this.onMouseOut, true); - - // aint no multi touch just yet! - this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true); - this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true); - this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true); - } - - - if (window.navigator.msPointerEnabled) - { - // time to remove some of that zoom in ja.. - domElement.style['-ms-content-zooming'] = 'none'; - domElement.style['-ms-touch-action'] = 'none'; - - // DO some window specific touch! - } - - this.interactionDOMElement = domElement; - - domElement.addEventListener('mousemove', this.onMouseMove, true); - domElement.addEventListener('mousedown', this.onMouseDown, true); - domElement.addEventListener('mouseout', this.onMouseOut, true); - - // aint no multi touch just yet! - domElement.addEventListener('touchstart', this.onTouchStart, true); - domElement.addEventListener('touchend', this.onTouchEnd, true); - domElement.addEventListener('touchmove', this.onTouchMove, true); -} - - -/** - * updates the state of interactive objects - * - * @method update - * @private - */ -PIXI.InteractionManager.prototype.update = function() -{ - if(!this.target)return; - - // frequency of 30fps?? - var now = Date.now(); - var diff = now - this.last; - diff = (diff * 30) / 1000; - if(diff < 1)return; - this.last = now; - // - - // ok.. so mouse events?? - // yes for now :) - // OPTIMSE - how often to check?? - if(this.dirty) - { - this.dirty = false; - - var len = this.interactiveItems.length; - - for (var i=0; i < len; i++) { - this.interactiveItems[i].interactiveChildren = false; - } - - this.interactiveItems = []; - - if(this.stage.interactive)this.interactiveItems.push(this.stage); - // go through and collect all the objects that are interactive.. - this.collectInteractiveSprite(this.stage, this.stage); - } - - // loop through interactive objects! - var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - - //if(!item.visible)continue; - - // OPTIMISATION - only calculate every time if the mousemove function exists.. - // OK so.. does the object have any other interactive functions? - // hit-test the clip! - - - if(item.mouseover || item.mouseout || item.buttonMode) - { - // ok so there are some functions so lets hit test it.. - item.__hit = this.hitTest(item, this.mouse); - this.mouse.target = item; - // ok so deal with interactions.. - // loks like there was a hit! - if(item.__hit) - { - if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer"; - - if(!item.__isOver) - { - - if(item.mouseover)item.mouseover(this.mouse); - item.__isOver = true; - } - } - else - { - if(item.__isOver) - { - // roll out! - if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; - } - } - } - - // ---> - } -} - -/** - * Is called when the mouse moves accross the renderer element - * - * @method onMouseMove - * @param event {Event} The DOM event of the mouse moving - * @private - */ -PIXI.InteractionManager.prototype.onMouseMove = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - // TODO optimize by not check EVERY TIME! maybe half as often? // - var rect = this.interactionDOMElement.getBoundingClientRect(); - - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); - - var length = this.interactiveItems.length; - var global = this.mouse.global; - - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mousemove) - { - //call the function! - item.mousemove(this.mouse); - } - } -} - -/** - * Is called when the mouse button is pressed down on the renderer element - * - * @method onMouseDown - * @param event {Event} The DOM event of a mouse button being pressed down - * @private - */ -PIXI.InteractionManager.prototype.onMouseDown = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - - // loop through inteaction tree... - // hit test each item! -> - // get interactive items under point?? - //stage.__i - var length = this.interactiveItems.length; - var global = this.mouse.global; - - var index = 0; - var parent = this.stage; - - // while - // hit test - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mousedown || item.click) - { - item.__mouseIsDown = true; - item.__hit = this.hitTest(item, this.mouse); - - if(item.__hit) - { - //call the function! - if(item.mousedown)item.mousedown(this.mouse); - item.__isDown = true; - - // just the one! - if(!item.interactiveChildren)break; - } - } - } -} - - -PIXI.InteractionManager.prototype.onMouseOut = function(event) -{ - var length = this.interactiveItems.length; - - this.interactionDOMElement.style.cursor = "default"; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.__isOver) - { - this.mouse.target = item; - if(item.mouseout)item.mouseout(this.mouse); - item.__isOver = false; - } - } -} - -/** - * Is called when the mouse button is released on the renderer element - * - * @method onMouseUp - * @param event {Event} The DOM event of a mouse button being released - * @private - */ -PIXI.InteractionManager.prototype.onMouseUp = function(event) -{ - this.mouse.originalEvent = event || window.event; //IE uses window.event - - var global = this.mouse.global; - - - var length = this.interactiveItems.length; - var up = false; - - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - - if(item.mouseup || item.mouseupoutside || item.click) - { - item.__hit = this.hitTest(item, this.mouse); - - if(item.__hit && !up) - { - //call the function! - if(item.mouseup) - { - item.mouseup(this.mouse); - } - if(item.__isDown) - { - if(item.click)item.click(this.mouse); - } - - if(!item.interactiveChildren)up = true; - } - else - { - if(item.__isDown) - { - if(item.mouseupoutside)item.mouseupoutside(this.mouse); - } - } - - item.__isDown = false; - } - } -} - -/** - * Tests if the current mouse coords hit a sprite - * - * @method hitTest - * @param item {DisplayObject} The displayObject to test for a hit - * @param interactionData {InteractionData} The interactiondata object to update in the case of a hit - * @private - */ -PIXI.InteractionManager.prototype.hitTest = function(item, interactionData) -{ - var global = interactionData.global; - - if(item.vcount !== PIXI.visibleCount)return false; - - var isSprite = (item instanceof PIXI.Sprite), - worldTransform = item.worldTransform, - a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10), - x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, - y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; - - interactionData.target = item; - - //a sprite or display object with a hit area defined - if(item.hitArea && item.hitArea.contains) { - if(item.hitArea.contains(x, y)) { - //if(isSprite) - interactionData.target = item; - - return true; - } - - return false; - } - // a sprite with no hitarea defined - else if(isSprite) - { - var width = item.texture.frame.width, - height = item.texture.frame.height, - x1 = -width * item.anchor.x, - y1; - - if(x > x1 && x < x1 + width) - { - y1 = -height * item.anchor.y; - - if(y > y1 && y < y1 + height) - { - // set the target property if a hit is true! - interactionData.target = item - return true; - } - } - } - - var length = item.children.length; - - for (var i = 0; i < length; i++) - { - var tempItem = item.children[i]; - var hit = this.hitTest(tempItem, interactionData); - if(hit) - { - // hmm.. TODO SET CORRECT TARGET? - interactionData.target = item - return true; - } - } - - return false; -} - -/** - * Is called when a touch is moved accross the renderer element - * - * @method onTouchMove - * @param event {Event} The DOM event of a touch moving accross the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchMove = function(event) -{ - var rect = this.interactionDOMElement.getBoundingClientRect(); - var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - var touchData = this.touchs[touchEvent.identifier]; - touchData.originalEvent = event || window.event; - - // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - } - - var length = this.interactiveItems.length; - for (var i = 0; i < length; i++) - { - var item = this.interactiveItems[i]; - if(item.touchmove)item.touchmove(touchData); - } -} - -/** - * Is called when a touch is started on the renderer element - * - * @method onTouchStart - * @param event {Event} The DOM event of a touch starting on the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchStart = function(event) -{ - var rect = this.interactionDOMElement.getBoundingClientRect(); - - var changedTouches = event.changedTouches; - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - - var touchData = this.pool.pop(); - if(!touchData)touchData = new PIXI.InteractionData(); - - touchData.originalEvent = event || window.event; - - this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - - var length = this.interactiveItems.length; - - for (var j = 0; j < length; j++) - { - var item = this.interactiveItems[j]; - - if(item.touchstart || item.tap) - { - item.__hit = this.hitTest(item, touchData); - - if(item.__hit) - { - //call the function! - if(item.touchstart)item.touchstart(touchData); - item.__isDown = true; - item.__touchData = touchData; - - if(!item.interactiveChildren)break; - } - } - } - } -} - -/** - * Is called when a touch is ended on the renderer element - * - * @method onTouchEnd - * @param event {Event} The DOM event of a touch ending on the renderer view - * @private - */ -PIXI.InteractionManager.prototype.onTouchEnd = function(event) -{ - //this.mouse.originalEvent = event || window.event; //IE uses window.event - var rect = this.interactionDOMElement.getBoundingClientRect(); - var changedTouches = event.changedTouches; - - for (var i=0; i < changedTouches.length; i++) - { - var touchEvent = changedTouches[i]; - var touchData = this.touchs[touchEvent.identifier]; - var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); - - var length = this.interactiveItems.length; - for (var j = 0; j < length; j++) - { - var item = this.interactiveItems[j]; - var itemTouchData = item.__touchData; // <-- Here! - item.__hit = this.hitTest(item, touchData); - - if(itemTouchData == touchData) - { - // so this one WAS down... - touchData.originalEvent = event || window.event; - // hitTest?? - - if(item.touchend || item.tap) - { - if(item.__hit && !up) - { - if(item.touchend)item.touchend(touchData); - if(item.__isDown) - { - if(item.tap)item.tap(touchData); - } - - if(!item.interactiveChildren)up = true; - } - else - { - if(item.__isDown) - { - if(item.touchendoutside)item.touchendoutside(touchData); - } - } - - item.__isDown = false; - } - - item.__touchData = null; - - } - else - { - - } - } - // remove the touch.. - this.pool.push(touchData); - this.touchs[touchEvent.identifier] = null; - } -} - -/** - * Holds all information related to an Interaction event - * - * @class InteractionData - * @constructor - */ -PIXI.InteractionData = function() -{ - /** - * This point stores the global coords of where the touch/mouse event happened - * - * @property global - * @type Point - */ - this.global = new PIXI.Point(); - - // this is here for legacy... but will remove - this.local = new PIXI.Point(); - - /** - * The target Sprite that was interacted with - * - * @property target - * @type Sprite - */ - this.target; - - /** - * When passed to an event handler, this will be the original DOM Event that was captured - * - * @property originalEvent - * @type Event - */ - this.originalEvent; -} - -/** - * This will return the local coords of the specified displayObject for this InteractionData - * - * @method getLocalPosition - * @param displayObject {DisplayObject} The DisplayObject that you would like the local coords off - * @return {Point} A point containing the coords of the InteractionData position relative to the DisplayObject - */ -PIXI.InteractionData.prototype.getLocalPosition = function(displayObject) -{ - var worldTransform = displayObject.worldTransform; - var global = this.global; - - // do a cheeky transform to get the mouse coords; - var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2], - a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5], - id = 1 / (a00 * a11 + a01 * -a10); - // set the mouse coords... - return new PIXI.Point(a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, - a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id) -} - -// constructor -PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A Stage represents the root of the display tree. Everything connected to the stage is rendered - * - * @class Stage - * @extends DisplayObjectContainer - * @constructor - * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format - * like: 0xFFFFFF for white - */ -PIXI.Stage = function(backgroundColor) -{ - PIXI.DisplayObjectContainer.call( this ); - - /** - * [read-only] Current transform of the object based on world (parent) factors - * - * @property worldTransform - * @type Mat3 - * @readOnly - * @private - */ - this.worldTransform = PIXI.mat3.create(); - - /** - * Whether or not the stage is interactive - * - * @property interactive - * @type Boolean - */ - this.interactive = true; - - /** - * The interaction manage for this stage, manages all interactive activity on the stage - * - * @property interactive - * @type InteractionManager - */ - this.interactionManager = new PIXI.InteractionManager(this); - - /** - * Whether the stage is dirty and needs to have interactions updated - * - * @property dirty - * @type Boolean - * @private - */ - this.dirty = true; - - this.__childrenAdded = []; - this.__childrenRemoved = []; - - //the stage is it's own stage - this.stage = this; - - //optimize hit detection a bit - this.stage.hitArea = new PIXI.Rectangle(0,0,100000, 100000); - - this.setBackgroundColor(backgroundColor); - this.worldVisible = true; -} - -// constructor -PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Stage.prototype.constructor = PIXI.Stage; - -/** - * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. - * This is useful for when you have other DOM elements ontop of the Canvas element. - * - * @method setInteractionDelegate - * @param domElement {DOMElement} This new domElement which will receive mouse/touch events - */ -PIXI.Stage.prototype.setInteractionDelegate = function(domElement) -{ - this.interactionManager.setTargetDomElement( domElement ); -} - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.Stage.prototype.updateTransform = function() -{ - this.worldAlpha = 1; - this.vcount = PIXI.visibleCount; - - for(var i=0,j=this.children.length; i> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; -} - -/** - * A polyfill for Function.prototype.bind - * - * @method bind - */ -if (typeof Function.prototype.bind != 'function') { - Function.prototype.bind = (function () { - var slice = Array.prototype.slice; - return function (thisArg) { - var target = this, boundArgs = slice.call(arguments, 1); - - if (typeof target != 'function') throw new TypeError(); - - function bound() { - var args = boundArgs.concat(slice.call(arguments)); - target.apply(this instanceof bound ? this : thisArg, args); - } - - bound.prototype = (function F(proto) { - proto && (F.prototype = proto); - if (!(this instanceof F)) return new F; - })(target.prototype); - - return bound; - }; - })(); -} - -/** - * A wrapper for ajax requests to be handled cross browser - * - * @class AjaxRequest - * @constructor - */ -var AjaxRequest = PIXI.AjaxRequest = function() -{ - var activexmodes = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Microsoft.XMLHTTP"] //activeX versions to check for in IE - - if (window.ActiveXObject) - { //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken) - for (var i=0; i>>>>>>>>") - console.log("_") - var safe = 0; - var tmp = item.first; - console.log(tmp); - - while(tmp._iNext) - { - safe++; - tmp = tmp._iNext; - console.log(tmp); - // console.log(tmp); - - if(safe > 100) - { - console.log("BREAK") - break - } - } -} - - - - - - -/** - * https://github.com/mrdoob/eventtarget.js/ - * THankS mr DOob! - */ - -/** - * Adds event emitter functionality to a class - * - * @class EventTarget - * @example - * function MyEmitter() { - * PIXI.EventTarget.call(this); //mixes in event target stuff - * } - * - * var em = new MyEmitter(); - * em.emit({ type: 'eventName', data: 'some data' }); - */ -PIXI.EventTarget = function () { - - var listeners = {}; - - this.addEventListener = this.on = function ( type, listener ) { - - - if ( listeners[ type ] === undefined ) { - - listeners[ type ] = []; - - } - - if ( listeners[ type ].indexOf( listener ) === - 1 ) { - - listeners[ type ].push( listener ); - } - - }; - - this.dispatchEvent = this.emit = function ( event ) { - - if ( !listeners[ event.type ] || !listeners[ event.type ].length ) { - - return; - - } - - for(var i = 0, l = listeners[ event.type ].length; i < l; i++) { - - listeners[ event.type ][ i ]( event ); - - } - - }; - - this.removeEventListener = this.off = function ( type, listener ) { - - var index = listeners[ type ].indexOf( listener ); - - if ( index !== - 1 ) { - - listeners[ type ].splice( index, 1 ); - - } - - }; - -}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * This helper function will automatically detect which renderer you should be using. - * WebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by - * the browser then this function will return a canvas renderer - * - * @method autoDetectRenderer - * @static - * @param width {Number} the width of the renderers view - * @param height {Number} the height of the renderers view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment) - * - * antialias - */ -PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) -{ - if(!width)width = 800; - if(!height)height = 600; - - // BORROWED from Mr Doob (mrdoob.com) - var webgl = ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(); - - //console.log(webgl); - if( webgl ) - { - return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); - } - - return new PIXI.CanvasRenderer(width, height, view, transparent); -}; - - - -/* - PolyK library - url: http://polyk.ivank.net - Released under MIT licence. - - Copyright (c) 2012 Ivan Kuckir - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - - This is an amazing lib! - - slightly modified by mat groves (matgroves.com); -*/ - -PIXI.PolyK = {}; - -/** - * Triangulates shapes for webGL graphic fills - * - * @method Triangulate - * @namespace PolyK - * @constructor - */ -PIXI.PolyK.Triangulate = function(p) -{ - var sign = true; - - var n = p.length>>1; - if(n<3) return []; - var tgs = []; - var avl = []; - for(var i=0; i 3) - { - var i0 = avl[(i+0)%al]; - var i1 = avl[(i+1)%al]; - var i2 = avl[(i+2)%al]; - - var ax = p[2*i0], ay = p[2*i0+1]; - var bx = p[2*i1], by = p[2*i1+1]; - var cx = p[2*i2], cy = p[2*i2+1]; - - var earFound = false; - if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign)) - { - earFound = true; - for(var j=0; j 3*al) - { - // need to flip flip reverse it! - // reset! - if(sign) - { - var tgs = []; - avl = []; - for(var i=0; i= 0) && (v >= 0) && (u + v < 1); -} - -/** - * Checks if a shape is convex - * - * @class _convex - * @namespace PolyK - * @private - */ -PIXI.PolyK._convex = function(ax, ay, bx, by, cx, cy, sign) -{ - return ((ay-by)*(cx-bx) + (bx-ax)*(cy-by) >= 0) == sign; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/* - * the default suoer fast shader! - */ - -PIXI.shaderFragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", - "gl_FragColor = gl_FragColor * vColor;", - "}" -]; - -PIXI.shaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - - "uniform vec2 projectionVector;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "void main(void) {", - "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" -]; - -/* - * the triangle strip shader.. - */ - -PIXI.stripShaderFragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform float alpha;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", - "gl_FragColor = gl_FragColor * alpha;", - "}" -]; - - -PIXI.stripShaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" -]; - -/* - * primitive shader.. - */ - -PIXI.primitiveShaderFragmentSrc = [ - "precision mediump float;", - "varying vec4 vColor;", - "void main(void) {", - "gl_FragColor = vColor;", - "}" -]; - -PIXI.primitiveShaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec4 aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "uniform float alpha;", - "varying vec4 vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vColor = aColor * alpha;", - "}" -]; - -PIXI.shaderStack = []; - -PIXI.initPrimitiveShader = function() -{ - var gl = PIXI.gl; - - var shaderProgram = PIXI.compileProgram(PIXI.primitiveShaderVertexSrc, PIXI.primitiveShaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); - - - //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - //gl.enableVertexAttribArray(shaderProgram.colorAttribute); -//gl.enableVertexAttribArray(program.textureCoordAttribute); - - shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); - - PIXI.primitiveProgram = shaderProgram; - - -} - -PIXI.initDefaultShader = function() -{ - PIXI.defaultShader = new PIXI.PixiShader(); - PIXI.defaultShader.init(); - PIXI.activateShader(PIXI.defaultShader); - /* - PIXI.shaderStack.push(PIXI.defaultShader); - PIXI.current*/ -} - -PIXI.initDefaultStripShader = function() -{ - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.stripShaderVertexSrc, PIXI.stripShaderFragmentSrc) - - gl.useProgram(shaderProgram); - - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); - shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); - - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.stripShaderProgram = shaderProgram; -} - -PIXI.CompileVertexShader = function(gl, shaderSrc) -{ - return PIXI._CompileShader(gl, shaderSrc, gl.VERTEX_SHADER); -} - -PIXI.CompileFragmentShader = function(gl, shaderSrc) -{ - return PIXI._CompileShader(gl, shaderSrc, gl.FRAGMENT_SHADER); -} - -PIXI._CompileShader = function(gl, shaderSrc, shaderType) -{ - var src = shaderSrc.join("\n"); - var shader = gl.createShader(shaderType); - gl.shaderSource(shader, src); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - alert(gl.getShaderInfoLog(shader)); - return null; - } - - return shader; -} - - -PIXI.compileProgram = function(vertexSrc, fragmentSrc) -{ - var gl = PIXI.gl; - var fragmentShader = PIXI.CompileFragmentShader(gl, fragmentSrc); - var vertexShader = PIXI.CompileVertexShader(gl, vertexSrc); - - var shaderProgram = gl.createProgram(); - - gl.attachShader(shaderProgram, vertexShader); - gl.attachShader(shaderProgram, fragmentShader); - gl.linkProgram(shaderProgram); - - if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { - alert("Could not initialise shaders"); - } - - return shaderProgram; -} - -PIXI.activateShader = function(shader) -{ - PIXI.shaderStack.push(shader); - - //console.log(">>>") - var gl = PIXI.gl; - - var shaderProgram = shader.program; - - // map uniforms.. - gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - - shader.syncUniforms(); - - PIXI.currentShader = shaderProgram; -} - - -PIXI.popShader = function() -{ - var gl = PIXI.gl; - // activate last program.. - var lastProgram = PIXI.shaderStack.pop(); - - var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; - - gl.useProgram(shaderProgram); - - PIXI.currentShader = shaderProgram; -} - -PIXI.activatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.primitiveProgram); - - //gl.disableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); - //gl.disableVertexAttribArray(PIXI.currentShader.colorAttribute); - gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); - - //gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute); - //gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute); -} - -PIXI.deactivatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.currentShader); - - gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); - //gl.enableVertexAttribArray(PIXI.currentShader.vertexPositionAttribute); - //gl.enableVertexAttribArray(PIXI.currentShader.colorAttribute); -} -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -PIXI.PixiShader = function() -{ - // the webGL program.. - this.program; - - this.fragmentSrc = [ - "precision lowp float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;", - "}" - ]; - -} - -PIXI.PixiShader.prototype.init = function() -{ - var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) - - var gl = PIXI.gl; - - gl.useProgram(program); - - // get the default shader bits! - program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); - program.colorAttribute = gl.getAttribLocation(program, "aColor"); - program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); - - program.projectionVector = gl.getUniformLocation(program, "projectionVector"); - program.samplerUniform = gl.getUniformLocation(program, "uSampler"); - - // add those custom shaders! - for (var key in this.uniforms) - { - // get the uniform locations.. - program[key] = gl.getUniformLocation(program, key); - } - - this.program = program; -} - -PIXI.PixiShader.prototype.syncUniforms = function() -{ - var gl = PIXI.gl; - - for (var key in this.uniforms) - { - //var - var type = this.uniforms[key].type; - - // need to grow this! - if(type == "f") - { - gl.uniform1f(this.program[key], this.uniforms[key].value); - } - else if(type == "mat4") - { - gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); - } - } - -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A set of functions used by the webGL renderer to draw the primitive graphics data - * - * @class CanvasGraphics - */ -PIXI.WebGLGraphics = function() -{ - -} - -/** - * Renders the graphics object - * - * @static - * @private - * @method renderGraphics - * @param graphics {Graphics} - * @param projection {Object} - */ -PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) -{ - var gl = PIXI.gl; - - if(!graphics._webGL)graphics._webGL = {points:[], indices:[], lastIndex:0, - buffer:gl.createBuffer(), - indexBuffer:gl.createBuffer()}; - - if(graphics.dirty) - { - graphics.dirty = false; - - if(graphics.clearDirty) - { - graphics.clearDirty = false; - - graphics._webGL.lastIndex = 0; - graphics._webGL.points = []; - graphics._webGL.indices = []; - - } - - PIXI.WebGLGraphics.updateGraphics(graphics); - } - - - PIXI.activatePrimitiveShader(); - - // This could be speeded up fo sure! - var m = PIXI.mat3.clone(graphics.worldTransform); - - PIXI.mat3.transpose(m); - - // set the matrix transform for the - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - gl.uniformMatrix3fv(PIXI.primitiveProgram.translationMatrix, false, m); - - gl.uniform2f(PIXI.primitiveProgram.projectionVector, projection.x, projection.y); - - gl.uniform1f(PIXI.primitiveProgram.alpha, graphics.worldAlpha); - - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - - // WHY DOES THIS LINE NEED TO BE THERE??? - //gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - // its not even used.. but need to be set or it breaks? - // only on pc though.. - - gl.vertexAttribPointer(PIXI.primitiveProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 4 * 6, 0); - gl.vertexAttribPointer(PIXI.primitiveProgram.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4); - - // set the index buffer! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); - - gl.drawElements(gl.TRIANGLE_STRIP, graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 ); - - PIXI.deactivatePrimitiveShader(); - - // return to default shader... -// PIXI.activateShader(PIXI.defaultShader); -} - -/** - * Updates the graphics object - * - * @static - * @private - * @method updateGraphics - * @param graphics {Graphics} - */ -PIXI.WebGLGraphics.updateGraphics = function(graphics) -{ - for (var i=graphics._webGL.lastIndex; i < graphics.graphicsData.length; i++) - { - var data = graphics.graphicsData[i]; - - if(data.type == PIXI.Graphics.POLY) - { - if(data.fill) - { - if(data.points.length>3) - PIXI.WebGLGraphics.buildPoly(data, graphics._webGL); - } - - if(data.lineWidth > 0) - { - PIXI.WebGLGraphics.buildLine(data, graphics._webGL); - } - } - else if(data.type == PIXI.Graphics.RECT) - { - PIXI.WebGLGraphics.buildRectangle(data, graphics._webGL); - } - else if(data.type == PIXI.Graphics.CIRC || data.type == PIXI.Graphics.ELIP) - { - PIXI.WebGLGraphics.buildCircle(data, graphics._webGL); - } - }; - - graphics._webGL.lastIndex = graphics.graphicsData.length; - - var gl = PIXI.gl; - - graphics._webGL.glPoints = new Float32Array(graphics._webGL.points); - - gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); - gl.bufferData(gl.ARRAY_BUFFER, graphics._webGL.glPoints, gl.STATIC_DRAW); - - graphics._webGL.glIndicies = new Uint16Array(graphics._webGL.indices); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.glIndicies, gl.STATIC_DRAW); -} - -/** - * Builds a rectangle to draw - * - * @static - * @private - * @method buildRectangle - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData) -{ - // --- // - // need to convert points to a nice regular data - // - var rectData = graphicsData.points; - var x = rectData[0]; - var y = rectData[1]; - var width = rectData[2]; - var height = rectData[3]; - - - if(graphicsData.fill) - { - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var verts = webGLData.points; - var indices = webGLData.indices; - - var vertPos = verts.length/6; - - // start - verts.push(x, y); - verts.push(r, g, b, alpha); - - verts.push(x + width, y); - verts.push(r, g, b, alpha); - - verts.push(x , y + height); - verts.push(r, g, b, alpha); - - verts.push(x + width, y + height); - verts.push(r, g, b, alpha); - - // insert 2 dead triangles.. - indices.push(vertPos, vertPos, vertPos+1, vertPos+2, vertPos+3, vertPos+3) - } - - if(graphicsData.lineWidth) - { - graphicsData.points = [x, y, - x + width, y, - x + width, y + height, - x, y + height, - x, y]; - - PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); - } - -} - -/** - * Builds a circle to draw - * - * @static - * @private - * @method buildCircle - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData) -{ - // --- // - // need to convert points to a nice regular data - // - var rectData = graphicsData.points; - var x = rectData[0]; - var y = rectData[1]; - var width = rectData[2]; - var height = rectData[3]; - - var totalSegs = 40; - var seg = (Math.PI * 2) / totalSegs ; - - if(graphicsData.fill) - { - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var verts = webGLData.points; - var indices = webGLData.indices; - - var vecPos = verts.length/6; - - indices.push(vecPos); - - for (var i=0; i < totalSegs + 1 ; i++) - { - verts.push(x,y, r, g, b, alpha); - - verts.push(x + Math.sin(seg * i) * width, - y + Math.cos(seg * i) * height, - r, g, b, alpha); - - indices.push(vecPos++, vecPos++); - }; - - indices.push(vecPos-1); - } - - if(graphicsData.lineWidth) - { - graphicsData.points = []; - - for (var i=0; i < totalSegs + 1; i++) - { - graphicsData.points.push(x + Math.sin(seg * i) * width, - y + Math.cos(seg * i) * height) - }; - - PIXI.WebGLGraphics.buildLine(graphicsData, webGLData); - } - -} - -/** - * Builds a line to draw - * - * @static - * @private - * @method buildLine - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData) -{ - // TODO OPTIMISE! - - var wrap = true; - var points = graphicsData.points; - if(points.length == 0)return; - - // get first and last point.. figure out the middle! - var firstPoint = new PIXI.Point( points[0], points[1] ); - var lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - - // if the first point is the last point - goona have issues :) - if(firstPoint.x == lastPoint.x && firstPoint.y == lastPoint.y) - { - points.pop(); - points.pop(); - - lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] ); - - var midPointX = lastPoint.x + (firstPoint.x - lastPoint.x) *0.5; - var midPointY = lastPoint.y + (firstPoint.y - lastPoint.y) *0.5; - - points.unshift(midPointX, midPointY); - points.push(midPointX, midPointY) - } - - var verts = webGLData.points; - var indices = webGLData.indices; - var length = points.length / 2; - var indexCount = points.length; - var indexStart = verts.length/6; - - // DRAW the Line - var width = graphicsData.lineWidth / 2; - - // sort color - var color = HEXtoRGB(graphicsData.lineColor); - var alpha = graphicsData.lineAlpha; - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var p1x, p1y, p2x, p2y, p3x, p3y; - var perpx, perpy, perp2x, perp2y, perp3x, perp3y; - var ipx, ipy; - var a1, b1, c1, a2, b2, c2; - var denom, pdist, dist; - - p1x = points[0]; - p1y = points[1]; - - p2x = points[2]; - p2y = points[3]; - - perpx = -(p1y - p2y); - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - // start - verts.push(p1x - perpx , p1y - perpy, - r, g, b, alpha); - - verts.push(p1x + perpx , p1y + perpy, - r, g, b, alpha); - - for (var i = 1; i < length-1; i++) - { - p1x = points[(i-1)*2]; - p1y = points[(i-1)*2 + 1]; - - p2x = points[(i)*2] - p2y = points[(i)*2 + 1] - - p3x = points[(i+1)*2]; - p3y = points[(i+1)*2 + 1]; - - perpx = -(p1y - p2y); - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - perp2x = -(p2y - p3y); - perp2y = p2x - p3x; - - dist = Math.sqrt(perp2x*perp2x + perp2y*perp2y); - perp2x /= dist; - perp2y /= dist; - perp2x *= width; - perp2y *= width; - - a1 = (-perpy + p1y) - (-perpy + p2y); - b1 = (-perpx + p2x) - (-perpx + p1x); - c1 = (-perpx + p1x) * (-perpy + p2y) - (-perpx + p2x) * (-perpy + p1y); - a2 = (-perp2y + p3y) - (-perp2y + p2y); - b2 = (-perp2x + p2x) - (-perp2x + p3x); - c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y); - - denom = a1*b2 - a2*b1; - - if (denom == 0) { - denom+=1; - } - - px = (b1*c2 - b2*c1)/denom; - py = (a2*c1 - a1*c2)/denom; - - pdist = (px -p2x) * (px -p2x) + (py -p2y) + (py -p2y); - - if(pdist > 140 * 140) - { - perp3x = perpx - perp2x; - perp3y = perpy - perp2y; - - dist = Math.sqrt(perp3x*perp3x + perp3y*perp3y); - perp3x /= dist; - perp3y /= dist; - perp3x *= width; - perp3y *= width; - - verts.push(p2x - perp3x, p2y -perp3y); - verts.push(r, g, b, alpha); - - verts.push(p2x + perp3x, p2y +perp3y); - verts.push(r, g, b, alpha); - - verts.push(p2x - perp3x, p2y -perp3y); - verts.push(r, g, b, alpha); - - indexCount++; - } - else - { - verts.push(px , py); - verts.push(r, g, b, alpha); - - verts.push(p2x - (px-p2x), p2y - (py - p2y)); - verts.push(r, g, b, alpha); - } - } - - p1x = points[(length-2)*2] - p1y = points[(length-2)*2 + 1] - - p2x = points[(length-1)*2] - p2y = points[(length-1)*2 + 1] - - perpx = -(p1y - p2y) - perpy = p1x - p2x; - - dist = Math.sqrt(perpx*perpx + perpy*perpy); - perpx /= dist; - perpy /= dist; - perpx *= width; - perpy *= width; - - verts.push(p2x - perpx , p2y - perpy) - verts.push(r, g, b, alpha); - - verts.push(p2x + perpx , p2y + perpy) - verts.push(r, g, b, alpha); - - indices.push(indexStart); - - for (var i=0; i < indexCount; i++) - { - indices.push(indexStart++); - }; - - indices.push(indexStart-1); -} - -/** - * Builds a polygon to draw - * - * @static - * @private - * @method buildPoly - * @param graphics {Graphics} - * @param webGLData {Object} - */ -PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData) -{ - var points = graphicsData.points; - if(points.length < 6)return; - - // get first and last point.. figure out the middle! - var verts = webGLData.points; - var indices = webGLData.indices; - - var length = points.length / 2; - - // sort color - var color = HEXtoRGB(graphicsData.fillColor); - var alpha = graphicsData.fillAlpha; - var r = color[0] * alpha; - var g = color[1] * alpha; - var b = color[2] * alpha; - - var triangles = PIXI.PolyK.Triangulate(points); - - var vertPos = verts.length / 6; - - for (var i=0; i < triangles.length; i+=3) - { - indices.push(triangles[i] + vertPos); - indices.push(triangles[i] + vertPos); - indices.push(triangles[i+1] + vertPos); - indices.push(triangles[i+2] +vertPos); - indices.push(triangles[i+2] + vertPos); - }; - - for (var i = 0; i < length; i++) - { - verts.push(points[i * 2], points[i * 2 + 1], - r, g, b, alpha); - }; -} - -function HEXtoRGB(hex) { - return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255]; -} - - - - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI._defaultFrame = new PIXI.Rectangle(0,0,1,1); - -// an instance of the gl context.. -// only one at the moment :/ -PIXI.gl; - -/** - * the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer - * should be used for browsers support webGL. This Render works by automatically managing webGLBatchs. - * So no need for Sprite Batch's or Sprite Cloud's - * Dont forget to add the view to your DOM or you will not see anything :) - * - * @class WebGLRenderer - * @constructor - * @param width=0 {Number} the width of the canvas view - * @param height=0 {Number} the height of the canvas view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) - * - */ -PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) -{ - // do a catch.. only 1 webGL renderer.. - - this.transparent = !!transparent; - - this.width = width || 800; - this.height = height || 600; - - this.view = view || document.createElement( 'canvas' ); - this.view.width = this.width; - this.view.height = this.height; - - // deal with losing context.. - var scope = this; - this.view.addEventListener('webglcontextlost', function(event) { scope.handleContextLost(event); }, false) - this.view.addEventListener('webglcontextrestored', function(event) { scope.handleContextRestored(event); }, false) - - this.batchs = []; - - try - { - PIXI.gl = this.gl = this.view.getContext("experimental-webgl", { - alpha: this.transparent, - antialias:!!antialias, // SPEED UP?? - premultipliedAlpha:false, - stencil:true - }); - } - catch (e) - { - throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this); - } - - PIXI.initDefaultShader(); - PIXI.initPrimitiveShader(); - PIXI.initDefaultStripShader(); - - -// PIXI.activateDefaultShader(); - - var gl = this.gl; - PIXI.WebGLRenderer.gl = gl; - - this.batch = new PIXI.WebGLBatch(gl); - gl.disable(gl.DEPTH_TEST); - gl.disable(gl.CULL_FACE); - - gl.enable(gl.BLEND); - gl.colorMask(true, true, true, this.transparent); - - PIXI.projection = new PIXI.Point(400, 300); - - this.resize(this.width, this.height); - this.contextLost = false; - - PIXI.activateShader(PIXI.defaultShader); - - this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); - -} - -// constructor -PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer; - -/** - * Gets a new WebGLBatch from the pool - * - * @static - * @method getBatch - * @return {WebGLBatch} - * @private - */ -PIXI.WebGLRenderer.getBatch = function() -{ - if(PIXI._batchs.length == 0) - { - return new PIXI.WebGLBatch(PIXI.WebGLRenderer.gl); - } - else - { - return PIXI._batchs.pop(); - } -} - -/** - * Puts a batch back into the pool - * - * @static - * @method returnBatch - * @param batch {WebGLBatch} The batch to return - * @private - */ -PIXI.WebGLRenderer.returnBatch = function(batch) -{ - batch.clean(); - PIXI._batchs.push(batch); -} - -/** - * Renders the stage to its webGL view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.WebGLRenderer.prototype.render = function(stage) -{ - if(this.contextLost)return; - - - // if rendering a new stage clear the batchs.. - if(this.__stage !== stage) - { - // TODO make this work - // dont think this is needed any more? - this.__stage = stage; - this.stageRenderGroup.setRenderable(stage); - } - - // TODO not needed now... - // update children if need be - // best to remove first! - /*for (var i=0; i < stage.__childrenRemoved.length; i++) - { - var group = stage.__childrenRemoved[i].__renderGroup - if(group)group.removeDisplayObject(stage.__childrenRemoved[i]); - }*/ - - // update any textures - PIXI.WebGLRenderer.updateTextures(); - - // update the scene graph - PIXI.visibleCount++; - stage.updateTransform(); - - var gl = this.gl; - - // -- Does this need to be set every frame? -- // - gl.colorMask(true, true, true, this.transparent); - gl.viewport(0, 0, this.width, this.height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent); - gl.clear(gl.COLOR_BUFFER_BIT); - - // HACK TO TEST - - this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit; - this.stageRenderGroup.render(PIXI.projection); - - // interaction - // run interaction! - if(stage.interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - - // after rendering lets confirm all frames that have been uodated.. - if(PIXI.Texture.frameUpdates.length > 0) - { - for (var i=0; i < PIXI.Texture.frameUpdates.length; i++) - { - PIXI.Texture.frameUpdates[i].updateFrame = false; - }; - - PIXI.Texture.frameUpdates = []; - } -} - -/** - * Updates the textures loaded into this webgl renderer - * - * @static - * @method updateTextures - * @private - */ -PIXI.WebGLRenderer.updateTextures = function() -{ - //TODO break this out into a texture manager... - for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]); - for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]); - PIXI.texturesToUpdate = []; - PIXI.texturesToDestroy = []; -} - -/** - * Updates a loaded webgl texture - * - * @static - * @method updateTexture - * @param texture {Texture} The texture to update - * @private - */ -PIXI.WebGLRenderer.updateTexture = function(texture) -{ - //TODO break this out into a texture manager... - var gl = PIXI.gl; - - if(!texture._glTexture) - { - texture._glTexture = gl.createTexture(); - } - - if(texture.hasLoaded) - { - gl.bindTexture(gl.TEXTURE_2D, texture._glTexture); - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - - // reguler... - - if(!texture._powerOf2) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - } - - gl.bindTexture(gl.TEXTURE_2D, null); - } -} - -/** - * Destroys a loaded webgl texture - * - * @method destroyTexture - * @param texture {Texture} The texture to update - * @private - */ -PIXI.WebGLRenderer.destroyTexture = function(texture) -{ - //TODO break this out into a texture manager... - var gl = PIXI.gl; - - if(texture._glTexture) - { - texture._glTexture = gl.createTexture(); - gl.deleteTexture(gl.TEXTURE_2D, texture._glTexture); - } -} - -/** - * resizes the webGL view to the specified width and height - * - * @method resize - * @param width {Number} the new width of the webGL view - * @param height {Number} the new height of the webGL view - */ -PIXI.WebGLRenderer.prototype.resize = function(width, height) -{ - this.width = width; - this.height = height; - - this.view.width = width; - this.view.height = height; - - this.gl.viewport(0, 0, this.width, this.height); - - //var projectionMatrix = this.projectionMatrix; - - PIXI.projection.x = this.width/2; - PIXI.projection.y = this.height/2; - -// projectionMatrix[0] = 2/this.width; -// projectionMatrix[5] = -2/this.height; -// projectionMatrix[12] = -1; -// projectionMatrix[13] = 1; -} - -/** - * Handles a lost webgl context - * - * @method handleContextLost - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextLost = function(event) -{ - event.preventDefault(); - this.contextLost = true; -} - -/** - * Handles a restored webgl context - * - * @method handleContextRestored - * @param event {Event} - * @private - */ -PIXI.WebGLRenderer.prototype.handleContextRestored = function(event) -{ - this.gl = this.view.getContext("experimental-webgl", { - alpha: true - }); - - this.initShaders(); - - for(var key in PIXI.TextureCache) - { - var texture = PIXI.TextureCache[key].baseTexture; - texture._glTexture = null; - PIXI.WebGLRenderer.updateTexture(texture); - }; - - for (var i=0; i < this.batchs.length; i++) - { - this.batchs[i].restoreLostContext(this.gl)// - this.batchs[i].dirty = true; - }; - - PIXI._restoreBatchs(this.gl); - - this.contextLost = false; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI._batchs = []; - -/** - * @private - */ -PIXI._getBatch = function(gl) -{ - if(PIXI._batchs.length == 0) - { - return new PIXI.WebGLBatch(gl); - } - else - { - return PIXI._batchs.pop(); - } -} - -/** - * @private - */ -PIXI._returnBatch = function(batch) -{ - batch.clean(); - PIXI._batchs.push(batch); -} - -/** - * @private - */ -PIXI._restoreBatchs = function(gl) -{ - for (var i=0; i < PIXI._batchs.length; i++) - { - PIXI._batchs[i].restoreLostContext(gl); - }; -} - -/** - * A WebGLBatch Enables a group of sprites to be drawn using the same settings. - * if a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch. - * All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites - * in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled - * automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster - * the webGL renderer will run. - * - * @class WebGLBatch - * @constructor - * @param gl {WebGLContext} an instance of the webGL context - */ -PIXI.WebGLBatch = function(gl) -{ - this.gl = gl; - - this.size = 0; - - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); - this.blendMode = PIXI.blendModes.NORMAL; - this.dynamicSize = 1; -} - -// constructor -PIXI.WebGLBatch.prototype.constructor = PIXI.WebGLBatch; - -/** - * Cleans the batch so that is can be returned to an object pool and reused - * - * @method clean - */ -PIXI.WebGLBatch.prototype.clean = function() -{ - this.verticies = []; - this.uvs = []; - this.indices = []; - this.colors = []; - this.dynamicSize = 1; - this.texture = null; - this.last = null; - this.size = 0; - this.head; - this.tail; -} - -/** - * Recreates the buffers in the event of a context loss - * - * @method restoreLostContext - * @param gl {WebGLContext} - */ -PIXI.WebGLBatch.prototype.restoreLostContext = function(gl) -{ - this.gl = gl; - this.vertexBuffer = gl.createBuffer(); - this.indexBuffer = gl.createBuffer(); - this.uvBuffer = gl.createBuffer(); - this.colorBuffer = gl.createBuffer(); -} - -/** - * inits the batch's texture and blend mode based if the supplied sprite - * - * @method init - * @param sprite {Sprite} the first sprite to be added to the batch. Only sprites with - * the same base texture and blend mode will be allowed to be added to this batch - */ -PIXI.WebGLBatch.prototype.init = function(sprite) -{ - sprite.batch = this; - this.dirty = true; - this.blendMode = sprite.blendMode; - this.texture = sprite.texture.baseTexture; - this.head = sprite; - this.tail = sprite; - this.size = 1; - - this.growBatch(); -} - -/** - * inserts a sprite before the specified sprite - * - * @method insertBefore - * @param sprite {Sprite} the sprite to be added - * @param nextSprite {nextSprite} the first sprite will be inserted before this sprite - */ -PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite) -{ - this.size++; - - sprite.batch = this; - this.dirty = true; - var tempPrev = nextSprite.__prev; - nextSprite.__prev = sprite; - sprite.__next = nextSprite; - - if(tempPrev) - { - sprite.__prev = tempPrev; - tempPrev.__next = sprite; - } - else - { - this.head = sprite; - } -} - -/** - * inserts a sprite after the specified sprite - * - * @method insertAfter - * @param sprite {Sprite} the sprite to be added - * @param previousSprite {Sprite} the first sprite will be inserted after this sprite - */ -PIXI.WebGLBatch.prototype.insertAfter = function(sprite, previousSprite) -{ - this.size++; - - sprite.batch = this; - this.dirty = true; - - var tempNext = previousSprite.__next; - previousSprite.__next = sprite; - sprite.__prev = previousSprite; - - if(tempNext) - { - sprite.__next = tempNext; - tempNext.__prev = sprite; - } - else - { - this.tail = sprite - } -} - -/** - * removes a sprite from the batch - * - * @method remove - * @param sprite {Sprite} the sprite to be removed - */ -PIXI.WebGLBatch.prototype.remove = function(sprite) -{ - this.size--; - - if(this.size == 0) - { - sprite.batch = null; - sprite.__prev = null; - sprite.__next = null; - return; - } - - if(sprite.__prev) - { - sprite.__prev.__next = sprite.__next; - } - else - { - this.head = sprite.__next; - this.head.__prev = null; - } - - if(sprite.__next) - { - sprite.__next.__prev = sprite.__prev; - } - else - { - this.tail = sprite.__prev; - this.tail.__next = null - } - - sprite.batch = null; - sprite.__next = null; - sprite.__prev = null; - this.dirty = true; -} - -/** - * Splits the batch into two with the specified sprite being the start of the new batch. - * - * @method split - * @param sprite {Sprite} the sprite that indicates where the batch should be split - * @return {WebGLBatch} the new batch - */ -PIXI.WebGLBatch.prototype.split = function(sprite) -{ - this.dirty = true; - - var batch = new PIXI.WebGLBatch(this.gl); - batch.init(sprite); - batch.texture = this.texture; - batch.tail = this.tail; - - this.tail = sprite.__prev; - this.tail.__next = null; - - sprite.__prev = null; - // return a splite batch! - - // TODO this size is wrong! - // need to recalculate :/ problem with a linked list! - // unless it gets calculated in the "clean"? - - // need to loop through items as there is no way to know the length on a linked list :/ - var tempSize = 0; - while(sprite) - { - tempSize++; - sprite.batch = batch; - sprite = sprite.__next; - } - - batch.size = tempSize; - this.size -= tempSize; - - return batch; -} - -/** - * Merges two batchs together - * - * @method merge - * @param batch {WebGLBatch} the batch that will be merged - */ -PIXI.WebGLBatch.prototype.merge = function(batch) -{ - this.dirty = true; - - this.tail.__next = batch.head; - batch.head.__prev = this.tail; - - this.size += batch.size; - - this.tail = batch.tail; - - var sprite = batch.head; - while(sprite) - { - sprite.batch = this; - sprite = sprite.__next; - } -} - -/** - * Grows the size of the batch. As the elements in the batch cannot have a dynamic size this - * function is used to increase the size of the batch. It also creates a little extra room so - * that the batch does not need to be resized every time a sprite is added - * - * @method growBatch - */ -PIXI.WebGLBatch.prototype.growBatch = function() -{ - var gl = this.gl; - if( this.size == 1) - { - this.dynamicSize = 1; - } - else - { - this.dynamicSize = this.size * 1.5 - } - // grow verts - this.verticies = new Float32Array(this.dynamicSize * 8); - - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW); - - this.uvs = new Float32Array( this.dynamicSize * 8 ); - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW); - - this.dirtyUVS = true; - - this.colors = new Float32Array( this.dynamicSize * 4 ); - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW); - - this.dirtyColors = true; - - this.indices = new Uint16Array(this.dynamicSize * 6); - var length = this.indices.length/6; - - for (var i=0; i < length; i++) - { - var index2 = i * 6; - var index3 = i * 4; - this.indices[index2 + 0] = index3 + 0; - this.indices[index2 + 1] = index3 + 1; - this.indices[index2 + 2] = index3 + 2; - this.indices[index2 + 3] = index3 + 0; - this.indices[index2 + 4] = index3 + 2; - this.indices[index2 + 5] = index3 + 3; - }; - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); -} - -/** - * Refresh's all the data in the batch and sync's it with the webGL buffers - * - * @method refresh - */ -PIXI.WebGLBatch.prototype.refresh = function() -{ - var gl = this.gl; - - if (this.dynamicSize < this.size) - { - this.growBatch(); - } - - var indexRun = 0; - var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index; - var a, b, c, d, tx, ty; - - var displayObject = this.head; - - while(displayObject) - { - index = indexRun * 8; - - var texture = displayObject.texture; - - var frame = texture.frame; - var tw = texture.baseTexture.width; - var th = texture.baseTexture.height; - - this.uvs[index + 0] = frame.x / tw; - this.uvs[index +1] = frame.y / th; - - this.uvs[index +2] = (frame.x + frame.width) / tw; - this.uvs[index +3] = frame.y / th; - - this.uvs[index +4] = (frame.x + frame.width) / tw; - this.uvs[index +5] = (frame.y + frame.height) / th; - - this.uvs[index +6] = frame.x / tw; - this.uvs[index +7] = (frame.y + frame.height) / th; - - displayObject.updateFrame = false; - - colorIndex = indexRun * 4; - this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; - - displayObject = displayObject.__next; - - indexRun ++; - } - - this.dirtyUVS = true; - this.dirtyColors = true; -} - -/** - * Updates all the relevant geometry and uploads the data to the GPU - * - * @method update - */ -PIXI.WebGLBatch.prototype.update = function() -{ - var gl = this.gl; - var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index, index2, index3 - - var a, b, c, d, tx, ty; - - var indexRun = 0; - - var displayObject = this.head; - - while(displayObject) - { - if(displayObject.vcount === PIXI.visibleCount) - { - width = displayObject.texture.frame.width; - height = displayObject.texture.frame.height; - - // TODO trim?? - aX = displayObject.anchor.x;// - displayObject.texture.trim.x - aY = displayObject.anchor.y; //- displayObject.texture.trim.y - w0 = width * (1-aX); - w1 = width * -aX; - - h0 = height * (1-aY); - h1 = height * -aY; - - index = indexRun * 8; - - worldTransform = displayObject.worldTransform; - - a = worldTransform[0]; - b = worldTransform[3]; - c = worldTransform[1]; - d = worldTransform[4]; - tx = worldTransform[2]; - ty = worldTransform[5]; - - this.verticies[index + 0 ] = a * w1 + c * h1 + tx; - this.verticies[index + 1 ] = d * h1 + b * w1 + ty; - - this.verticies[index + 2 ] = a * w0 + c * h1 + tx; - this.verticies[index + 3 ] = d * h1 + b * w0 + ty; - - this.verticies[index + 4 ] = a * w0 + c * h0 + tx; - this.verticies[index + 5 ] = d * h0 + b * w0 + ty; - - this.verticies[index + 6] = a * w1 + c * h0 + tx; - this.verticies[index + 7] = d * h0 + b * w1 + ty; - - if(displayObject.updateFrame || displayObject.texture.updateFrame) - { - this.dirtyUVS = true; - - var texture = displayObject.texture; - - var frame = texture.frame; - var tw = texture.baseTexture.width; - var th = texture.baseTexture.height; - - this.uvs[index + 0] = frame.x / tw; - this.uvs[index +1] = frame.y / th; - - this.uvs[index +2] = (frame.x + frame.width) / tw; - this.uvs[index +3] = frame.y / th; - - this.uvs[index +4] = (frame.x + frame.width) / tw; - this.uvs[index +5] = (frame.y + frame.height) / th; - - this.uvs[index +6] = frame.x / tw; - this.uvs[index +7] = (frame.y + frame.height) / th; - - displayObject.updateFrame = false; - } - - // TODO this probably could do with some optimisation.... - if(displayObject.cacheAlpha != displayObject.worldAlpha) - { - displayObject.cacheAlpha = displayObject.worldAlpha; - - var colorIndex = indexRun * 4; - this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha; - this.dirtyColors = true; - } - } - else - { - index = indexRun * 8; - - this.verticies[index + 0 ] = 0; - this.verticies[index + 1 ] = 0; - - this.verticies[index + 2 ] = 0; - this.verticies[index + 3 ] = 0; - - this.verticies[index + 4 ] = 0; - this.verticies[index + 5 ] = 0; - - this.verticies[index + 6] = 0; - this.verticies[index + 7] = 0; - } - - indexRun++; - displayObject = displayObject.__next; - } -} - -/** - * Draws the batch to the frame buffer - * - * @method render - */ -PIXI.WebGLBatch.prototype.render = function(start, end) -{ - start = start || 0; - - if(end == undefined)end = this.size; - - if(this.dirty) - { - this.refresh(); - this.dirty = false; - } - - if (this.size == 0)return; - - this.update(); - var gl = this.gl; - - //TODO optimize this! - - var shaderProgram = PIXI.currentShader; - - //gl.useProgram(shaderProgram); - - // update the verts.. - gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); - // ok.. - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - // update the uvs - var isDefault = (shaderProgram == PIXI.shaderProgram) - - gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); - - if(this.dirtyUVS) - { - this.dirtyUVS = false; - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvs); - } - - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this.texture._glTexture); - - // update color! - gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer); - - if(this.dirtyColors) - { - this.dirtyColors = false; - gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.colors); - } - - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); - - var len = end - start; - - // DRAW THAT this! - gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 ); -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * A WebGLBatch Enables a group of sprites to be drawn using the same settings. - * if a group of sprites all have the same baseTexture and blendMode then they can be - * grouped into a batch. All the sprites in a batch can then be drawn in one go by the - * GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch - * even if the batch only contains one sprite. Batching is handled automatically by the - * webGL renderer. A good tip is: the smaller the number of batchs there are, the faster - * the webGL renderer will run. - * - * @class WebGLBatch - * @contructor - * @param gl {WebGLContext} An instance of the webGL context - */ -PIXI.WebGLRenderGroup = function(gl) -{ - this.gl = gl; - this.root; - - this.backgroundColor; - this.batchs = []; - this.toRemove = []; -} - -// constructor -PIXI.WebGLRenderGroup.prototype.constructor = PIXI.WebGLRenderGroup; - -/** - * Add a display object to the webgl renderer - * - * @method setRenderable - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.setRenderable = function(displayObject) -{ - // has this changed?? - if(this.root)this.removeDisplayObjectAndChildren(this.root); - - displayObject.worldVisible = displayObject.visible; - - // soooooo // - // to check if any batchs exist already?? - - // TODO what if its already has an object? should remove it - this.root = displayObject; - this.addDisplayObjectAndChildren(displayObject); -} - -/** - * Renders the stage to its webgl view - * - * @method render - * @param projection {Object} - */ -PIXI.WebGLRenderGroup.prototype.render = function(projection) -{ - PIXI.WebGLRenderer.updateTextures(); - - var gl = this.gl; - - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - // will render all the elements in the group - var renderable; - for (var i=0; i < this.batchs.length; i++) - { - - renderable = this.batchs[i]; - if(renderable instanceof PIXI.WebGLBatch) - { - this.batchs[i].render(); - continue; - } - - // non sprite batch.. - var worldVisible = renderable.vcount === PIXI.visibleCount; - - if(renderable instanceof PIXI.TilingSprite) - { - if(worldVisible)this.renderTilingSprite(renderable, projection); - } - else if(renderable instanceof PIXI.Strip) - { - if(worldVisible)this.renderStrip(renderable, projection); - } - else if(renderable instanceof PIXI.Graphics) - { - if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix); - } - else if(renderable instanceof PIXI.FilterBlock) - { - this.handleFilterBlock(renderable, projection); - } - } - -} - -/** - * Renders a specific displayObject - * - * @method renderSpecific - * @param displayObject {DisplayObject} - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection) -{ - PIXI.WebGLRenderer.updateTextures(); - - var gl = this.gl; - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - - // to do! - // render part of the scene... - - var startIndex; - var startBatchIndex; - - var endIndex; - var endBatchIndex; - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.first; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - var startBatch = nextRenderable.batch; - - if(nextRenderable instanceof PIXI.Sprite) - { - startBatch = nextRenderable.batch; - - var head = startBatch.head; - var next = head; - - // ok now we have the batch.. need to find the start index! - if(head == nextRenderable) - { - startIndex = 0; - } - else - { - startIndex = 1; - - while(head.__next != nextRenderable) - { - startIndex++; - head = head.__next; - } - } - } - else - { - startBatch = nextRenderable; - } - - // Get the LAST renderable object - var lastRenderable = displayObject; - var endBatch; - var lastItem = displayObject; - while(lastItem.children.length > 0) - { - lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem.last; - } - - if(lastRenderable instanceof PIXI.Sprite) - { - endBatch = lastRenderable.batch; - - var head = endBatch.head; - - if(head == lastRenderable) - { - endIndex = 0; - } - else - { - endIndex = 1; - - while(head.__next != lastRenderable) - { - endIndex++; - head = head.__next; - } - } - } - else - { - endBatch = lastRenderable; - } - - // TODO - need to fold this up a bit! - - if(startBatch == endBatch) - { - if(startBatch instanceof PIXI.WebGLBatch) - { - startBatch.render(startIndex, endIndex+1); - } - else - { - this.renderSpecial(startBatch, projection); - } - return; - } - - // now we have first and last! - startBatchIndex = this.batchs.indexOf(startBatch); - endBatchIndex = this.batchs.indexOf(endBatch); - - // DO the first batch - if(startBatch instanceof PIXI.WebGLBatch) - { - startBatch.render(startIndex); - } - else - { - this.renderSpecial(startBatch, projection); - } - - // DO the middle batchs.. - for (var i=startBatchIndex+1; i < endBatchIndex; i++) - { - renderable = this.batchs[i]; - - if(renderable instanceof PIXI.WebGLBatch) - { - this.batchs[i].render(); - } - else - { - this.renderSpecial(renderable, projection); - } - } - - // DO the last batch.. - if(endBatch instanceof PIXI.WebGLBatch) - { - endBatch.render(0, endIndex+1); - } - else - { - this.renderSpecial(endBatch, projection); - } -} - -/** - * Renders a specific renderable - * - * @method renderSpecial - * @param renderable {DisplayObject} - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) -{ - var sta = PIXI.shaderStack.length; - - var worldVisible = renderable.vcount === PIXI.visibleCount - - if(renderable instanceof PIXI.TilingSprite) - { - if(worldVisible)this.renderTilingSprite(renderable, projection); - } - else if(renderable instanceof PIXI.Strip) - { - if(worldVisible)this.renderStrip(renderable, projection); - } - else if(renderable instanceof PIXI.CustomRenderable) - { - if(worldVisible) renderable.renderWebGL(this, projection); - } - else if(renderable instanceof PIXI.Graphics) - { - if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection); - } - else if(renderable instanceof PIXI.FilterBlock) - { - this.handleFilterBlock(renderable, projection); - } -} - -PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection) -{ - /* - * for now only masks are supported.. - */ - var gl = PIXI.gl; - - if(renderable.open) - { - if(renderable.data instanceof Array) - { - var filter = renderable.data[0]; - - if(!filter.shader) - { - var shader = new PIXI.PixiShader(); - - shader.fragmentSrc = filter.fragmentSrc; - shader.uniforms = filter.uniforms; - shader.init(); - - filter.shader = shader - } - - PIXI.activateShader(filter.shader); - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - } - else - { - gl.enable(gl.STENCIL_TEST); - - gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.ALWAYS,1,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE); - PIXI.WebGLGraphics.renderGraphics(renderable.data, projection); - - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL,0,0xff); - gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP); - } - } - else - { - if(renderable.data instanceof Array) - { - PIXI.popShader(); - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - } - else - { - gl.disable(gl.STENCIL_TEST); - } - } -} - -/** - * Updates a webgl texture - * - * @method updateTexture - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject) -{ - - // TODO definitely can optimse this function.. - - this.removeObject(displayObject); - - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - var previousRenderable = displayObject.first; - while(previousRenderable != this.root) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.last; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - - this.insertObject(displayObject, previousRenderable, nextRenderable); -} - -/** - * Adds filter blocks - * - * @method addFilterBlocks - * @param start {FilterBlock} - * @param end {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end) -{ - start.__renderGroup = this; - end.__renderGroup = this; - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - var previousRenderable = start; - while(previousRenderable != this.root.first) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - this.insertAfter(start, previousRenderable); - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var previousRenderable2 = end; - while(previousRenderable2 != this.root.first) - { - previousRenderable2 = previousRenderable2._iPrev; - if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break; - } - this.insertAfter(end, previousRenderable2); -} - -/** - * Remove filter blocks - * - * @method removeFilterBlocks - * @param start {FilterBlock} - * @param end {FilterBlock} - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeFilterBlocks = function(start, end) -{ - this.removeObject(start); - this.removeObject(end); -} - -/** - * Adds a display object and children to the webgl context - * - * @method addDisplayObjectAndChildren - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayObject) -{ - if(displayObject.__renderGroup)displayObject.__renderGroup.removeDisplayObjectAndChildren(displayObject); - - /* - * LOOK FOR THE PREVIOUS RENDERABLE - * This part looks for the closest previous sprite that can go into a batch - * It keeps going back until it finds a sprite or the stage - */ - - var previousRenderable = displayObject.first; - while(previousRenderable != this.root.first) - { - previousRenderable = previousRenderable._iPrev; - if(previousRenderable.renderable && previousRenderable.__renderGroup)break; - } - - /* - * LOOK FOR THE NEXT SPRITE - * This part looks for the closest next sprite that can go into a batch - * it keeps looking until it finds a sprite or gets to the end of the display - * scene graph - */ - var nextRenderable = displayObject.last; - while(nextRenderable._iNext) - { - nextRenderable = nextRenderable._iNext; - if(nextRenderable.renderable && nextRenderable.__renderGroup)break; - } - - // one the display object hits this. we can break the loop - - var tempObject = displayObject.first; - var testObject = displayObject.last._iNext; - do - { - tempObject.__renderGroup = this; - - if(tempObject.renderable) - { - - this.insertObject(tempObject, previousRenderable, nextRenderable); - previousRenderable = tempObject; - } - - tempObject = tempObject._iNext; - } - while(tempObject != testObject) -} - -/** - * Removes a display object and children to the webgl context - * - * @method removeDisplayObjectAndChildren - * @param displayObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren = function(displayObject) -{ - if(displayObject.__renderGroup != this)return; - -// var displayObject = displayObject.first; - var lastObject = displayObject.last; - do - { - displayObject.__renderGroup = null; - if(displayObject.renderable)this.removeObject(displayObject); - displayObject = displayObject._iNext; - } - while(displayObject) -} - -/** - * Inserts a displayObject into the linked list - * - * @method insertObject - * @param displayObject {DisplayObject} - * @param previousObject {DisplayObject} - * @param nextObject {DisplayObject} - * @private - */ -PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousObject, nextObject) -{ - // while looping below THE OBJECT MAY NOT HAVE BEEN ADDED - var previousSprite = previousObject; - var nextSprite = nextObject; - - /* - * so now we have the next renderable and the previous renderable - * - */ - if(displayObject instanceof PIXI.Sprite) - { - var previousBatch - var nextBatch - - if(previousSprite instanceof PIXI.Sprite) - { - previousBatch = previousSprite.batch; - if(previousBatch) - { - if(previousBatch.texture == displayObject.texture.baseTexture && previousBatch.blendMode == displayObject.blendMode) - { - previousBatch.insertAfter(displayObject, previousSprite); - return; - } - } - } - else - { - // TODO reword! - previousBatch = previousSprite; - } - - if(nextSprite) - { - if(nextSprite instanceof PIXI.Sprite) - { - nextBatch = nextSprite.batch; - - //batch may not exist if item was added to the display list but not to the webGL - if(nextBatch) - { - if(nextBatch.texture == displayObject.texture.baseTexture && nextBatch.blendMode == displayObject.blendMode) - { - nextBatch.insertBefore(displayObject, nextSprite); - return; - } - else - { - if(nextBatch == previousBatch) - { - // THERE IS A SPLIT IN THIS BATCH! // - var splitBatch = previousBatch.split(nextSprite); - // COOL! - // add it back into the array - /* - * OOPS! - * seems the new sprite is in the middle of a batch - * lets split it.. - */ - var batch = PIXI.WebGLRenderer.getBatch(); - - var index = this.batchs.indexOf( previousBatch ); - batch.init(displayObject); - this.batchs.splice(index+1, 0, batch, splitBatch); - - return; - } - } - } - } - else - { - // TODO re-word! - - nextBatch = nextSprite; - } - } - - /* - * looks like it does not belong to any batch! - * but is also not intersecting one.. - * time to create anew one! - */ - - var batch = PIXI.WebGLRenderer.getBatch(); - batch.init(displayObject); - - if(previousBatch) // if this is invalid it means - { - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, batch); - } - else - { - this.batchs.push(batch); - } - - return; - } - else if(displayObject instanceof PIXI.TilingSprite) - { - - // add to a batch!! - this.initTilingSprite(displayObject); - // this.batchs.push(displayObject); - - } - else if(displayObject instanceof PIXI.Strip) - { - // add to a batch!! - this.initStrip(displayObject); - // this.batchs.push(displayObject); - } - else if(displayObject)// instanceof PIXI.Graphics) - { - //displayObject.initWebGL(this); - - // add to a batch!! - //this.initStrip(displayObject); - //this.batchs.push(displayObject); - } - - this.insertAfter(displayObject, previousSprite); - - // insert and SPLIT! - -} - -/** - * Inserts a displayObject into the linked list - * - * @method insertAfter - * @param item {DisplayObject} - * @param displayObject {DisplayObject} The object to insert - * @private - */ -PIXI.WebGLRenderGroup.prototype.insertAfter = function(item, displayObject) -{ - if(displayObject instanceof PIXI.Sprite) - { - var previousBatch = displayObject.batch; - - if(previousBatch) - { - // so this object is in a batch! - - // is it not? need to split the batch - if(previousBatch.tail == displayObject) - { - // is it tail? insert in to batchs - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, item); - } - else - { - // TODO MODIFY ADD / REMOVE CHILD TO ACCOUNT FOR FILTERS (also get prev and next) // - - // THERE IS A SPLIT IN THIS BATCH! // - var splitBatch = previousBatch.split(displayObject.__next); - - // COOL! - // add it back into the array - /* - * OOPS! - * seems the new sprite is in the middle of a batch - * lets split it.. - */ - var index = this.batchs.indexOf( previousBatch ); - this.batchs.splice(index+1, 0, item, splitBatch); - } - } - else - { - this.batchs.push(item); - } - } - else - { - var index = this.batchs.indexOf( displayObject ); - this.batchs.splice(index+1, 0, item); - } -} - -/** - * Removes a displayObject from the linked list - * - * @method removeObject - * @param displayObject {DisplayObject} The object to remove - * @private - */ -PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject) -{ - // loop through children.. - // display object // - - // add a child from the render group.. - // remove it and all its children! - //displayObject.cacheVisible = false;//displayObject.visible; - - /* - * removing is a lot quicker.. - * - */ - var batchToRemove; - - if(displayObject instanceof PIXI.Sprite) - { - // should always have a batch! - var batch = displayObject.batch; - if(!batch)return; // this means the display list has been altered befre rendering - - batch.remove(displayObject); - - if(batch.size==0) - { - batchToRemove = batch; - } - } - else - { - batchToRemove = displayObject; - } - - /* - * Looks like there is somthing that needs removing! - */ - if(batchToRemove) - { - var index = this.batchs.indexOf( batchToRemove ); - if(index == -1)return;// this means it was added then removed before rendered - - // ok so.. check to see if you adjacent batchs should be joined. - // TODO may optimise? - if(index == 0 || index == this.batchs.length-1) - { - // wha - eva! just get of the empty batch! - this.batchs.splice(index, 1); - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - - return; - } - - if(this.batchs[index-1] instanceof PIXI.WebGLBatch && this.batchs[index+1] instanceof PIXI.WebGLBatch) - { - if(this.batchs[index-1].texture == this.batchs[index+1].texture && this.batchs[index-1].blendMode == this.batchs[index+1].blendMode) - { - //console.log("MERGE") - this.batchs[index-1].merge(this.batchs[index+1]); - - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - PIXI.WebGLRenderer.returnBatch(this.batchs[index+1]); - this.batchs.splice(index, 2); - return; - } - } - - this.batchs.splice(index, 1); - if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove); - } -} - - -/** - * Initializes a tiling sprite - * - * @method initTilingSprite - * @param sprite {TilingSprite} The tiling sprite to initialize - * @private - */ -PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) -{ - var gl = this.gl; - - // make the texture tilable.. - - sprite.verticies = new Float32Array([0, 0, - sprite.width, 0, - sprite.width, sprite.height, - 0, sprite.height]); - - sprite.uvs = new Float32Array([0, 0, - 1, 0, - 1, 1, - 0, 1]); - - sprite.colors = new Float32Array([1,1,1,1]); - - sprite.indices = new Uint16Array([0, 1, 3,2])//, 2]); - - sprite._vertexBuffer = gl.createBuffer(); - sprite._indexBuffer = gl.createBuffer(); - sprite._uvBuffer = gl.createBuffer(); - sprite._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.verticies, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.uvs, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, sprite.colors, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sprite._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sprite.indices, gl.STATIC_DRAW); - -// return ( (x > 0) && ((x & (x - 1)) == 0) ); - - if(sprite.texture.baseTexture._glTexture) - { - gl.bindTexture(gl.TEXTURE_2D, sprite.texture.baseTexture._glTexture); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - sprite.texture.baseTexture._powerOf2 = true; - } - else - { - sprite.texture.baseTexture._powerOf2 = true; - } -} - -/** - * Renders a Strip - * - * @method renderStrip - * @param strip {Strip} The strip to render - * @param projection {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) -{ - var gl = this.gl; - var shaderProgram = PIXI.stripShaderProgram; - - - gl.useProgram(shaderProgram); - - var m = PIXI.mat3.clone(strip.worldTransform); - - PIXI.mat3.transpose(m); - - // set the matrix transform for the - gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); - gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); - -/* - if(strip.blendMode == PIXI.blendModes.NORMAL) - { - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - } - else - { - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR); - } - */ - - - if(!strip.dirty) - { - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, strip.verticies) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - } - else - { - strip.dirty = false; - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); - - // update the uvs - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); - - // dont need to upload! - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); - - } - - gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - - gl.useProgram(PIXI.currentProgram); -} - -/** - * Renders a TilingSprite - * - * @method renderTilingSprite - * @param sprite {TilingSprite} The tiling sprite to render - * @param projectionMatrix {Object} - * @private - */ -PIXI.WebGLRenderGroup.prototype.renderTilingSprite = function(sprite, projectionMatrix) -{ - var gl = this.gl; - var shaderProgram = PIXI.shaderProgram; - - var tilePosition = sprite.tilePosition; - var tileScale = sprite.tileScale; - - var offsetX = tilePosition.x/sprite.texture.baseTexture.width; - var offsetY = tilePosition.y/sprite.texture.baseTexture.height; - - var scaleX = (sprite.width / sprite.texture.baseTexture.width) / tileScale.x; - var scaleY = (sprite.height / sprite.texture.baseTexture.height) / tileScale.y; - - sprite.uvs[0] = 0 - offsetX; - sprite.uvs[1] = 0 - offsetY; - - sprite.uvs[2] = (1 * scaleX) -offsetX; - sprite.uvs[3] = 0 - offsetY; - - sprite.uvs[4] = (1 *scaleX) - offsetX; - sprite.uvs[5] = (1 *scaleY) - offsetY; - - sprite.uvs[6] = 0 - offsetX; - sprite.uvs[7] = (1 *scaleY) - offsetY; - - gl.bindBuffer(gl.ARRAY_BUFFER, sprite._uvBuffer); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, sprite.uvs) - - this.renderStrip(sprite, projectionMatrix); -} - -/** - * Initializes a strip to be rendered - * - * @method initStrip - * @param strip {Strip} The strip to initialize - * @private - */ -PIXI.WebGLRenderGroup.prototype.initStrip = function(strip) -{ - // build the strip! - var gl = this.gl; - var shaderProgram = this.shaderProgram; - - strip._vertexBuffer = gl.createBuffer(); - strip._indexBuffer = gl.createBuffer(); - strip._uvBuffer = gl.createBuffer(); - strip._colorBuffer = gl.createBuffer(); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.DYNAMIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW); - - gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW); - - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW); -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * the CanvasRenderer draws the stage and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. - * Dont forget to add the view to your DOM or you will not see anything :) - * - * @class CanvasRenderer - * @constructor - * @param width=0 {Number} the width of the canvas view - * @param height=0 {Number} the height of the canvas view - * @param view {Canvas} the canvas to use as a view, optional - * @param transparent=false {Boolean} the transparency of the render view, default false - */ -PIXI.CanvasRenderer = function(width, height, view, transparent) -{ - this.transparent = transparent; - - /** - * The width of the canvas view - * - * @property width - * @type Number - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @property height - * @type Number - * @default 600 - */ - this.height = height || 600; - - /** - * The canvas element that the everything is drawn to - * - * @property view - * @type Canvas - */ - this.view = view || document.createElement( 'canvas' ); - - /** - * The canvas context that the everything is drawn to - * @property context - * @type Canvas 2d Context - */ - this.context = this.view.getContext("2d"); - - this.refresh = true; - // hack to enable some hardware acceleration! - //this.view.style["transform"] = "translatez(0)"; - - this.view.width = this.width; - this.view.height = this.height; - this.count = 0; -} - -// constructor -PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer; - -/** - * Renders the stage to its canvas view - * - * @method render - * @param stage {Stage} the Stage element to be rendered - */ -PIXI.CanvasRenderer.prototype.render = function(stage) -{ - - //stage.__childrenAdded = []; - //stage.__childrenRemoved = []; - - // update textures if need be - PIXI.texturesToUpdate = []; - PIXI.texturesToDestroy = []; - - PIXI.visibleCount++; - stage.updateTransform(); - - // update the background color - if(this.view.style.backgroundColor!=stage.backgroundColorString && !this.transparent)this.view.style.backgroundColor = stage.backgroundColorString; - - this.context.setTransform(1,0,0,1,0,0); - this.context.clearRect(0, 0, this.width, this.height) - this.renderDisplayObject(stage); - //as - - // run interaction! - if(stage.interactive) - { - //need to add some events! - if(!stage._interactiveEventsAdded) - { - stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); - } - } - - // remove frame updates.. - if(PIXI.Texture.frameUpdates.length > 0) - { - PIXI.Texture.frameUpdates = []; - } - - -} - -/** - * resizes the canvas view to the specified width and height - * - * @method resize - * @param width {Number} the new width of the canvas view - * @param height {Number} the new height of the canvas view - */ -PIXI.CanvasRenderer.prototype.resize = function(width, height) -{ - this.width = width; - this.height = height; - - this.view.width = width; - this.view.height = height; -} - -/** - * Renders a display object - * - * @method renderDisplayObject - * @param displayObject {DisplayObject} The displayObject to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject) -{ - // no loger recurrsive! - var transform; - var context = this.context; - - context.globalCompositeOperation = 'source-over'; - - // one the display object hits this. we can break the loop - var testObject = displayObject.last._iNext; - displayObject = displayObject.first; - - do - { - transform = displayObject.worldTransform; - - if(!displayObject.visible) - { - displayObject = displayObject.last._iNext; - continue; - } - - if(!displayObject.renderable) - { - displayObject = displayObject._iNext; - continue; - } - - if(displayObject instanceof PIXI.Sprite) - { - - var frame = displayObject.texture.frame; - - if(frame && frame.width && frame.height) - { - context.globalAlpha = displayObject.worldAlpha; - - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); - - context.drawImage(displayObject.texture.baseTexture.source, - frame.x, - frame.y, - frame.width, - frame.height, - (displayObject.anchor.x) * -frame.width, - (displayObject.anchor.y) * -frame.height, - frame.width, - frame.height); - } - } - else if(displayObject instanceof PIXI.Strip) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - this.renderStrip(displayObject); - } - else if(displayObject instanceof PIXI.TilingSprite) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - this.renderTilingSprite(displayObject); - } - else if(displayObject instanceof PIXI.CustomRenderable) - { - displayObject.renderCanvas(this); - } - else if(displayObject instanceof PIXI.Graphics) - { - context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]) - PIXI.CanvasGraphics.renderGraphics(displayObject, context); - } - else if(displayObject instanceof PIXI.FilterBlock) - { - if(PIXI.FilterBlock.data instanceof PIXI.Graphics) - { - if(displayObject.open) - { - context.save(); - - var cacheAlpha = displayObject.mask.alpha; - var maskTransform = displayObject.mask.worldTransform; - - context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5]) - - displayObject.mask.worldAlpha = 0.5; - - context.worldAlpha = 0; - - PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context); - context.clip(); - - displayObject.mask.worldAlpha = cacheAlpha; - } - else - { - context.restore(); - } - } - else - { - // only masks supported right now! - } - } - // count++ - displayObject = displayObject._iNext; - - - } - while(displayObject != testObject) - - -} - -/** - * Renders a flat strip - * - * @method renderStripFlat - * @param strip {Strip} The Strip to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip) -{ - var context = this.context; - var verticies = strip.verticies; - var uvs = strip.uvs; - - var length = verticies.length/2; - this.count++; - - context.beginPath(); - for (var i=1; i < length-2; i++) - { - - // draw some triangles! - var index = i*2; - - var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; - var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - - }; - - context.fillStyle = "#FF0000"; - context.fill(); - context.closePath(); -} - -/** - * Renders a tiling sprite - * - * @method renderTilingSprite - * @param sprite {TilingSprite} The tilingsprite to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite) -{ - var context = this.context; - - context.globalAlpha = sprite.worldAlpha; - - if(!sprite.__tilePattern) sprite.__tilePattern = context.createPattern(sprite.texture.baseTexture.source, "repeat"); - - context.beginPath(); - - var tilePosition = sprite.tilePosition; - var tileScale = sprite.tileScale; - - // offset - context.scale(tileScale.x,tileScale.y); - context.translate(tilePosition.x, tilePosition.y); - - context.fillStyle = sprite.__tilePattern; - context.fillRect(-tilePosition.x,-tilePosition.y,sprite.width / tileScale.x, sprite.height / tileScale.y); - - context.scale(1/tileScale.x, 1/tileScale.y); - context.translate(-tilePosition.x, -tilePosition.y); - - context.closePath(); -} - -/** - * Renders a strip - * - * @method renderStrip - * @param strip {Strip} The Strip to render - * @private - */ -PIXI.CanvasRenderer.prototype.renderStrip = function(strip) -{ - var context = this.context; - - // draw triangles!! - var verticies = strip.verticies; - var uvs = strip.uvs; - - var length = verticies.length/2; - this.count++; - for (var i=1; i < length-2; i++) - { - - // draw some triangles! - var index = i*2; - - var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; - var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - - var u0 = uvs[index] * strip.texture.width, u1 = uvs[index+2] * strip.texture.width, u2 = uvs[index+4]* strip.texture.width; - var v0 = uvs[index+1]* strip.texture.height, v1 = uvs[index+3] * strip.texture.height, v2 = uvs[index+5]* strip.texture.height; - - - 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 delta_a = x0*v1 + v0*x2 + x1*v2 - v1*x2 - v0*x1 - x0*v2; - var delta_b = u0*x1 + x0*u2 + u1*x2 - x1*u2 - x0*u1 - u0*x2; - var delta_c = u0*v1*x2 + v0*x1*u2 + x0*u1*v2 - x0*v1*u2 - v0*u1*x2 - u0*x1*v2; - var delta_d = y0*v1 + v0*y2 + y1*v2 - v1*y2 - v0*y1 - y0*v2; - var delta_e = u0*y1 + y0*u2 + u1*y2 - y1*u2 - y0*u1 - u0*y2; - var delta_f = u0*v1*y2 + v0*y1*u2 + y0*u1*v2 - y0*v1*u2 - v0*u1*y2 - u0*y1*v2; - - - - - context.transform(delta_a/delta, delta_d/delta, - delta_b/delta, delta_e/delta, - delta_c/delta, delta_f/delta); - - context.drawImage(strip.texture.baseTexture.source, 0, 0); - context.restore(); - }; - -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * A set of functions used by the canvas renderer to draw the primitive graphics data - * - * @class CanvasGraphics - */ -PIXI.CanvasGraphics = function() -{ - -} - - -/* - * Renders the graphics object - * - * @static - * @private - * @method renderGraphics - * @param graphics {Graphics} - * @param context {Context2D} - */ -PIXI.CanvasGraphics.renderGraphics = function(graphics, context) -{ - var worldAlpha = graphics.worldAlpha; - - for (var i=0; i < graphics.graphicsData.length; i++) - { - var data = graphics.graphicsData[i]; - var points = data.points; - - context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6); - - context.lineWidth = data.lineWidth; - - if(data.type == PIXI.Graphics.POLY) - { - context.beginPath(); - - context.moveTo(points[0], points[1]); - - for (var j=1; j < points.length/2; j++) - { - context.lineTo(points[j * 2], points[j * 2 + 1]); - } - - // if the first and last point are the same close the path - much neater :) - if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) - { - context.closePath(); - } - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - else if(data.type == PIXI.Graphics.RECT) - { - - if(data.fillColor || data.fillColor === 0) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fillRect(points[0], points[1], points[2], points[3]); - - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.strokeRect(points[0], points[1], points[2], points[3]); - } - - } - else if(data.type == PIXI.Graphics.CIRC) - { - // TODO - need to be Undefined! - context.beginPath(); - context.arc(points[0], points[1], points[2],0,2*Math.PI); - context.closePath(); - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - else if(data.type == PIXI.Graphics.ELIP) - { - - // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - - var elipseData = data.points; - - var w = elipseData[2] * 2; - var h = elipseData[3] * 2; - - var x = elipseData[0] - w/2; - var y = elipseData[1] - h/2; - - context.beginPath(); - - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - - context.moveTo(x, ym); - context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - - context.closePath(); - - if(data.fill) - { - context.globalAlpha = data.fillAlpha * worldAlpha; - context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6); - context.fill(); - } - if(data.lineWidth) - { - context.globalAlpha = data.lineAlpha * worldAlpha; - context.stroke(); - } - } - - }; -} - -/* - * Renders a graphics mask - * - * @static - * @private - * @method renderGraphicsMask - * @param graphics {Graphics} - * @param context {Context2D} - */ -PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context) -{ - var worldAlpha = graphics.worldAlpha; - - var len = graphics.graphicsData.length; - if(len > 1) - { - len = 1; - console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object") - } - - for (var i=0; i < 1; i++) - { - var data = graphics.graphicsData[i]; - var points = data.points; - - if(data.type == PIXI.Graphics.POLY) - { - context.beginPath(); - context.moveTo(points[0], points[1]); - - for (var j=1; j < points.length/2; j++) - { - context.lineTo(points[j * 2], points[j * 2 + 1]); - } - - // if the first and last point are the same close the path - much neater :) - if(points[0] == points[points.length-2] && points[1] == points[points.length-1]) - { - context.closePath(); - } - - } - else if(data.type == PIXI.Graphics.RECT) - { - context.beginPath(); - context.rect(points[0], points[1], points[2], points[3]); - context.closePath(); - } - else if(data.type == PIXI.Graphics.CIRC) - { - // TODO - need to be Undefined! - context.beginPath(); - context.arc(points[0], points[1], points[2],0,2*Math.PI); - context.closePath(); - } - else if(data.type == PIXI.Graphics.ELIP) - { - - // elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas - var elipseData = data.points; - - var w = elipseData[2] * 2; - var h = elipseData[3] * 2; - - var x = elipseData[0] - w/2; - var y = elipseData[1] - h/2; - - context.beginPath(); - - var kappa = .5522848, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - - context.moveTo(x, ym); - context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - context.closePath(); - } - - - }; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. - * It is important to know that with the webGL renderer only simple polys can be filled at this stage - * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png - * - * @class Graphics - * @extends DisplayObjectContainer - * @constructor - */ -PIXI.Graphics = function() -{ - PIXI.DisplayObjectContainer.call( this ); - - this.renderable = true; - - /** - * The alpha of the fill of this graphics object - * - * @property fillAlpha - * @type Number - */ - this.fillAlpha = 1; - - /** - * The width of any lines drawn - * - * @property lineWidth - * @type Number - */ - this.lineWidth = 0; - - /** - * The color of any lines drawn - * - * @property lineColor - * @type String - */ - this.lineColor = "black"; - - /** - * Graphics data - * - * @property graphicsData - * @type Array - * @private - */ - this.graphicsData = []; - - /** - * Current path - * - * @property currentPath - * @type Object - * @private - */ - this.currentPath = {points:[]}; -} - -// constructor -PIXI.Graphics.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Graphics.prototype.constructor = PIXI.Graphics; - -/** - * Specifies a line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method. - * - * @method lineStyle - * @param lineWidth {Number} width of the line to draw, will update the object's stored style - * @param color {Number} color of the line to draw, will update the object's stored style - * @param alpha {Number} alpha of the line to draw, will update the object's stored style - */ -PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.lineWidth = lineWidth || 0; - this.lineColor = color || 0; - this.lineAlpha = (alpha == undefined) ? 1 : alpha; - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - - this.graphicsData.push(this.currentPath); -} - -/** - * Moves the current drawing position to (x, y). - * - * @method moveTo - * @param x {Number} the X coord to move to - * @param y {Number} the Y coord to move to - */ -PIXI.Graphics.prototype.moveTo = function(x, y) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY}; - - this.currentPath.points.push(x, y); - - this.graphicsData.push(this.currentPath); -} - -/** - * Draws a line using the current line style from the current drawing position to (x, y); - * the current drawing position is then set to (x, y). - * - * @method lineTo - * @param x {Number} the X coord to draw to - * @param y {Number} the Y coord to draw to - */ -PIXI.Graphics.prototype.lineTo = function(x, y) -{ - this.currentPath.points.push(x, y); - this.dirty = true; -} - -/** - * Specifies a simple one-color fill that subsequent calls to other Graphics methods - * (such as lineTo() or drawCircle()) use when drawing. - * - * @method beginFill - * @param color {uint} the color of the fill - * @param alpha {Number} the alpha - */ -PIXI.Graphics.prototype.beginFill = function(color, alpha) -{ - this.filling = true; - this.fillColor = color || 0; - this.fillAlpha = (alpha == undefined) ? 1 : alpha; -} - -/** - * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. - * - * @method endFill - */ -PIXI.Graphics.prototype.endFill = function() -{ - this.filling = false; - this.fillColor = null; - this.fillAlpha = 1; -} - -/** - * @method drawRect - * - * @param x {Number} The X coord of the top-left of the rectangle - * @param y {Number} The Y coord of the top-left of the rectangle - * @param width {Number} The width of the rectangle - * @param height {Number} The height of the rectangle - */ -PIXI.Graphics.prototype.drawRect = function( x, y, width, height ) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, width, height], type:PIXI.Graphics.RECT}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Draws a circle. - * - * @method drawCircle - * @param x {Number} The X coord of the center of the circle - * @param y {Number} The Y coord of the center of the circle - * @param radius {Number} The radius of the circle - */ -PIXI.Graphics.prototype.drawCircle = function( x, y, radius) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, radius, radius], type:PIXI.Graphics.CIRC}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Draws an elipse. - * - * @method drawElipse - * @param x {Number} - * @param y {Number} - * @param width {Number} - * @param height {Number} - */ -PIXI.Graphics.prototype.drawElipse = function( x, y, width, height) -{ - if(this.currentPath.points.length == 0)this.graphicsData.pop(); - - this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, - fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, - points:[x, y, width, height], type:PIXI.Graphics.ELIP}; - - this.graphicsData.push(this.currentPath); - this.dirty = true; -} - -/** - * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @method clear - */ -PIXI.Graphics.prototype.clear = function() -{ - this.lineWidth = 0; - this.filling = false; - - this.dirty = true; - this.clearDirty = true; - this.graphicsData = []; -} - -// SOME TYPES: -PIXI.Graphics.POLY = 0; -PIXI.Graphics.RECT = 1; -PIXI.Graphics.CIRC = 2; -PIXI.Graphics.ELIP = 3; - -/** - * @author Mat Groves http://matgroves.com/ - */ - -PIXI.Strip = function(texture, width, height) -{ - PIXI.DisplayObjectContainer.call( this ); - this.texture = texture; - this.blendMode = PIXI.blendModes.NORMAL; - - try - { - this.uvs = new Float32Array([0, 1, - 1, 1, - 1, 0, 0,1]); - - this.verticies = new Float32Array([0, 0, - 0,0, - 0,0, 0, - 0, 0]); - - this.colors = new Float32Array([1, 1, 1, 1]); - - this.indices = new Uint16Array([0, 1, 2, 3]); - } - catch(error) - { - this.uvs = [0, 1, - 1, 1, - 1, 0, 0,1]; - - this.verticies = [0, 0, - 0,0, - 0,0, 0, - 0, 0]; - - this.colors = [1, 1, 1, 1]; - - this.indices = [0, 1, 2, 3]; - } - - - /* - this.uvs = new Float32Array() - this.verticies = new Float32Array() - this.colors = new Float32Array() - this.indices = new Uint16Array() -*/ - this.width = width; - this.height = height; - - // load the texture! - if(texture.baseTexture.hasLoaded) - { - this.width = this.texture.frame.width; - this.height = this.texture.frame.height; - this.updateFrame = true; - } - else - { - this.onTextureUpdateBind = this.onTextureUpdate.bind(this); - this.texture.addEventListener( 'update', this.onTextureUpdateBind ); - } - - this.renderable = true; -} - -// constructor -PIXI.Strip.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.Strip.prototype.constructor = PIXI.Strip; - -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; -} - -PIXI.Strip.prototype.onTextureUpdate = function(event) -{ - this.updateFrame = true; -} -// some helper functions.. - - -/** - * @author Mat Groves http://matgroves.com/ - */ - - -PIXI.Rope = function(texture, points) -{ - PIXI.Strip.call( this, texture ); - this.points = points; - - try - { - this.verticies = new Float32Array( points.length * 4); - this.uvs = new Float32Array( points.length * 4); - this.colors = new Float32Array( points.length * 2); - this.indices = new Uint16Array( points.length * 2); - } - catch(error) - { - this.verticies = verticies - - this.uvs = uvs - this.colors = colors - this.indices = indices - } - - this.refresh(); -} - - -// constructor -PIXI.Rope.prototype = Object.create( PIXI.Strip.prototype ); -PIXI.Rope.prototype.constructor = PIXI.Rope; - -PIXI.Rope.prototype.refresh = function() -{ - var points = this.points; - if(points.length < 1)return; - - var uvs = this.uvs - var indices = this.indices; - var colors = this.colors; - - var lastPoint = points[0]; - var nextPoint; - var perp = {x:0, y:0}; - var point = points[0]; - - this.count-=0.2; - - - uvs[0] = 0 - uvs[1] = 1 - uvs[2] = 0 - uvs[3] = 1 - - colors[0] = 1; - colors[1] = 1; - - indices[0] = 0; - indices[1] = 1; - - var total = points.length; - - for (var i = 1; i < total; i++) - { - - var point = points[i]; - var index = i * 4; - // time to do some smart drawing! - var 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; - } -} - -PIXI.Rope.prototype.updateTransform = function() -{ - - var points = this.points; - if(points.length < 1)return; - - var verticies = this.verticies - - var lastPoint = points[0]; - var nextPoint; - var perp = {x:0, y:0}; - var point = points[0]; - - this.count-=0.2; - - verticies[0] = point.x + perp.x - verticies[1] = point.y + perp.y //+ 200 - verticies[2] = point.x - perp.x - verticies[3] = point.y - perp.y//+200 - // time to do some smart drawing! - - var total = points.length; - - for (var i = 1; i < total; i++) - { - - var point = points[i]; - var 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; - - var ratio = (1 - (i / (total-1))) * 10; - if(ratio > 1)ratio = 1; - - var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y); - var 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; - - verticies[index] = point.x + perp.x - verticies[index+1] = point.y + perp.y - verticies[index+2] = point.x - perp.x - verticies[index+3] = point.y - perp.y - - lastPoint = point; - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call( this ); -} - -PIXI.Rope.prototype.setTexture = function(texture) -{ - // stop current texture - this.texture = texture; - this.updateFrame = true; -} - - - - - -/** - * @author Mat Groves http://matgroves.com/ - */ - -/** - * A tiling sprite is a fast way of rendering a tiling image - * - * @class TilingSprite - * @extends DisplayObjectContainer - * @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.DisplayObjectContainer.call( this ); - - /** - * The texture that the sprite is using - * - * @property texture - * @type Texture - */ - this.texture = texture; - - /** - * The width of the tiling sprite - * - * @property width - * @type Number - */ - this.width = width; - - /** - * The height of the tiling sprite - * - * @property height - * @type Number - */ - this.height = height; - - /** - * The scaling of the image that is being tiled - * - * @property tileScale - * @type Point - */ - this.tileScale = 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); - - this.renderable = true; - - this.blendMode = PIXI.blendModes.NORMAL -} - -// constructor -PIXI.TilingSprite.prototype = Object.create( PIXI.DisplayObjectContainer.prototype ); -PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite; - -/** - * Sets the texture of the tiling sprite - * - * @method setTexture - * @param texture {Texture} The PIXI texture that is displayed by the sprite - */ -PIXI.TilingSprite.prototype.setTexture = function(texture) -{ - //TODO SET THE TEXTURES - //TODO VISIBILITY - - // stop current texture - this.texture = texture; - this.updateFrame = true; -} - -/** - * When the texture is updated, this event will fire to update the frame - * - * @method onTextureUpdate - * @param event - * @private - */ -PIXI.TilingSprite.prototype.onTextureUpdate = function(event) -{ - this.updateFrame = true; -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi - * - * Awesome JS run time provided by EsotericSoftware - * https://github.com/EsotericSoftware/spine-runtimes - * - */ - -/** - * 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)) { - continue; - } - var spriteName = attachment.rendererObject.name; - var sprite = this.createSprite(slot, attachment.rendererObject); - slot.currentSprite = sprite; - slot.currentSpriteName = spriteName; - slotContainer.addChild(sprite); - } -}; - -PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype); -PIXI.Spine.prototype.constructor = PIXI.Spine; - -/* - * Updates the object transform for rendering - * - * @method updateTransform - * @private - */ -PIXI.Spine.prototype.updateTransform = function () { - this.lastTime = this.lastTime || Date.now(); - var timeDelta = (Date.now() - this.lastTime) * 0.001; - this.lastTime = Date.now(); - this.state.update(timeDelta); - 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 instanceof spine.RegionAttachment)) { - slotContainer.visible = false; - continue; - } - - 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.rendererObject); - slotContainer.addChild(sprite); - } - slot.currentSprite = slot.sprites[spriteName]; - slot.currentSpriteName = spriteName; - } - } - slotContainer.visible = true; - - 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 * Math.PI / 180); - } - - PIXI.DisplayObjectContainer.prototype.updateTransform.call(this); -}; - - -PIXI.Spine.prototype.createSprite = function (slot, descriptor) { - var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png"; - var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name)); - sprite.scale = descriptor.scale; - sprite.rotation = descriptor.rotation; - sprite.anchor.x = sprite.anchor.y = 0.5; - - slot.sprites = slot.sprites || {}; - slot.sprites[descriptor.name] = sprite; - return sprite; -}; - -/* - * Awesome JS run time provided by EsotericSoftware - * - * https://github.com/EsotericSoftware/spine-runtimes - * - */ - -var spine = {}; - -spine.BoneData = function (name, parent) { - this.name = name; - this.parent = parent; -}; -spine.BoneData.prototype = { - length: 0, - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1 -}; - -spine.SlotData = function (name, boneData) { - this.name = name; - this.boneData = boneData; -}; -spine.SlotData.prototype = { - r: 1, g: 1, b: 1, a: 1, - attachmentName: null -}; - -spine.Bone = function (boneData, parent) { - this.data = boneData; - this.parent = parent; - this.setToSetupPose(); -}; -spine.Bone.yDown = false; -spine.Bone.prototype = { - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1, - m00: 0, m01: 0, worldX: 0, // a b x - m10: 0, m11: 0, worldY: 0, // c d y - worldRotation: 0, - worldScaleX: 1, worldScaleY: 1, - updateWorldTransform: function (flipX, flipY) { - var parent = this.parent; - if (parent != null) { - this.worldX = this.x * parent.m00 + this.y * parent.m01 + parent.worldX; - this.worldY = this.x * parent.m10 + this.y * parent.m11 + parent.worldY; - this.worldScaleX = parent.worldScaleX * this.scaleX; - this.worldScaleY = parent.worldScaleY * this.scaleY; - this.worldRotation = parent.worldRotation + this.rotation; - } else { - this.worldX = this.x; - this.worldY = this.y; - this.worldScaleX = this.scaleX; - this.worldScaleY = this.scaleY; - this.worldRotation = this.rotation; - } - var radians = this.worldRotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - this.m00 = cos * this.worldScaleX; - this.m10 = sin * this.worldScaleX; - this.m01 = -sin * this.worldScaleY; - this.m11 = cos * this.worldScaleY; - if (flipX) { - this.m00 = -this.m00; - this.m01 = -this.m01; - } - if (flipY) { - this.m10 = -this.m10; - this.m11 = -this.m11; - } - if (spine.Bone.yDown) { - this.m10 = -this.m10; - this.m11 = -this.m11; - } - }, - setToSetupPose: function () { - var data = this.data; - this.x = data.x; - this.y = data.y; - this.rotation = data.rotation; - this.scaleX = data.scaleX; - this.scaleY = data.scaleY; - } -}; - -spine.Slot = function (slotData, skeleton, bone) { - this.data = slotData; - this.skeleton = skeleton; - this.bone = bone; - this.setToSetupPose(); -}; -spine.Slot.prototype = { - r: 1, g: 1, b: 1, a: 1, - _attachmentTime: 0, - attachment: null, - setAttachment: function (attachment) { - this.attachment = attachment; - this._attachmentTime = this.skeleton.time; - }, - setAttachmentTime: function (time) { - this._attachmentTime = this.skeleton.time - time; - }, - getAttachmentTime: function () { - return this.skeleton.time - this._attachmentTime; - }, - setToSetupPose: function () { - var data = this.data; - this.r = data.r; - this.g = data.g; - this.b = data.b; - this.a = data.a; - - var slotDatas = this.skeleton.data.slots; - for (var i = 0, n = slotDatas.length; i < n; i++) { - if (slotDatas[i] == data) { - this.setAttachment(!data.attachmentName ? null : this.skeleton.getAttachmentBySlotIndex(i, data.attachmentName)); - break; - } - } - } -}; - -spine.Skin = function (name) { - this.name = name; - this.attachments = {}; -}; -spine.Skin.prototype = { - addAttachment: function (slotIndex, name, attachment) { - this.attachments[slotIndex + ":" + name] = attachment; - }, - getAttachment: function (slotIndex, name) { - return this.attachments[slotIndex + ":" + name]; - }, - _attachAll: function (skeleton, oldSkin) { - for (var key in oldSkin.attachments) { - var colon = key.indexOf(":"); - var slotIndex = parseInt(key.substring(0, colon)); - var name = key.substring(colon + 1); - var slot = skeleton.slots[slotIndex]; - if (slot.attachment && slot.attachment.name == name) { - var attachment = this.getAttachment(slotIndex, name); - if (attachment) slot.setAttachment(attachment); - } - } - } -}; - -spine.Animation = function (name, timelines, duration) { - this.name = name; - this.timelines = timelines; - this.duration = duration; -}; -spine.Animation.prototype = { - apply: function (skeleton, time, loop) { - if (loop && this.duration != 0) time %= this.duration; - var timelines = this.timelines; - for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, time, 1); - }, - mix: function (skeleton, time, loop, alpha) { - if (loop && this.duration != 0) time %= this.duration; - var timelines = this.timelines; - for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, time, alpha); - } -}; - -spine.binarySearch = function (values, target, step) { - var low = 0; - var high = Math.floor(values.length / step) - 2; - if (high == 0) return step; - var current = high >>> 1; - while (true) { - if (values[(current + 1) * step] <= target) - low = current + 1; - else - high = current; - if (low == high) return (low + 1) * step; - current = (low + high) >>> 1; - } -}; -spine.linearSearch = function (values, target, step) { - for (var i = 0, last = values.length - step; i <= last; i += step) - if (values[i] > target) return i; - return -1; -}; - -spine.Curves = function (frameCount) { - this.curves = []; // dfx, dfy, ddfx, ddfy, dddfx, dddfy, ... - this.curves.length = (frameCount - 1) * 6; -}; -spine.Curves.prototype = { - setLinear: function (frameIndex) { - this.curves[frameIndex * 6] = 0/*LINEAR*/; - }, - setStepped: function (frameIndex) { - this.curves[frameIndex * 6] = -1/*STEPPED*/; - }, - /** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next. - * cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of - * the difference between the keyframe's values. */ - setCurve: function (frameIndex, cx1, cy1, cx2, cy2) { - var subdiv_step = 1 / 10/*BEZIER_SEGMENTS*/; - var subdiv_step2 = subdiv_step * subdiv_step; - var subdiv_step3 = subdiv_step2 * subdiv_step; - var pre1 = 3 * subdiv_step; - var pre2 = 3 * subdiv_step2; - var pre4 = 6 * subdiv_step2; - var pre5 = 6 * subdiv_step3; - var tmp1x = -cx1 * 2 + cx2; - var tmp1y = -cy1 * 2 + cy2; - var tmp2x = (cx1 - cx2) * 3 + 1; - var tmp2y = (cy1 - cy2) * 3 + 1; - var i = frameIndex * 6; - var curves = this.curves; - curves[i] = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; - curves[i + 1] = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; - curves[i + 2] = tmp1x * pre4 + tmp2x * pre5; - curves[i + 3] = tmp1y * pre4 + tmp2y * pre5; - curves[i + 4] = tmp2x * pre5; - curves[i + 5] = tmp2y * pre5; - }, - getCurvePercent: function (frameIndex, percent) { - percent = percent < 0 ? 0 : (percent > 1 ? 1 : percent); - var curveIndex = frameIndex * 6; - var curves = this.curves; - var dfx = curves[curveIndex]; - if (!dfx/*LINEAR*/) return percent; - if (dfx == -1/*STEPPED*/) return 0; - var dfy = curves[curveIndex + 1]; - var ddfx = curves[curveIndex + 2]; - var ddfy = curves[curveIndex + 3]; - var dddfx = curves[curveIndex + 4]; - var dddfy = curves[curveIndex + 5]; - var x = dfx, y = dfy; - var i = 10/*BEZIER_SEGMENTS*/ - 2; - while (true) { - if (x >= percent) { - var lastX = x - dfx; - var lastY = y - dfy; - return lastY + (y - lastY) * (percent - lastX) / (x - lastX); - } - if (i == 0) break; - i--; - dfx += ddfx; - dfy += ddfy; - ddfx += dddfx; - ddfy += dddfy; - x += dfx; - y += dfy; - } - return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1. - } -}; - -spine.RotateTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, angle, ... - this.frames.length = frameCount * 2; -}; -spine.RotateTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 2; - }, - setFrame: function (frameIndex, time, angle) { - frameIndex *= 2; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = angle; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 2]) { // Time is after last frame. - var amount = bone.data.rotation + frames[frames.length - 1] - bone.rotation; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - bone.rotation += amount * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 2); - var lastFrameValue = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex - 2/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent); - - var amount = frames[frameIndex + 1/*FRAME_VALUE*/] - lastFrameValue; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - amount = bone.data.rotation + (lastFrameValue + amount * percent) - bone.rotation; - while (amount > 180) - amount -= 360; - while (amount < -180) - amount += 360; - bone.rotation += amount * alpha; - } -}; - -spine.TranslateTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, x, y, ... - this.frames.length = frameCount * 3; -}; -spine.TranslateTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 3; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 3; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = x; - this.frames[frameIndex + 2] = y; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 3]) { // Time is after last frame. - bone.x += (bone.data.x + frames[frames.length - 2] - bone.x) * alpha; - bone.y += (bone.data.y + frames[frames.length - 1] - bone.y) * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 3); - var lastFrameX = frames[frameIndex - 2]; - var lastFrameY = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); - - bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha; - bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha; - } -}; - -spine.ScaleTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, x, y, ... - this.frames.length = frameCount * 3; -}; -spine.ScaleTimeline.prototype = { - boneIndex: 0, - getFrameCount: function () { - return this.frames.length / 3; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 3; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = x; - this.frames[frameIndex + 2] = y; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var bone = skeleton.bones[this.boneIndex]; - - if (time >= frames[frames.length - 3]) { // Time is after last frame. - bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 3); - var lastFrameX = frames[frameIndex - 2]; - var lastFrameY = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent); - - bone.scaleX += (bone.data.scaleX - 1 + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - 1 + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.scaleY) * alpha; - } -}; - -spine.ColorTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, r, g, b, a, ... - this.frames.length = frameCount * 5; -}; -spine.ColorTimeline.prototype = { - slotIndex: 0, - getFrameCount: function () { - return this.frames.length / 2; - }, - setFrame: function (frameIndex, time, x, y) { - frameIndex *= 5; - this.frames[frameIndex] = time; - this.frames[frameIndex + 1] = r; - this.frames[frameIndex + 2] = g; - this.frames[frameIndex + 3] = b; - this.frames[frameIndex + 4] = a; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var slot = skeleton.slots[this.slotIndex]; - - if (time >= frames[frames.length - 5]) { // Time is after last frame. - var i = frames.length - 1; - slot.r = frames[i - 3]; - slot.g = frames[i - 2]; - slot.b = frames[i - 1]; - slot.a = frames[i]; - return; - } - - // Interpolate between the last frame and the current frame. - var frameIndex = spine.binarySearch(frames, time, 5); - var lastFrameR = frames[frameIndex - 4]; - var lastFrameG = frames[frameIndex - 3]; - var lastFrameB = frames[frameIndex - 2]; - var lastFrameA = frames[frameIndex - 1]; - var frameTime = frames[frameIndex]; - var percent = 1 - (time - frameTime) / (frames[frameIndex - 5/*LAST_FRAME_TIME*/] - frameTime); - percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent); - - var r = lastFrameR + (frames[frameIndex + 1/*FRAME_R*/] - lastFrameR) * percent; - var g = lastFrameG + (frames[frameIndex + 2/*FRAME_G*/] - lastFrameG) * percent; - var b = lastFrameB + (frames[frameIndex + 3/*FRAME_B*/] - lastFrameB) * percent; - var a = lastFrameA + (frames[frameIndex + 4/*FRAME_A*/] - lastFrameA) * percent; - if (alpha < 1) { - slot.r += (r - slot.r) * alpha; - slot.g += (g - slot.g) * alpha; - slot.b += (b - slot.b) * alpha; - slot.a += (a - slot.a) * alpha; - } else { - slot.r = r; - slot.g = g; - slot.b = b; - slot.a = a; - } - } -}; - -spine.AttachmentTimeline = function (frameCount) { - this.curves = new spine.Curves(frameCount); - this.frames = []; // time, ... - this.frames.length = frameCount; - this.attachmentNames = []; // time, ... - this.attachmentNames.length = frameCount; -}; -spine.AttachmentTimeline.prototype = { - slotIndex: 0, - getFrameCount: function () { - return this.frames.length; - }, - setFrame: function (frameIndex, time, attachmentName) { - this.frames[frameIndex] = time; - this.attachmentNames[frameIndex] = attachmentName; - }, - apply: function (skeleton, time, alpha) { - var frames = this.frames; - if (time < frames[0]) return; // Time is before first frame. - - var frameIndex; - if (time >= frames[frames.length - 1]) // Time is after last frame. - frameIndex = frames.length - 1; - else - frameIndex = spine.binarySearch(frames, time, 1) - 1; - - var attachmentName = this.attachmentNames[frameIndex]; - skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName)); - } -}; - -spine.SkeletonData = function () { - this.bones = []; - this.slots = []; - this.skins = []; - this.animations = []; -}; -spine.SkeletonData.prototype = { - defaultSkin: null, - /** @return May be null. */ - findBone: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].name == boneName) return bones[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findBoneIndex: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].name == boneName) return i; - return -1; - }, - /** @return May be null. */ - findSlot: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) { - if (slots[i].name == slotName) return slot[i]; - } - return null; - }, - /** @return -1 if the bone was not found. */ - findSlotIndex: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].name == slotName) return i; - return -1; - }, - /** @return May be null. */ - findSkin: function (skinName) { - var skins = this.skins; - for (var i = 0, n = skins.length; i < n; i++) - if (skins[i].name == skinName) return skins[i]; - return null; - }, - /** @return May be null. */ - findAnimation: function (animationName) { - var animations = this.animations; - for (var i = 0, n = animations.length; i < n; i++) - if (animations[i].name == animationName) return animations[i]; - return null; - } -}; - -spine.Skeleton = function (skeletonData) { - this.data = skeletonData; - - this.bones = []; - for (var i = 0, n = skeletonData.bones.length; i < n; i++) { - var boneData = skeletonData.bones[i]; - var parent = !boneData.parent ? null : this.bones[skeletonData.bones.indexOf(boneData.parent)]; - this.bones.push(new spine.Bone(boneData, parent)); - } - - this.slots = []; - this.drawOrder = []; - for (var i = 0, n = skeletonData.slots.length; i < n; i++) { - var slotData = skeletonData.slots[i]; - var bone = this.bones[skeletonData.bones.indexOf(slotData.boneData)]; - var slot = new spine.Slot(slotData, this, bone); - this.slots.push(slot); - this.drawOrder.push(slot); - } -}; -spine.Skeleton.prototype = { - x: 0, y: 0, - skin: null, - r: 1, g: 1, b: 1, a: 1, - time: 0, - flipX: false, flipY: false, - /** Updates the world transform for each bone. */ - updateWorldTransform: function () { - var flipX = this.flipX; - var flipY = this.flipY; - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - bones[i].updateWorldTransform(flipX, flipY); - }, - /** Sets the bones and slots to their setup pose values. */ - setToSetupPose: function () { - this.setBonesToSetupPose(); - this.setSlotsToSetupPose(); - }, - setBonesToSetupPose: function () { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - bones[i].setToSetupPose(); - }, - setSlotsToSetupPose: function () { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - slots[i].setToSetupPose(i); - }, - /** @return May return null. */ - getRootBone: function () { - return this.bones.length == 0 ? null : this.bones[0]; - }, - /** @return May be null. */ - findBone: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].data.name == boneName) return bones[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findBoneIndex: function (boneName) { - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) - if (bones[i].data.name == boneName) return i; - return -1; - }, - /** @return May be null. */ - findSlot: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].data.name == slotName) return slots[i]; - return null; - }, - /** @return -1 if the bone was not found. */ - findSlotIndex: function (slotName) { - var slots = this.slots; - for (var i = 0, n = slots.length; i < n; i++) - if (slots[i].data.name == slotName) return i; - return -1; - }, - setSkinByName: function (skinName) { - var skin = this.data.findSkin(skinName); - if (!skin) throw "Skin not found: " + skinName; - this.setSkin(skin); - }, - /** Sets the skin used to look up attachments not found in the {@link SkeletonData#getDefaultSkin() default skin}. Attachments - * from the new skin are attached if the corresponding attachment from the old skin was attached. - * @param newSkin May be null. */ - setSkin: function (newSkin) { - if (this.skin && newSkin) newSkin._attachAll(this, this.skin); - this.skin = newSkin; - }, - /** @return May be null. */ - getAttachmentBySlotName: function (slotName, attachmentName) { - return this.getAttachmentBySlotIndex(this.data.findSlotIndex(slotName), attachmentName); - }, - /** @return May be null. */ - getAttachmentBySlotIndex: function (slotIndex, attachmentName) { - if (this.skin) { - var attachment = this.skin.getAttachment(slotIndex, attachmentName); - if (attachment) return attachment; - } - if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); - return null; - }, - /** @param attachmentName May be null. */ - setAttachment: function (slotName, attachmentName) { - var slots = this.slots; - for (var i = 0, n = slots.size; i < n; i++) { - var slot = slots[i]; - if (slot.data.name == slotName) { - var attachment = null; - if (attachmentName) { - attachment = this.getAttachment(i, attachmentName); - if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName; - } - slot.setAttachment(attachment); - return; - } - } - throw "Slot not found: " + slotName; - }, - update: function (delta) { - time += delta; - } -}; - -spine.AttachmentType = { - region: 0 -}; - -spine.RegionAttachment = function () { - this.offset = []; - this.offset.length = 8; - this.uvs = []; - this.uvs.length = 8; -}; -spine.RegionAttachment.prototype = { - x: 0, y: 0, - rotation: 0, - scaleX: 1, scaleY: 1, - width: 0, height: 0, - rendererObject: null, - regionOffsetX: 0, regionOffsetY: 0, - regionWidth: 0, regionHeight: 0, - regionOriginalWidth: 0, regionOriginalHeight: 0, - setUVs: function (u, v, u2, v2, rotate) { - var uvs = this.uvs; - if (rotate) { - uvs[2/*X2*/] = u; - uvs[3/*Y2*/] = v2; - uvs[4/*X3*/] = u; - uvs[5/*Y3*/] = v; - uvs[6/*X4*/] = u2; - uvs[7/*Y4*/] = v; - uvs[0/*X1*/] = u2; - uvs[1/*Y1*/] = v2; - } else { - uvs[0/*X1*/] = u; - uvs[1/*Y1*/] = v2; - uvs[2/*X2*/] = u; - uvs[3/*Y2*/] = v; - uvs[4/*X3*/] = u2; - uvs[5/*Y3*/] = v; - uvs[6/*X4*/] = u2; - uvs[7/*Y4*/] = v2; - } - }, - updateOffset: function () { - var regionScaleX = this.width / this.regionOriginalWidth * this.scaleX; - var regionScaleY = this.height / this.regionOriginalHeight * this.scaleY; - var localX = -this.width / 2 * this.scaleX + this.regionOffsetX * regionScaleX; - var localY = -this.height / 2 * this.scaleY + this.regionOffsetY * regionScaleY; - var localX2 = localX + this.regionWidth * regionScaleX; - var localY2 = localY + this.regionHeight * regionScaleY; - var radians = this.rotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - var localXCos = localX * cos + this.x; - var localXSin = localX * sin; - var localYCos = localY * cos + this.y; - var localYSin = localY * sin; - var localX2Cos = localX2 * cos + this.x; - var localX2Sin = localX2 * sin; - var localY2Cos = localY2 * cos + this.y; - var localY2Sin = localY2 * sin; - var offset = this.offset; - offset[0/*X1*/] = localXCos - localYSin; - offset[1/*Y1*/] = localYCos + localXSin; - offset[2/*X2*/] = localXCos - localY2Sin; - offset[3/*Y2*/] = localY2Cos + localXSin; - offset[4/*X3*/] = localX2Cos - localY2Sin; - offset[5/*Y3*/] = localY2Cos + localX2Sin; - offset[6/*X4*/] = localX2Cos - localYSin; - offset[7/*Y4*/] = localYCos + localX2Sin; - }, - computeVertices: function (x, y, bone, vertices) { - x += bone.worldX; - y += bone.worldY; - var m00 = bone.m00; - var m01 = bone.m01; - var m10 = bone.m10; - var m11 = bone.m11; - var offset = this.offset; - vertices[0/*X1*/] = offset[0/*X1*/] * m00 + offset[1/*Y1*/] * m01 + x; - vertices[1/*Y1*/] = offset[0/*X1*/] * m10 + offset[1/*Y1*/] * m11 + y; - vertices[2/*X2*/] = offset[2/*X2*/] * m00 + offset[3/*Y2*/] * m01 + x; - vertices[3/*Y2*/] = offset[2/*X2*/] * m10 + offset[3/*Y2*/] * m11 + y; - vertices[4/*X3*/] = offset[4/*X3*/] * m00 + offset[5/*X3*/] * m01 + x; - vertices[5/*X3*/] = offset[4/*X3*/] * m10 + offset[5/*X3*/] * m11 + y; - vertices[6/*X4*/] = offset[6/*X4*/] * m00 + offset[7/*Y4*/] * m01 + x; - vertices[7/*Y4*/] = offset[6/*X4*/] * m10 + offset[7/*Y4*/] * m11 + y; - } -} - -spine.AnimationStateData = function (skeletonData) { - this.skeletonData = skeletonData; - this.animationToMixTime = {}; -}; -spine.AnimationStateData.prototype = { - defaultMix: 0, - setMixByName: function (fromName, toName, duration) { - var from = this.skeletonData.findAnimation(fromName); - if (!from) throw "Animation not found: " + fromName; - var to = this.skeletonData.findAnimation(toName); - if (!to) throw "Animation not found: " + toName; - this.setMix(from, to, duration); - }, - setMix: function (from, to, duration) { - this.animationToMixTime[from.name + ":" + to.name] = duration; - }, - getMix: function (from, to) { - var time = this.animationToMixTime[from.name + ":" + to.name]; - return time ? time : this.defaultMix; - } -}; - -spine.AnimationState = function (stateData) { - this.data = stateData; - this.queue = []; -}; -spine.AnimationState.prototype = { - current: null, - previous: null, - currentTime: 0, - previousTime: 0, - currentLoop: false, - previousLoop: false, - mixTime: 0, - mixDuration: 0, - update: function (delta) { - this.currentTime += delta; - this.previousTime += delta; - this.mixTime += delta; - - if (this.queue.length > 0) { - var entry = this.queue[0]; - if (this.currentTime >= entry.delay) { - this._setAnimation(entry.animation, entry.loop); - this.queue.shift(); - } - } - }, - apply: function (skeleton) { - if (!this.current) return; - if (this.previous) { - this.previous.apply(skeleton, this.previousTime, this.previousLoop); - var alpha = this.mixTime / this.mixDuration; - if (alpha >= 1) { - alpha = 1; - this.previous = null; - } - this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha); - } else - this.current.apply(skeleton, this.currentTime, this.currentLoop); - }, - clearAnimation: function () { - this.previous = null; - this.current = null; - this.queue.length = 0; - }, - _setAnimation: function (animation, loop) { - this.previous = null; - if (animation && this.current) { - this.mixDuration = this.data.getMix(this.current, animation); - if (this.mixDuration > 0) { - this.mixTime = 0; - this.previous = this.current; - this.previousTime = this.currentTime; - this.previousLoop = this.currentLoop; - } - } - this.current = animation; - this.currentLoop = loop; - this.currentTime = 0; - }, - /** @see #setAnimation(Animation, Boolean) */ - setAnimationByName: function (animationName, loop) { - var animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw "Animation not found: " + animationName; - this.setAnimation(animation, loop); - }, - /** Set the current animation. Any queued animations are cleared and the current animation time is set to 0. - * @param animation May be null. */ - setAnimation: function (animation, loop) { - this.queue.length = 0; - this._setAnimation(animation, loop); - }, - /** @see #addAnimation(Animation, Boolean, Number) */ - addAnimationByName: function (animationName, loop, delay) { - var animation = this.data.skeletonData.findAnimation(animationName); - if (!animation) throw "Animation not found: " + animationName; - this.addAnimation(animation, loop, delay); - }, - /** Adds an animation to be played delay seconds after the current or last queued animation. - * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */ - addAnimation: function (animation, loop, delay) { - var entry = {}; - entry.animation = animation; - entry.loop = loop; - - if (!delay || delay <= 0) { - var previousAnimation = this.queue.length == 0 ? this.current : this.queue[this.queue.length - 1].animation; - if (previousAnimation != null) - delay = previousAnimation.duration - this.data.getMix(previousAnimation, animation) + (delay || 0); - else - delay = 0; - } - entry.delay = delay; - - this.queue.push(entry); - }, - /** Returns true if no animation is set or if the current time is greater than the animation duration, regardless of looping. */ - isComplete: function () { - return !this.current || this.currentTime >= this.current.duration; - } -}; - -spine.SkeletonJson = function (attachmentLoader) { - this.attachmentLoader = attachmentLoader; -}; -spine.SkeletonJson.prototype = { - scale: 1, - readSkeletonData: function (root) { - var skeletonData = new spine.SkeletonData(); - - // Bones. - var bones = root["bones"]; - for (var i = 0, n = bones.length; i < n; i++) { - var boneMap = bones[i]; - var parent = null; - if (boneMap["parent"]) { - parent = skeletonData.findBone(boneMap["parent"]); - if (!parent) throw "Parent bone not found: " + boneMap["parent"]; - } - var boneData = new spine.BoneData(boneMap["name"], parent); - boneData.length = (boneMap["length"] || 0) * this.scale; - boneData.x = (boneMap["x"] || 0) * this.scale; - boneData.y = (boneMap["y"] || 0) * this.scale; - boneData.rotation = (boneMap["rotation"] || 0); - boneData.scaleX = boneMap["scaleX"] || 1; - boneData.scaleY = boneMap["scaleY"] || 1; - skeletonData.bones.push(boneData); - } - - // Slots. - var slots = root["slots"]; - for (var i = 0, n = slots.length; i < n; i++) { - var slotMap = slots[i]; - var boneData = skeletonData.findBone(slotMap["bone"]); - if (!boneData) throw "Slot bone not found: " + slotMap["bone"]; - var slotData = new spine.SlotData(slotMap["name"], boneData); - - var color = slotMap["color"]; - if (color) { - slotData.r = spine.SkeletonJson.toColor(color, 0); - slotData.g = spine.SkeletonJson.toColor(color, 1); - slotData.b = spine.SkeletonJson.toColor(color, 2); - slotData.a = spine.SkeletonJson.toColor(color, 3); - } - - slotData.attachmentName = slotMap["attachment"]; - - skeletonData.slots.push(slotData); - } - - // Skins. - var skins = root["skins"]; - for (var skinName in skins) { - if (!skins.hasOwnProperty(skinName)) continue; - var skinMap = skins[skinName]; - var skin = new spine.Skin(skinName); - for (var slotName in skinMap) { - if (!skinMap.hasOwnProperty(slotName)) continue; - var slotIndex = skeletonData.findSlotIndex(slotName); - var slotEntry = skinMap[slotName]; - for (var attachmentName in slotEntry) { - if (!slotEntry.hasOwnProperty(attachmentName)) continue; - var attachment = this.readAttachment(skin, attachmentName, slotEntry[attachmentName]); - if (attachment != null) skin.addAttachment(slotIndex, attachmentName, attachment); - } - } - skeletonData.skins.push(skin); - if (skin.name == "default") skeletonData.defaultSkin = skin; - } - - // Animations. - var animations = root["animations"]; - for (var animationName in animations) { - if (!animations.hasOwnProperty(animationName)) continue; - this.readAnimation(animationName, animations[animationName], skeletonData); - } - - return skeletonData; - }, - readAttachment: function (skin, name, map) { - name = map["name"] || name; - - var type = spine.AttachmentType[map["type"] || "region"]; - - if (type == spine.AttachmentType.region) { - var attachment = new spine.RegionAttachment(); - attachment.x = (map["x"] || 0) * this.scale; - attachment.y = (map["y"] || 0) * this.scale; - attachment.scaleX = map["scaleX"] || 1; - attachment.scaleY = map["scaleY"] || 1; - attachment.rotation = map["rotation"] || 0; - attachment.width = (map["width"] || 32) * this.scale; - attachment.height = (map["height"] || 32) * this.scale; - attachment.updateOffset(); - - attachment.rendererObject = {}; - attachment.rendererObject.name = name; - attachment.rendererObject.scale = {}; - attachment.rendererObject.scale.x = attachment.scaleX; - attachment.rendererObject.scale.y = attachment.scaleY; - attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180; - return attachment; - } - - throw "Unknown attachment type: " + type; - }, - - readAnimation: function (name, map, skeletonData) { - var timelines = []; - var duration = 0; - - var bones = map["bones"]; - for (var boneName in bones) { - if (!bones.hasOwnProperty(boneName)) continue; - var boneIndex = skeletonData.findBoneIndex(boneName); - if (boneIndex == -1) throw "Bone not found: " + boneName; - var boneMap = bones[boneName]; - - for (var timelineName in boneMap) { - if (!boneMap.hasOwnProperty(timelineName)) continue; - var values = boneMap[timelineName]; - if (timelineName == "rotate") { - var timeline = new spine.RotateTimeline(values.length); - timeline.boneIndex = boneIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - timeline.setFrame(frameIndex, valueMap["time"], valueMap["angle"]); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 2 - 2]); - - } else if (timelineName == "translate" || timelineName == "scale") { - var timeline; - var timelineScale = 1; - if (timelineName == "scale") - timeline = new spine.ScaleTimeline(values.length); - else { - timeline = new spine.TranslateTimeline(values.length); - timelineScale = this.scale; - } - timeline.boneIndex = boneIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - var x = (valueMap["x"] || 0) * timelineScale; - var y = (valueMap["y"] || 0) * timelineScale; - timeline.setFrame(frameIndex, valueMap["time"], x, y); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]); - - } else - throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"; - } - } - var slots = map["slots"]; - for (var slotName in slots) { - if (!slots.hasOwnProperty(slotName)) continue; - var slotMap = slots[slotName]; - var slotIndex = skeletonData.findSlotIndex(slotName); - - for (var timelineName in slotMap) { - if (!slotMap.hasOwnProperty(timelineName)) continue; - var values = slotMap[timelineName]; - if (timelineName == "color") { - var timeline = new spine.ColorTimeline(values.length); - timeline.slotIndex = slotIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - var color = valueMap["color"]; - var r = spine.SkeletonJson.toColor(color, 0); - var g = spine.SkeletonJson.toColor(color, 1); - var b = spine.SkeletonJson.toColor(color, 2); - var a = spine.SkeletonJson.toColor(color, 3); - timeline.setFrame(frameIndex, valueMap["time"], r, g, b, a); - spine.SkeletonJson.readCurve(timeline, frameIndex, valueMap); - frameIndex++; - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 5 - 5]); - - } else if (timelineName == "attachment") { - var timeline = new spine.AttachmentTimeline(values.length); - timeline.slotIndex = slotIndex; - - var frameIndex = 0; - for (var i = 0, n = values.length; i < n; i++) { - var valueMap = values[i]; - timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]); - } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); - - } else - throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"; - } - } - skeletonData.animations.push(new spine.Animation(name, timelines, duration)); - } -}; -spine.SkeletonJson.readCurve = function (timeline, frameIndex, valueMap) { - var curve = valueMap["curve"]; - if (!curve) return; - if (curve == "stepped") - timeline.curves.setStepped(frameIndex); - else if (curve instanceof Array) - timeline.curves.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); -}; -spine.SkeletonJson.toColor = function (hexString, colorIndex) { - if (hexString.length != 8) throw "Color hexidecimal length must be 8, recieved: " + hexString; - return parseInt(hexString.substring(colorIndex * 2, 2), 16) / 255; -}; - -spine.Atlas = function (atlasText, textureLoader) { - this.textureLoader = textureLoader; - this.pages = []; - this.regions = []; - - var reader = new spine.AtlasReader(atlasText); - var tuple = []; - tuple.length = 4; - var page = null; - while (true) { - var line = reader.readLine(); - if (line == null) break; - line = reader.trim(line); - if (line.length == 0) - page = null; - else if (!page) { - page = new spine.AtlasPage(); - page.name = line; - - page.format = spine.Atlas.Format[reader.readValue()]; - - reader.readTuple(tuple); - page.minFilter = spine.Atlas.TextureFilter[tuple[0]]; - page.magFilter = spine.Atlas.TextureFilter[tuple[1]]; - - var direction = reader.readValue(); - page.uWrap = spine.Atlas.TextureWrap.clampToEdge; - page.vWrap = spine.Atlas.TextureWrap.clampToEdge; - if (direction == "x") - page.uWrap = spine.Atlas.TextureWrap.repeat; - else if (direction == "y") - page.vWrap = spine.Atlas.TextureWrap.repeat; - else if (direction == "xy") - page.uWrap = page.vWrap = spine.Atlas.TextureWrap.repeat; - - textureLoader.load(page, line); - - this.pages.push(page); - - } else { - var region = new spine.AtlasRegion(); - region.name = line; - region.page = page; - - region.rotate = reader.readValue() == "true"; - - reader.readTuple(tuple); - var x = parseInt(tuple[0]); - var y = parseInt(tuple[1]); - - reader.readTuple(tuple); - var width = parseInt(tuple[0]); - var height = parseInt(tuple[1]); - - region.u = x / page.width; - region.v = y / page.height; - if (region.rotate) { - region.u2 = (x + height) / page.width; - region.v2 = (y + width) / page.height; - } else { - region.u2 = (x + width) / page.width; - region.v2 = (y + height) / page.height; - } - region.x = x; - region.y = y; - region.width = Math.abs(width); - region.height = Math.abs(height); - - if (reader.readTuple(tuple) == 4) { // split is optional - region.splits = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; - - if (reader.readTuple(tuple) == 4) { // pad is optional, but only present with splits - region.pads = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])]; - - reader.readTuple(tuple); - } - } - - region.originalWidth = parseInt(tuple[0]); - region.originalHeight = parseInt(tuple[1]); - - reader.readTuple(tuple); - region.offsetX = parseInt(tuple[0]); - region.offsetY = parseInt(tuple[1]); - - region.index = parseInt(reader.readValue()); - - this.regions.push(region); - } - } -}; -spine.Atlas.prototype = { - findRegion: function (name) { - var regions = this.regions; - for (var i = 0, n = regions.length; i < n; i++) - if (regions[i].name == name) return regions[i]; - return null; - }, - dispose: function () { - var pages = this.pages; - for (var i = 0, n = pages.length; i < n; i++) - this.textureLoader.unload(pages[i].rendererObject); - }, - updateUVs: function (page) { - var regions = this.regions; - for (var i = 0, n = regions.length; i < n; i++) { - var region = regions[i]; - if (region.page != page) continue; - region.u = region.x / page.width; - region.v = region.y / page.height; - if (region.rotate) { - region.u2 = (region.x + region.height) / page.width; - region.v2 = (region.y + region.width) / page.height; - } else { - region.u2 = (region.x + region.width) / page.width; - region.v2 = (region.y + region.height) / page.height; - } - } - } -}; - -spine.Atlas.Format = { - alpha: 0, - intensity: 1, - luminanceAlpha: 2, - rgb565: 3, - rgba4444: 4, - rgb888: 5, - rgba8888: 6 -}; - -spine.Atlas.TextureFilter = { - nearest: 0, - linear: 1, - mipMap: 2, - mipMapNearestNearest: 3, - mipMapLinearNearest: 4, - mipMapNearestLinear: 5, - mipMapLinearLinear: 6 -}; - -spine.Atlas.TextureWrap = { - mirroredRepeat: 0, - clampToEdge: 1, - repeat: 2 -}; - -spine.AtlasPage = function () {}; -spine.AtlasPage.prototype = { - name: null, - format: null, - minFilter: null, - magFilter: null, - uWrap: null, - vWrap: null, - rendererObject: null, - width: 0, - height: 0 -}; - -spine.AtlasRegion = function () {}; -spine.AtlasRegion.prototype = { - page: null, - name: null, - x: 0, y: 0, - width: 0, height: 0, - u: 0, v: 0, u2: 0, v2: 0, - offsetX: 0, offsetY: 0, - originalWidth: 0, originalHeight: 0, - index: 0, - rotate: false, - splits: null, - pads: null, -}; - -spine.AtlasReader = function (text) { - this.lines = text.split(/\r\n|\r|\n/); -}; -spine.AtlasReader.prototype = { - index: 0, - trim: function (value) { - return value.replace(/^\s+|\s+$/g, ""); - }, - readLine: function () { - if (this.index >= this.lines.length) return null; - return this.lines[this.index++]; - }, - readValue: function () { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) throw "Invalid line: " + line; - return this.trim(line.substring(colon + 1)); - }, - /** Returns the number of tuple values read (2 or 4). */ - readTuple: function (tuple) { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) throw "Invalid line: " + line; - var i = 0, lastMatch= colon + 1; - for (; i < 3; i++) { - var comma = line.indexOf(",", lastMatch); - if (comma == -1) { - if (i == 0) throw "Invalid line: " + line; - break; - } - tuple[i] = this.trim(line.substr(lastMatch, comma - lastMatch)); - lastMatch = comma + 1; - } - tuple[i] = this.trim(line.substring(lastMatch)); - return i + 1; - } -} - -spine.AtlasAttachmentLoader = function (atlas) { - this.atlas = atlas; -} -spine.AtlasAttachmentLoader.prototype = { - newAttachment: function (skin, type, name) { - switch (type) { - case spine.AttachmentType.region: - var region = this.atlas.findRegion(name); - if (!region) throw "Region not found in atlas: " + name + " (" + type + ")"; - var attachment = new spine.RegionAttachment(name); - attachment.rendererObject = region; - attachment.setUVs(region.u, region.v, region.u2, region.v2, region.rotate); - attachment.regionOffsetX = region.offsetX; - attachment.regionOffsetY = region.offsetY; - attachment.regionWidth = region.width; - attachment.regionHeight = region.height; - attachment.regionOriginalWidth = region.originalWidth; - attachment.regionOriginalHeight = region.originalHeight; - return attachment; - } - throw "Unknown attachment type: " + type; - } -} - -PIXI.AnimCache = {}; -spine.Bone.yDown = true; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - - -/** - * This object is one that will allow you to specify custom rendering functions based on render type - * - * @class CustomRenderable - * @extends DisplayObject - * @constructor - */ -PIXI.CustomRenderable = function() -{ - PIXI.DisplayObject.call( this ); - -} - -// constructor -PIXI.CustomRenderable.prototype = Object.create( PIXI.DisplayObject.prototype ); -PIXI.CustomRenderable.prototype.constructor = PIXI.CustomRenderable; - -/** - * If this object is being rendered by a CanvasRenderer it will call this callback - * - * @method renderCanvas - * @param renderer {CanvasRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.renderCanvas = function(renderer) -{ - // override! -} - -/** - * If this object is being rendered by a WebGLRenderer it will call this callback to initialize - * - * @method initWebGL - * @param renderer {WebGLRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.initWebGL = function(renderer) -{ - // override! -} - -/** - * If this object is being rendered by a WebGLRenderer it will call this callback - * - * @method renderWebGL - * @param renderer {WebGLRenderer} The renderer instance - */ -PIXI.CustomRenderable.prototype.renderWebGL = function(renderGroup, projectionMatrix) -{ - // not sure if both needed? but ya have for now! - // override! -} - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.BaseTextureCache = {}; -PIXI.texturesToUpdate = []; -PIXI.texturesToDestroy = []; - -/** - * A texture stores the information that represents an image. All textures have a base texture - * - * @class BaseTexture - * @uses EventTarget - * @constructor - * @param source {String} the source object (image or canvas) - */ -PIXI.BaseTexture = function(source) -{ - PIXI.EventTarget.call( this ); - - /** - * [read-only] The width of the base texture set when the image has loaded - * - * @property width - * @type Number - * @readOnly - */ - this.width = 100; - - /** - * [read-only] The height of the base texture set when the image has loaded - * - * @property height - * @type Number - * @readOnly - */ - this.height = 100; - - /** - * [read-only] Describes if the base texture has loaded or not - * - * @property hasLoaded - * @type Boolean - * @readOnly - */ - this.hasLoaded = false; - - /** - * The source that is loaded to create the texture - * - * @property source - * @type Image - */ - this.source = source; - - if(!source)return; - - if(this.source instanceof Image || this.source instanceof HTMLImageElement) - { - if(this.source.complete) - { - this.hasLoaded = true; - this.width = this.source.width; - this.height = this.source.height; - - PIXI.texturesToUpdate.push(this); - } - else - { - - var scope = this; - this.source.onload = function(){ - - scope.hasLoaded = true; - scope.width = scope.source.width; - scope.height = scope.source.height; - - // add it to somewhere... - PIXI.texturesToUpdate.push(scope); - scope.dispatchEvent( { type: 'loaded', content: scope } ); - } - // this.image.src = imageUrl; - } - } - else - { - this.hasLoaded = true; - this.width = this.source.width; - this.height = this.source.height; - - PIXI.texturesToUpdate.push(this); - } - - this._powerOf2 = false; -} - -PIXI.BaseTexture.prototype.constructor = PIXI.BaseTexture; - -/** - * Destroys this base texture - * - * @method destroy - */ -PIXI.BaseTexture.prototype.destroy = function() -{ - if(this.source instanceof Image) - { - this.source.src = null; - } - this.source = null; - PIXI.texturesToDestroy.push(this); -} - -/** - * Helper function that returns a base texture based on an image url - * If the image is not in the base texture cache it will be created and loaded - * - * @static - * @method fromImage - * @param imageUrl {String} The image url of the texture - * @return BaseTexture - */ -PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin) -{ - var baseTexture = PIXI.BaseTextureCache[imageUrl]; - if(!baseTexture) - { - // new Image() breaks tex loading in some versions of Chrome. - // See https://code.google.com/p/chromium/issues/detail?id=238071 - var image = new Image();//document.createElement('img'); - if (crossorigin) - { - image.crossOrigin = ''; - } - image.src = imageUrl; - baseTexture = new PIXI.BaseTexture(image); - PIXI.BaseTextureCache[imageUrl] = baseTexture; - } - - return baseTexture; -} - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -PIXI.TextureCache = {}; -PIXI.FrameCache = {}; - -/** - * A texture stores the information that represents an image or part of an image. It cannot be added - * to the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used - * - * @class Texture - * @uses EventTarget - * @constructor - * @param baseTexture {BaseTexture} The base texture source to create the texture from - * @param frame {Rectangle} The rectangle frame of the texture to show - */ -PIXI.Texture = function(baseTexture, frame) -{ - PIXI.EventTarget.call( this ); - - if(!frame) - { - this.noFrame = true; - frame = new PIXI.Rectangle(0,0,1,1); - } - - if(baseTexture instanceof PIXI.Texture) - baseTexture = baseTexture.baseTexture; - - /** - * The base texture of this texture - * - * @property baseTexture - * @type BaseTexture - */ - this.baseTexture = baseTexture; - - /** - * The frame specifies the region of the base texture that this texture uses - * - * @property frame - * @type Rectangle - */ - this.frame = frame; - - /** - * The trim point - * - * @property trim - * @type Point - */ - this.trim = new PIXI.Point(); - - this.scope = this; - - if(baseTexture.hasLoaded) - { - if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); - //console.log(frame) - - this.setFrame(frame); - } - else - { - var scope = this; - baseTexture.addEventListener( 'loaded', function(){ scope.onBaseTextureLoaded()} ); - } -} - -PIXI.Texture.prototype.constructor = PIXI.Texture; - -/** - * Called when the base texture is loaded - * - * @method onBaseTextureLoaded - * @param event - * @private - */ -PIXI.Texture.prototype.onBaseTextureLoaded = function(event) -{ - var baseTexture = this.baseTexture; - baseTexture.removeEventListener( 'loaded', this.onLoaded ); - - if(this.noFrame)this.frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height); - this.noFrame = false; - this.width = this.frame.width; - this.height = this.frame.height; - - this.scope.dispatchEvent( { type: 'update', content: this } ); -} - -/** - * Destroys this texture - * - * @method destroy - * @param destroyBase {Boolean} Whether to destroy the base texture as well - */ -PIXI.Texture.prototype.destroy = function(destroyBase) -{ - if(destroyBase)this.baseTexture.destroy(); -} - -/** - * Specifies the rectangle region of the baseTexture - * - * @method setFrame - * @param frame {Rectangle} The frame of the texture to set it to - */ -PIXI.Texture.prototype.setFrame = function(frame) -{ - this.frame = frame; - this.width = frame.width; - this.height = frame.height; - - if(frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height) - { - throw new Error("Texture Error: frame does not fit inside the base Texture dimensions " + this); - } - - this.updateFrame = true; - - PIXI.Texture.frameUpdates.push(this); - //this.dispatchEvent( { type: 'update', content: this } ); -} - -/** - * Helper function that returns a texture based on an image url - * If the image is not in the texture cache it will be created and loaded - * - * @static - * @method fromImage - * @param imageUrl {String} The image url of the texture - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - * @return Texture - */ -PIXI.Texture.fromImage = function(imageUrl, crossorigin) -{ - var texture = PIXI.TextureCache[imageUrl]; - - if(!texture) - { - texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin)); - PIXI.TextureCache[imageUrl] = texture; - } - - return texture; -} - -/** - * Helper function that returns a texture based on a frame id - * If the frame id is not in the texture cache an error will be thrown - * - * @static - * @method fromFrame - * @param frameId {String} The frame id of the texture - * @return Texture - */ -PIXI.Texture.fromFrame = function(frameId) -{ - var texture = PIXI.TextureCache[frameId]; - if(!texture)throw new Error("The frameId '"+ frameId +"' does not exist in the texture cache " + this); - return texture; -} - -/** - * Helper function that returns a texture based on a canvas element - * If the canvas is not in the texture cache it will be created and loaded - * - * @static - * @method fromCanvas - * @param canvas {Canvas} The canvas element source of the texture - * @return Texture - */ -PIXI.Texture.fromCanvas = function(canvas) -{ - var baseTexture = new PIXI.BaseTexture(canvas); - return new PIXI.Texture(baseTexture); -} - - -/** - * Adds a texture to the textureCache. - * - * @static - * @method addTextureToCache - * @param texture {Texture} - * @param id {String} the id that the texture will be stored against. - */ -PIXI.Texture.addTextureToCache = function(texture, id) -{ - PIXI.TextureCache[id] = texture; -} - -/** - * Remove a texture from the textureCache. - * - * @static - * @method removeTextureFromCache - * @param id {String} the id of the texture to be removed - * @return {Texture} the texture that was removed - */ -PIXI.Texture.removeTextureFromCache = function(id) -{ - var texture = PIXI.TextureCache[id] - PIXI.TextureCache[id] = null; - return texture; -} - -// this is more for webGL.. it contains updated frames.. -PIXI.Texture.frameUpdates = []; - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - A RenderTexture is a special texture that allows any pixi displayObject to be rendered to it. - - __Hint__: All DisplayObjects (exmpl. Sprites) that renders on RenderTexture should be preloaded. - Otherwise black rectangles will be drawn instead. - - RenderTexture takes snapshot of DisplayObject passed to render method. If DisplayObject is passed to render method, position and rotation of it will be ignored. For example: - - var renderTexture = new PIXI.RenderTexture(800, 600); - var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - sprite.position.x = 800/2; - sprite.position.y = 600/2; - sprite.anchor.x = 0.5; - sprite.anchor.y = 0.5; - renderTexture.render(sprite); - - Sprite in this case will be rendered to 0,0 position. To render this sprite at center DisplayObjectContainer should be used: - - var doc = new PIXI.DisplayObjectContainer(); - doc.addChild(sprite); - renderTexture.render(doc); // Renders to center of renderTexture - - @class RenderTexture - @extends Texture - @constructor - @param width {Number} The width of the render texture - @param height {Number} The height of the render texture - */ -PIXI.RenderTexture = function(width, height) -{ - PIXI.EventTarget.call( this ); - - this.width = width || 100; - this.height = height || 100; - - this.indetityMatrix = PIXI.mat3.create(); - - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); - - if(PIXI.gl) - { - this.initWebGL(); - } - else - { - this.initCanvas(); - } -} - -PIXI.RenderTexture.prototype = Object.create( PIXI.Texture.prototype ); -PIXI.RenderTexture.prototype.constructor = PIXI.RenderTexture; - -/** - * Initializes the webgl data for this texture - * - * @method initWebGL - * @private - */ -PIXI.RenderTexture.prototype.initWebGL = function() -{ - var gl = PIXI.gl; - this.glFramebuffer = gl.createFramebuffer(); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - - this.glFramebuffer.width = this.width; - this.glFramebuffer.height = this.height; - - this.baseTexture = new PIXI.BaseTexture(); - - this.baseTexture.width = this.width; - this.baseTexture.height = this.height; - - this.baseTexture._glTexture = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); - - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - - this.baseTexture.isRender = true; - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.baseTexture._glTexture, 0); - - // create a projection matrix.. - this.projection = new PIXI.Point(this.width/2 , this.height/2); - - // set the correct render function.. - this.render = this.renderWebGL; - - -} - - -PIXI.RenderTexture.prototype.resize = function(width, height) -{ - - this.width = width; - this.height = height; - - if(PIXI.gl) - { - this.projection.x = this.width/2 - this.projection.y = this.height/2; - - var gl = PIXI.gl; - gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - } - else - { - - this.frame.width = this.width - this.frame.height = this.height; - this.renderer.resize(this.width, this.height); - } -} - -/** - * Initializes the canvas data for this texture - * - * @method initCanvas - * @private - */ -PIXI.RenderTexture.prototype.initCanvas = function() -{ - this.renderer = new PIXI.CanvasRenderer(this.width, this.height, null, 0); - - this.baseTexture = new PIXI.BaseTexture(this.renderer.view); - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); - - this.render = this.renderCanvas; -} - -/** - * This function will draw the display object to the texture. - * - * @method renderWebGL - * @param displayObject {DisplayObject} The display object to render this texture on - * @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn - * @private - */ -PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, clear) -{ - var gl = PIXI.gl; - - // enable the alpha color mask.. - gl.colorMask(true, true, true, true); - - gl.viewport(0, 0, this.width, this.height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer ); - - if(clear) - { - gl.clearColor(0,0,0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - } - - // THIS WILL MESS WITH HIT TESTING! - var children = displayObject.children; - - //TODO -? create a new one??? dont think so! - var originalWorldTransform = displayObject.worldTransform; - displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix; - // modify to flip... - displayObject.worldTransform[4] = -1; - displayObject.worldTransform[5] = this.projection.y * 2; - - - if(position) - { - displayObject.worldTransform[2] = position.x; - displayObject.worldTransform[5] -= position.y; - } - - PIXI.visibleCount++; - displayObject.vcount = PIXI.visibleCount; - - for(var i=0,j=children.length; i} assetURLs an array of image/sprite sheet urls that you would like loaded - * supported. Supported image formats include "jpeg", "jpg", "png", "gif". Supported - * sprite sheet data formats only include "JSON" at this time. Supported bitmap font - * data formats include "xml" and "fnt". - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.AssetLoader = function(assetURLs, crossorigin) -{ - PIXI.EventTarget.call(this); - - /** - * The array of asset URLs that are going to be loaded - * - * @property assetURLs - * @type Array - */ - this.assetURLs = assetURLs; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * Maps file extension to loader types - * - * @property loadersByType - * @type Object - */ - this.loadersByType = { - "jpg": PIXI.ImageLoader, - "jpeg": PIXI.ImageLoader, - "png": PIXI.ImageLoader, - "gif": PIXI.ImageLoader, - "json": PIXI.JsonLoader, - "anim": PIXI.SpineLoader, - "xml": PIXI.BitmapFontLoader, - "fnt": PIXI.BitmapFontLoader - }; - - -}; - -/** - * Fired when an item has loaded - * @event onProgress - */ - -/** - * Fired when all the assets have loaded - * @event onComplete - */ - -// constructor -PIXI.AssetLoader.prototype.constructor = PIXI.AssetLoader; - -/** - * Starts loading the assets sequentially - * - * @method load - */ -PIXI.AssetLoader.prototype.load = function() -{ - var scope = this; - - this.loadCount = this.assetURLs.length; - - for (var i=0; i < this.assetURLs.length; i++) - { - var fileName = this.assetURLs[i]; - var fileType = fileName.split(".").pop().toLowerCase(); - - var loaderClass = this.loadersByType[fileType]; - if(!loaderClass) - throw new Error(fileType + " is an unsupported file type"); - - var loader = new loaderClass(fileName, this.crossorigin); - - loader.addEventListener("loaded", function() - { - scope.onAssetLoaded(); - }); - loader.load(); - } -}; - -/** - * Invoked after each file is loaded - * - * @method onAssetLoaded - * @private - */ -PIXI.AssetLoader.prototype.onAssetLoaded = function() -{ - this.loadCount--; - this.dispatchEvent({type: "onProgress", content: this}); - if(this.onProgress) this.onProgress(); - - if(this.loadCount == 0) - { - this.dispatchEvent({type: "onComplete", content: this}); - if(this.onComplete) this.onComplete(); - } -}; - - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The json file loader is used to load in JSON data and parsing it - * When loaded this class will dispatch a "loaded" event - * If load failed this class will dispatch a "error" event - * - * @class JsonLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the JSON file - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.JsonLoader = function (url, crossorigin) { - PIXI.EventTarget.call(this); - - /** - * The url of the bitmap font data - * - * @property url - * @type String - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * [read-only] The base url of the bitmap font data - * - * @property baseUrl - * @type String - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ""); - - /** - * [read-only] Whether the data has loaded yet - * - * @property loaded - * @type Boolean - * @readOnly - */ - this.loaded = false; - -}; - -// constructor -PIXI.JsonLoader.prototype.constructor = PIXI.JsonLoader; - -/** - * Loads the JSON data - * - * @method load - */ -PIXI.JsonLoader.prototype.load = function () { - this.ajaxRequest = new AjaxRequest(); - var scope = this; - this.ajaxRequest.onreadystatechange = function () { - scope.onJSONLoaded(); - }; - - this.ajaxRequest.open("GET", this.url, true); - if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/json"); - this.ajaxRequest.send(null); -}; - -/** - * Invoke when JSON file is loaded - * - * @method onJSONLoaded - * @private - */ -PIXI.JsonLoader.prototype.onJSONLoaded = function () { - if (this.ajaxRequest.readyState == 4) { - if (this.ajaxRequest.status == 200 || window.location.href.indexOf("http") == -1) { - this.json = JSON.parse(this.ajaxRequest.responseText); - - if(this.json.frames) - { - // sprite sheet - var scope = this; - var textureUrl = this.baseUrl + this.json.meta.image; - var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); - var frameData = this.json.frames; - - this.texture = image.texture.baseTexture; - image.addEventListener("loaded", function (event) { - scope.onLoaded(); - }); - - for (var i in frameData) { - var rect = frameData[i].frame; - if (rect) { - PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) { - //var realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) - // calculate the offset! - } - } - } - - image.load(); - - } - else if(this.json.bones) - { - // spine animation - var spineJsonParser = new spine.SkeletonJson(); - var skeletonData = spineJsonParser.readSkeletonData(this.json); - PIXI.AnimCache[this.url] = skeletonData; - this.onLoaded(); - } - else - { - this.onLoaded(); - } - } - else - { - this.onError(); - } - } -}; - -/** - * Invoke when json file loaded - * - * @method onLoaded - * @private - */ -PIXI.JsonLoader.prototype.onLoaded = function () { - this.loaded = true; - this.dispatchEvent({ - type: "loaded", - content: this - }); -}; - -/** - * Invoke when error occured - * - * @method onError - * @private - */ -PIXI.JsonLoader.prototype.onError = function () { - this.dispatchEvent({ - type: "error", - content: this - }); -}; -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The sprite sheet loader is used to load in JSON sprite sheet data - * To generate the data you can use http://www.codeandweb.com/texturepacker and publish the "JSON" format - * There is a free version so thats nice, although the paid version is great value for money. - * It is highly recommended to use Sprite sheets (also know as texture atlas") as it means sprite"s can be batched and drawn together for highly increased rendering speed. - * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() - * This loader will also load the image file that the Spritesheet points to as well as the data. - * When loaded this class will dispatch a "loaded" event - * - * @class SpriteSheetLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the sprite sheet JSON file - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ - -PIXI.SpriteSheetLoader = function (url, crossorigin) { - /* - * i use texture packer to load the assets.. - * http://www.codeandweb.com/texturepacker - * make sure to set the format as "JSON" - */ - PIXI.EventTarget.call(this); - - /** - * The url of the bitmap font data - * - * @property url - * @type String - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @property crossorigin - * @type Boolean - */ - this.crossorigin = crossorigin; - - /** - * [read-only] The base url of the bitmap font data - * - * @property baseUrl - * @type String - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ""); - - /** - * The texture being loaded - * - * @property texture - * @type Texture - */ - this.texture = null; - - /** - * The frames of the sprite sheet - * - * @property frames - * @type Object - */ - this.frames = {}; -}; - -// constructor -PIXI.SpriteSheetLoader.prototype.constructor = PIXI.SpriteSheetLoader; - -/** - * This will begin loading the JSON file - * - * @method load - */ -PIXI.SpriteSheetLoader.prototype.load = function () { - var scope = this; - var jsonLoader = new PIXI.JsonLoader(this.url, this.crossorigin); - jsonLoader.addEventListener("loaded", function (event) { - scope.json = event.content.json; - scope.onJSONLoaded(); - }); - jsonLoader.load(); -}; - -/** - * Invoke when JSON file is loaded - * - * @method onJSONLoaded - * @private - */ -PIXI.SpriteSheetLoader.prototype.onJSONLoaded = function () { - var scope = this; - var textureUrl = this.baseUrl + this.json.meta.image; - var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); - var frameData = this.json.frames; - - this.texture = image.texture.baseTexture; - image.addEventListener("loaded", function (event) { - scope.onLoaded(); - }); - - for (var i in frameData) { - var rect = frameData[i].frame; - if (rect) { - PIXI.TextureCache[i] = new PIXI.Texture(this.texture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) { - //var realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize; - PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w) - // calculate the offset! - } - } - } - - image.load(); -}; -/** - * Invoke when all files are loaded (json and texture) - * - * @method onLoaded - * @private - */ -PIXI.SpriteSheetLoader.prototype.onLoaded = function () { - this.dispatchEvent({ - type: "loaded", - content: this - }); -}; - -/** - * @author Mat Groves http://matgroves.com/ @Doormat23 - */ - -/** - * The image loader class is responsible for loading images file formats ("jpeg", "jpg", "png" and "gif") - * Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() - * When loaded this class will dispatch a 'loaded' event - * - * @class ImageLoader - * @uses EventTarget - * @constructor - * @param url {String} The url of the image - * @param crossorigin {Boolean} Whether requests should be treated as crossorigin - */ -PIXI.ImageLoader = function(url, crossorigin) -{ - PIXI.EventTarget.call(this); - - /** - * The texture being loaded - * - * @property texture - * @type Texture - */ - this.texture = PIXI.Texture.fromImage(url, crossorigin); - - /** - * if the image is loaded with loadFramedSpriteSheet - * frames will contain the sprite sheet frames - * - */ - this.frames = []; -}; - -// constructor -PIXI.ImageLoader.prototype.constructor = PIXI.ImageLoader; - -/** - * Loads image or takes it from cache - * - * @method load - */ -PIXI.ImageLoader.prototype.load = function() -{ - if(!this.texture.baseTexture.hasLoaded) - { - var scope = this; - this.texture.baseTexture.addEventListener("loaded", function() - { - scope.onLoaded(); - }); - } - else - { - this.onLoaded(); - } -}; - -/** - * Invoked when image file is loaded or it is already cached and ready to use - * - * @method onLoaded - * @private - */ -PIXI.ImageLoader.prototype.onLoaded = function() -{ - this.dispatchEvent({type: "loaded", content: this}); -}; - -/** - * Loads image and split it to uniform sized frames - * - * - * @method loadFramedSpriteSheet - * @param frameWidth {Number} with of each frame - * @param frameHeight {Number} height of each frame - * @param textureName {String} if given, the frames will be cached in - format - */ -PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName) -{ - this.frames = []; - var cols = Math.floor(this.texture.width / frameWidth); - var rows = Math.floor(this.texture.height / frameHeight); - - var i=0; - for (var y=0; y - + + + + + + + + + + + + + + + + + + + diff --git a/examples/example 16 - Displacement/index.html b/examples/example 16 - Displacement/index.html index c4c12d2..9827748 100644 --- a/examples/example 16 - Displacement/index.html +++ b/examples/example 16 - Displacement/index.html @@ -38,7 +38,6 @@ var blur = new PIXI.BlurFilter(); - // create an new instance of a pixi stage var stage = new PIXI.Stage(0xFFFFFF, true); @@ -69,7 +68,7 @@ var bgFront = PIXI.Sprite.fromImage("SceneRotate.jpg"); bgFront.anchor.x = 0.5; bgFront.anchor.y = 0.5; - bgFront.filters = [blur]//, blurY]; + //bgFront.filters = [blur]//, blurY]; stage.addChild(bgFront); bgFront.position.x = 800/2; bgFront.position.y = 600/2; @@ -107,7 +106,7 @@ //container.filters = [smart]//f, f2]; //panda.filters = [f2]; - +// container.filters = [filter] var count = 0; var switchy = false; @@ -117,13 +116,13 @@ if(!switchy) { - // panda.filters = [filter];// - container.filters = [f,blurX, blurY]; + container.filters = [f];// + // container.filters = [filter]//,blurX, blurY]; } else { - //panda.filters = null//.. [filter]; - container.filters = null; + container.filters = null//.. [filter]; + // container.filters = null; } PIXI.runList(stage); @@ -154,20 +153,19 @@ stage.addChild(help); //stage.filters = [filter]; - //stage.addChild(new PIXI.Sprite(mapTexture)) + stage.addChild(new PIXI.Sprite(mapTexture)) PIXI.runList(stage); requestAnimFrame(animate); - var position = new PIXI.Point(800/2 + 200, 600/2 ); + var position = new PIXI.Point(800/2 , 600/2 ); function animate() { - /// mapTexture.render(container, position); - - // console.log(PIXI.frameBufferPool.length); + mapTexture.render(container, position, true); + filter.scale.x = Math.sin(count) * 100; filter.scale.y = Math.cos(count) * 100; bg.rotation += 0.01; @@ -181,11 +179,11 @@ count += 0.1; - blurX.blur = 1/256; - blurY.blur = 1/256; +// blurX.blur = Math.sin(count) * 1/128; + // blurY.blur = Math.cos(count) * 1/128; // filter.matrix = colorMatrix; - + f.grey = Math.sin(count) renderer.render(stage); // f.renderTex(); diff --git a/pixi.sublime-project b/pixi.sublime-project new file mode 100644 index 0000000..d834dea --- /dev/null +++ b/pixi.sublime-project @@ -0,0 +1,8 @@ +{ + "folders": + [ + { + "path": "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js" + } + ] +} diff --git a/pixi.sublime-workspace b/pixi.sublime-workspace new file mode 100644 index 0000000..e998692 --- /dev/null +++ b/pixi.sublime-workspace @@ -0,0 +1,535 @@ +{ + "auto_complete": + { + "selected_items": + [ + [ + "pro", + "prototype" + ], + [ + "for", + "for for (…) {…}" + ], + [ + "fil", + "filters" + ], + [ + "blu", + "blurX" + ], + [ + "Blu", + "BlurXFilter" + ], + [ + "appl", + "applyFilterPass" + ], + [ + "ou", + "outputTexture" + ], + [ + "filte", + "filterBlock" + ], + [ + "We", + "WebGLGraphics" + ], + [ + "max", + "maxY" + ], + [ + "min", + "minY" + ], + [ + "re", + "rectangle" + ], + [ + "rend", + "renderable" + ] + ] + }, + "buffers": + [ + { + "file": "examples/example 16 - Displacement/index.html", + "settings": + { + "buffer_size": 4901, + "line_ending": "Unix" + } + }, + { + "file": "src/pixi/filters/GreyFilter.js", + "settings": + { + "buffer_size": 852, + "line_ending": "Unix" + } + }, + { + "file": "src/pixi/filters/DisplacementFilter.js", + "settings": + { + "buffer_size": 1698, + "line_ending": "Unix" + } + }, + { + "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", + "settings": + { + "buffer_size": 25104, + "line_ending": "Unix" + } + }, + { + "file": "src/pixi/renderers/webgl/WebGLFilterManager.js", + "settings": + { + "buffer_size": 11987, + "line_ending": "Unix" + } + } + ], + "build_system": "", + "command_palette": + { + "height": 0.0, + "selected_items": + [ + ], + "width": 0.0 + }, + "console": + { + "height": 139.0 + }, + "distraction_free": + { + "menu_visible": true, + "show_minimap": false, + "show_open_files": false, + "show_tabs": false, + "side_bar_visible": false, + "status_bar_visible": false + }, + "file_history": + [ + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLFilterManager.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/BlurXFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 16 - Displacement/index.html", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/BlurYFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/BlurFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLRenderGroup.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/SmartBlurFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/Gruntfile.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/display/DisplayObject.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/ColorMatrixFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/DisplacementFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/GreyFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/InvertFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/SepiaFilter.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/test/unit/DisplayObject.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/filters/SmartBlur.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/filters/FilterManager.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/textures/RenderTexture.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/PixiShader.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 13 - Graphics/index.html", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/primitives/Graphics.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLGraphics.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 11 - RenderTexture/index.html", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/examples/example 14 - Masking/index.html", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLShaders.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/renderers/webgl/WebGLRenderer.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/test/unit/renderers/WebGLShaders.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/core/Matrix.js", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/docs/classes/RenderTexture.html", + "/Users/matgroves/Dropbox/Development/html/workspace/pixi.js/src/pixi/core/Ellipse.js" + ], + "find": + { + "height": 35.0 + }, + "find_in_files": + { + "height": 0.0, + "where_history": + [ + "" + ] + }, + "find_state": + { + "case_sensitive": false, + "find_history": + [ + "console", + "pand", + "colorMatrix", + "FilterTexture", + "minY", + "minX", + "uvBuffer", + " \n", + "console", + "data", + "console", + "applyFilterPass", + " \n", + "filterA", + " \n", + "filters", + "render", + "filter", + "Filter", + "filter", + "Filter", + "filter", + " //", + " \n", + "\n ", + " \n", + "pass", + "RTScene", + "vTexCoord", + "blurSize", + "FilterManager", + "i", + "dirty", + "console", + " ", + "PIXI.projection", + "\n ", + "h1", + "h0", + "w1", + "w0", + "TODO", + "radius", + "Things", + "radius", + " ", + "t", + "cle", + "this", + "PIXI", + ");\n", + "\n", + " \n", + " \n", + "console", + " \n", + "this", + "this.renderSpecial(renderable, projection);\nthis.renderSpecial(renderable, projection);\nrenderSpecial", + "this.renderSpecial(renderable, projection);", + "off", + "atlas", + "spineboy.atlas", + "spineboy.atla", + "spineboy.png", + "floor", + "groun" + ], + "highlight": true, + "in_selection": false, + "preserve_case": false, + "regex": false, + "replace_history": + [ + ], + "reverse": false, + "show_context": true, + "use_buffer2": true, + "whole_word": false, + "wrap": true + }, + "groups": + [ + { + "selected": 0, + "sheets": + [ + { + "buffer": 0, + "file": "examples/example 16 - Displacement/index.html", + "settings": + { + "buffer_size": 4901, + "regions": + { + }, + "selection": + [ + [ + 2608, + 2608 + ] + ], + "settings": + { + "syntax": "Packages/HTML/HTML.tmLanguage", + "translate_tabs_to_spaces": false + }, + "translation.x": 0.0, + "translation.y": 0.0, + "zoom_level": 1.0 + }, + "type": "text" + }, + { + "buffer": 1, + "file": "src/pixi/filters/GreyFilter.js", + "settings": + { + "buffer_size": 852, + "regions": + { + }, + "selection": + [ + [ + 0, + 0 + ] + ], + "settings": + { + "syntax": "Packages/JavaScript/JavaScript.tmLanguage" + }, + "translation.x": 0.0, + "translation.y": 0.0, + "zoom_level": 1.0 + }, + "type": "text" + }, + { + "buffer": 2, + "file": "src/pixi/filters/DisplacementFilter.js", + "settings": + { + "buffer_size": 1698, + "regions": + { + }, + "selection": + [ + [ + 818, + 818 + ] + ], + "settings": + { + "syntax": "Packages/JavaScript/JavaScript.tmLanguage" + }, + "translation.x": 0.0, + "translation.y": 0.0, + "zoom_level": 1.0 + }, + "type": "text" + }, + { + "buffer": 3, + "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", + "settings": + { + "buffer_size": 25104, + "regions": + { + }, + "selection": + [ + [ + 3418, + 3418 + ] + ], + "settings": + { + "syntax": "Packages/JavaScript/JavaScript.tmLanguage", + "translate_tabs_to_spaces": false + }, + "translation.x": 4.0, + "translation.y": 1680.0, + "zoom_level": 1.0 + }, + "type": "text" + }, + { + "buffer": 4, + "file": "src/pixi/renderers/webgl/WebGLFilterManager.js", + "settings": + { + "buffer_size": 11987, + "regions": + { + }, + "selection": + [ + [ + 664, + 664 + ] + ], + "settings": + { + "syntax": "Packages/JavaScript/JavaScript.tmLanguage", + "translate_tabs_to_spaces": false + }, + "translation.x": 0.0, + "translation.y": 371.0, + "zoom_level": 1.0 + }, + "type": "text" + } + ] + } + ], + "incremental_find": + { + "height": 0.0 + }, + "input": + { + "height": 33.0 + }, + "layout": + { + "cells": + [ + [ + 0, + 0, + 1, + 1 + ] + ], + "cols": + [ + 0.0, + 1.0 + ], + "rows": + [ + 0.0, + 1.0 + ] + }, + "menu_visible": true, + "replace": + { + "height": 0.0 + }, + "save_all_on_build": true, + "select_file": + { + "height": 0.0, + "selected_items": + [ + [ + "webglrend", + "src/pixi/renderers/webgl/WebGLRenderGroup.js" + ], + [ + "greyfil", + "src/pixi/filters/GreyFilter.js" + ], + [ + "displ", + "src/pixi/display/DisplayObject.js" + ], + [ + "grun", + "Gruntfile.js" + ], + [ + "webgle", + "src/pixi/renderers/webgl/WebGLRenderGroup.js" + ], + [ + "displa", + "src/pixi/display/DisplayObject.js" + ], + [ + "index", + "examples/example 16 - Displacement/index.html" + ], + [ + "ind", + "examples/example 13 - Graphics/index.html" + ], + [ + "grunt", + "Gruntfile.js" + ], + [ + "webglgr", + "src/pixi/renderers/webgl/WebGLGraphics.js" + ], + [ + "webglsh", + "src/pixi/renderers/webgl/WebGLShaders.js" + ], + [ + "webglsha", + "test/unit/renderers/WebGLShaders.js" + ], + [ + "webglren", + "src/pixi/renderers/webgl/WebGLRenderer.js" + ], + [ + "webgl", + "src/pixi/renderers/webgl/WebGLShaders.js" + ], + [ + "grap", + "src/pixi/primitives/Graphics.js" + ], + [ + "index.", + "examples/example 13 - Graphics/index.html" + ], + [ + "inde", + "examples/example 14 - Masking/index.html" + ], + [ + "rendertexture", + "src/pixi/textures/RenderTexture.js" + ], + [ + "rendert", + "docs/classes/RenderTexture.html" + ], + [ + "matrix", + "src/pixi/core/Matrix.js" + ] + ], + "width": 0.0 + }, + "select_project": + { + "height": 0.0, + "selected_items": + [ + ], + "width": 0.0 + }, + "show_minimap": true, + "show_open_files": false, + "show_tabs": true, + "side_bar_visible": true, + "side_bar_width": 229.0, + "status_bar_visible": true +} diff --git a/src/pixi/filters/DisplacementFilter.js b/src/pixi/filters/DisplacementFilter.js index d486563..df19f6f 100644 --- a/src/pixi/filters/DisplacementFilter.js +++ b/src/pixi/filters/DisplacementFilter.js @@ -27,8 +27,11 @@ PIXI.DisplacementFilter = function(texture) "const vec2 textureDimensions = vec2(800.0, 600.0);", "void main(void) {", - - "vec2 matSample = texture2D(displacementMap, vTextureCoord * (textureDimensions/mapDimensions)).xy;", + "vec2 mapCords = vTextureCoord.xy;", +// "mapCords -= ;", + // "mapCords.y *= -1.0;", + // "mapCords.y += 1.0;", + "vec2 matSample = texture2D(displacementMap, mapCords).xy;", "matSample -= 0.5;", "matSample *= scale;", "matSample /= textureDimensions;", diff --git a/src/pixi/renderers/webgl/WebGLFilterManager.js b/src/pixi/renderers/webgl/WebGLFilterManager.js index 94b7eb1..0f9b78a 100644 --- a/src/pixi/renderers/webgl/WebGLFilterManager.js +++ b/src/pixi/renderers/webgl/WebGLFilterManager.js @@ -73,6 +73,8 @@ PIXI.WebGLFilterManager.prototype.pushFilter = function(filterBlock) //filter.texture = texture; filterBlock._glFilterTexture = texture; + + //console.log("PUSH") } @@ -172,7 +174,7 @@ PIXI.WebGLFilterManager.prototype.popFilter = function() // time to render the filters texture to the previous scene if(this.filterStack.length === 0) { - gl.colorMask(true, true, true, false); + gl.colorMask(true, true, true, this.buffer); } else { diff --git a/src/pixi/renderers/webgl/WebGLRenderGroup.js b/src/pixi/renderers/webgl/WebGLRenderGroup.js index e5c3a8f..48d3327 100644 --- a/src/pixi/renderers/webgl/WebGLRenderGroup.js +++ b/src/pixi/renderers/webgl/WebGLRenderGroup.js @@ -99,9 +99,15 @@ PIXI.WebGLRenderGroup.prototype.render = function(projection, buffer) PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection, buffer) { PIXI.WebGLRenderer.updateTextures(); - var gl = this.gl; + gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + + this.filterManager.begin(projection, buffer); + + //console.log(buffer) + + //gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); // to do! // render part of the scene... @@ -121,11 +127,13 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project var nextRenderable = displayObject.first; while(nextRenderable._iNext) { - nextRenderable = nextRenderable._iNext; if(nextRenderable.renderable && nextRenderable.__renderGroup)break; + nextRenderable = nextRenderable._iNext; } var startBatch = nextRenderable.batch; + //console.log(nextRenderable); + //console.log(renderable) if(nextRenderable instanceof PIXI.Sprite) { startBatch = nextRenderable.batch; @@ -155,13 +163,11 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project } // Get the LAST renderable object - var lastRenderable = displayObject; - var endBatch; - var lastItem = displayObject; - while(lastItem.children.length > 0) + var lastRenderable = displayObject.last; + while(lastRenderable._iPrev) { - lastItem = lastItem.children[lastItem.children.length-1]; - if(lastItem.renderable)lastRenderable = lastItem.last; + if(lastRenderable.renderable && lastRenderable.__renderGroup)break; + lastRenderable = lastRenderable._iNext; } if(lastRenderable instanceof PIXI.Sprite) @@ -190,6 +196,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project endBatch = lastRenderable; } + console.log(endBatch); // TODO - need to fold this up a bit! if(startBatch == endBatch) @@ -259,6 +266,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) var worldVisible = renderable.vcount === PIXI.visibleCount + if(renderable instanceof PIXI.TilingSprite) { if(worldVisible)this.renderTilingSprite(renderable, projection); From a46b74f8cac31f4aed88f9b1d20b3b7ade2ec36e Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Fri, 1 Nov 2013 13:51:25 +0000 Subject: [PATCH 62/96] Filter Tweaks Displacement Map Filter tweaked Demos created --- Gruntfile.js | 5 +- bin/pixi.dev.js | 812 +++++++++++------- bin/pixi.dev.js.map | 6 +- bin/pixi.js | 10 +- examples/example 13 - Graphics/index.html | 1 - .../example 15 - Filters/displacementMAP.jpg | Bin 0 -> 20161 bytes .../example 15 - Filters/displacement_BG.jpg | Bin 14477 -> 61854 bytes ...ement_fish1.jpg => displacement_fish1.png} | Bin ...ement_fish2.jpg => displacement_fish2.png} | Bin .../displacement_fish3.jpg | Bin 67276 -> 0 bytes .../displacement_fish3.png | Bin 0 -> 4410 bytes ...ement_fish4.jpg => displacement_fish4.png} | Bin .../example 15 - Filters/displacement_map.jpg | Bin 0 -> 86309 bytes examples/example 15 - Filters/indexAll.html | 161 ++++ examples/example 15 - Filters/indexBlur.html | 6 +- .../indexDisplacement.html | 161 ++++ .../indexDisplacement_2.html | 162 ++++ examples/example 15 - Filters/zeldaWaves.png | Bin 0 -> 38032 bytes examples/example 16 - Displacement/index.html | 59 +- pixi.sublime-workspace | 367 ++++++-- src/pixi/filters/AbstractFilter.js | 18 + src/pixi/filters/BlurFilter.js | 2 +- src/pixi/filters/BlurXFilter.js | 12 +- src/pixi/filters/BlurYFilter.js | 10 +- src/pixi/filters/ColorMatrixFilter.js | 4 + src/pixi/filters/DisplacementFilter.js | 61 +- src/pixi/filters/GreyFilter.js | 5 + src/pixi/filters/InvertFilter.js | 4 + src/pixi/filters/PixelateFilter.js | 52 ++ src/pixi/filters/SepiaFilter.js | 5 + src/pixi/filters/SmartBlurFilter.js | 5 + src/pixi/renderers/webgl/PixiShader.js | 44 +- src/pixi/renderers/webgl/PrimitiveShader.js | 57 ++ src/pixi/renderers/webgl/StripShader.js | 65 ++ src/pixi/renderers/webgl/WebGLBatch.js | 6 +- .../renderers/webgl/WebGLFilterManager.js | 107 ++- src/pixi/renderers/webgl/WebGLGraphics.js | 14 +- src/pixi/renderers/webgl/WebGLRenderGroup.js | 56 +- src/pixi/renderers/webgl/WebGLRenderer.js | 23 +- src/pixi/renderers/webgl/WebGLShaders.js | 265 ++---- 40 files changed, 1809 insertions(+), 756 deletions(-) create mode 100644 examples/example 15 - Filters/displacementMAP.jpg rename examples/example 15 - Filters/{displacement_fish1.jpg => displacement_fish1.png} (100%) rename examples/example 15 - Filters/{displacement_fish2.jpg => displacement_fish2.png} (100%) delete mode 100644 examples/example 15 - Filters/displacement_fish3.jpg create mode 100644 examples/example 15 - Filters/displacement_fish3.png rename examples/example 15 - Filters/{displacement_fish4.jpg => displacement_fish4.png} (100%) create mode 100644 examples/example 15 - Filters/displacement_map.jpg create mode 100644 examples/example 15 - Filters/indexAll.html create mode 100644 examples/example 15 - Filters/indexDisplacement.html create mode 100644 examples/example 15 - Filters/indexDisplacement_2.html create mode 100644 examples/example 15 - Filters/zeldaWaves.png create mode 100644 src/pixi/filters/AbstractFilter.js create mode 100644 src/pixi/filters/PixelateFilter.js create mode 100644 src/pixi/renderers/webgl/PrimitiveShader.js create mode 100644 src/pixi/renderers/webgl/StripShader.js diff --git a/Gruntfile.js b/Gruntfile.js index dc63b6d..4d2ffee 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -34,6 +34,8 @@ module.exports = function(grunt) { '<%= dirs.src %>/utils/Polyk.js', '<%= dirs.src %>/renderers/webgl/WebGLShaders.js', '<%= dirs.src %>/renderers/webgl/PixiShader.js', + '<%= dirs.src %>/renderers/webgl/StripShader.js', + '<%= dirs.src %>/renderers/webgl/PrimitiveShader.js', '<%= dirs.src %>/renderers/webgl/WebGLGraphics.js', '<%= dirs.src %>/renderers/webgl/WebGLRenderer.js', '<%= dirs.src %>/renderers/webgl/WebGLBatch.js', @@ -56,10 +58,11 @@ module.exports = function(grunt) { '<%= dirs.src %>/loaders/ImageLoader.js', '<%= dirs.src %>/loaders/BitmapFontLoader.js', '<%= dirs.src %>/loaders/SpineLoader.js', - + '<%= dirs.src %>/filters/AbstractFilter.js', '<%= dirs.src %>/filters/ColorMatrixFilter.js', '<%= dirs.src %>/filters/GreyFilter.js', '<%= dirs.src %>/filters/DisplacementFilter.js', + '<%= dirs.src %>/filters/PixelateFilter.js', '<%= dirs.src %>/filters/BlurXFilter.js', '<%= dirs.src %>/filters/BlurYFilter.js', '<%= dirs.src %>/filters/BlurFilter.js', diff --git a/bin/pixi.dev.js b/bin/pixi.dev.js index 4473b7c..de541ea 100644 --- a/bin/pixi.dev.js +++ b/bin/pixi.dev.js @@ -3686,175 +3686,65 @@ PIXI.PolyK._convex = function(ax, ay, bx, by, cx, cy, sign) */ -/* - * the default suoer fast shader! - */ - -PIXI.shaderFragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", - "gl_FragColor = gl_FragColor * vColor;", - "}" -]; - -PIXI.shaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - - "uniform vec2 projectionVector;", - "uniform vec2 offsetVector;", - "varying vec2 vTextureCoord;", - - "varying float vColor;", - //"const vec2 offsetVector = vec2(1000.0, 0.0);", - "const vec2 center = vec2(-1.0, 1.0);", - "void main(void) {", - "gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" -]; - -/* - * the triangle strip shader.. - */ - -PIXI.stripShaderFragmentSrc = [ - "precision mediump float;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "uniform float alpha;", - "uniform sampler2D uSampler;", - "void main(void) {", - "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", - "gl_FragColor = gl_FragColor * alpha;", - "}" -]; - - -PIXI.stripShaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec2 aTextureCoord;", - "attribute float aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "varying vec2 vTextureCoord;", - "varying float vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vTextureCoord = aTextureCoord;", - "vColor = aColor;", - "}" -]; - -/* - * primitive shader.. - */ - -PIXI.primitiveShaderFragmentSrc = [ - "precision mediump float;", - "varying vec4 vColor;", - "void main(void) {", - "gl_FragColor = vColor;", - "}" -]; - -PIXI.primitiveShaderVertexSrc = [ - "attribute vec2 aVertexPosition;", - "attribute vec4 aColor;", - "uniform mat3 translationMatrix;", - "uniform vec2 projectionVector;", - "uniform vec2 offsetVector;", - "uniform float alpha;", - "varying vec4 vColor;", - "void main(void) {", - "vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);", - "v -= offsetVector.xyx;", - "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", - "vColor = aColor * alpha;", - "}" -]; - -PIXI.shaderStack = []; - -PIXI.initPrimitiveShader = function() +PIXI.initDefaultShaders = function() { - var gl = PIXI.gl; + PIXI.primitiveShader = new PIXI.PrimitiveShader(); + PIXI.primitiveShader.init(); - var shaderProgram = PIXI.compileProgram(PIXI.primitiveShaderVertexSrc, PIXI.primitiveShaderFragmentSrc) - - gl.useProgram(shaderProgram); + PIXI.stripShader = new PIXI.StripShader(); + PIXI.stripShader.init(); - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.offsetVector = gl.getUniformLocation(shaderProgram, "offsetVector"); - - shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); - - - //gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - //gl.enableVertexAttribArray(shaderProgram.colorAttribute); -//gl.enableVertexAttribArray(program.textureCoordAttribute); - - shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); - - PIXI.primitiveProgram = shaderProgram; - - -} - -PIXI.initDefaultShader = function() -{ - PIXI.frameBufferStack = []; - PIXI.frameBufferPool = []; - PIXI.defaultShader = new PIXI.PixiShader(); PIXI.defaultShader.init(); - PIXI.pushShader(PIXI.defaultShader); - - // offset.. - - - - // ok and also create 2 spare frame buffers.. -// PIXI.frameBuffer1 = PIXI.generateFrameBuffer(800, 600); -// PIXI.frameBuffer2 = PIXI.generateFrameBuffer(800, 600); -// PIXI.currentFrameBuffer; - - /* - PIXI.shaderStack.push(PIXI.defaultShader); - PIXI.current*/ + + var gl = PIXI.gl; + var shaderProgram = PIXI.defaultShader.program; + + + gl.useProgram(shaderProgram); + + gl.enableVertexAttribArray(PIXI.defaultShader.aVertexPosition); + gl.enableVertexAttribArray(PIXI.defaultShader.colorAttribute); + gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord); } - -PIXI.initDefaultStripShader = function() +PIXI.activatePrimitiveShader = function() { - var gl = this.gl; - var shaderProgram = PIXI.compileProgram(PIXI.stripShaderVertexSrc, PIXI.stripShaderFragmentSrc) - - gl.useProgram(shaderProgram); + var gl = PIXI.gl; + + gl.useProgram(PIXI.primitiveShader.program); + gl.disableVertexAttribArray(PIXI.defaultShader.aTextureCoord); +} - shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); - shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix"); - shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha"); +PIXI.deactivatePrimitiveShader = function() +{ + var gl = PIXI.gl; - shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor"); - shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector"); - shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); - - PIXI.stripShaderProgram = shaderProgram; + gl.useProgram(PIXI.defaultShader.program); + gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord); } +PIXI.activateStripShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.stripShader.program); + // gl.disableVertexAttribArray(PIXI.defaultShader.aTextureCoord); +} + +PIXI.deactivateStripShader = function() +{ + var gl = PIXI.gl; + + gl.useProgram(PIXI.defaultShader.program); + //gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord); +} + +/* + +SHADER COMPILER HELPERS +*/ + PIXI.CompileVertexShader = function(gl, shaderSrc) { return PIXI._CompileShader(gl, shaderSrc, gl.VERTEX_SHADER); @@ -3873,7 +3763,7 @@ PIXI._CompileShader = function(gl, shaderSrc, shaderType) gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - alert(gl.getShaderInfoLog(shader)); + console.log(gl.getShaderInfoLog(shader)); return null; } @@ -3894,68 +3784,12 @@ PIXI.compileProgram = function(vertexSrc, fragmentSrc) gl.linkProgram(shaderProgram); if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { - alert("Could not initialise shaders"); + console.log("Could not initialise shaders"); } return shaderProgram; } -PIXI.pushShader = function(shader) -{ - var gl = PIXI.gl; - - gl.colorMask(true, true, true, true); - gl.viewport(0, 0, this.width, this.height); - gl.clearColor(0,0,0, 0); - gl.clear(gl.COLOR_BUFFER_BIT); - - PIXI.shaderStack.push(shader); - - var shaderProgram = shader.program; - - // flip! the texture.. - // set the texture! - - // map uniforms.. - gl.useProgram(shaderProgram); - - gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); - gl.enableVertexAttribArray(shaderProgram.colorAttribute); - gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); - - shader.syncUniforms(); - - PIXI.currentShader = shaderProgram; -} - - -PIXI.popShader = function() -{ - var gl = PIXI.gl; - var lastProgram = PIXI.shaderStack.pop(); - - var shaderProgram = PIXI.shaderStack[ PIXI.shaderStack.length-1 ].program; - - gl.useProgram(shaderProgram); - - PIXI.currentShader = shaderProgram; -} - -PIXI.activatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.primitiveProgram); - gl.disableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); -} - -PIXI.deactivatePrimitiveShader = function() -{ - var gl = PIXI.gl; - - gl.useProgram(PIXI.currentShader); - gl.enableVertexAttribArray(PIXI.currentShader.textureCoordAttribute); -} /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -3980,7 +3814,7 @@ PIXI.PixiShader = function() PIXI.PixiShader.prototype.init = function() { - var program = PIXI.compileProgram(this.vertexSrc || PIXI.shaderVertexSrc, this.fragmentSrc) + var program = PIXI.compileProgram(this.vertexSrc || PIXI.PixiShader.defaultVertexSrc, this.fragmentSrc) var gl = PIXI.gl; @@ -3990,28 +3824,24 @@ PIXI.PixiShader.prototype.init = function() this.uSampler = gl.getUniformLocation(program, "uSampler"); this.projectionVector = gl.getUniformLocation(program, "projectionVector"); this.offsetVector = gl.getUniformLocation(program, "offsetVector"); + this.colorAttribute = gl.getAttribLocation(program, "aColor"); //this.dimensions = gl.getUniformLocation(this.program, "dimensions"); // get and store the attributes this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); this.aTextureCoord = gl.getAttribLocation(program, "aTextureCoord"); - - // get the default shader bits! - program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition"); - program.colorAttribute = gl.getAttribLocation(program, "aColor"); - program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord"); - - program.projectionVector = gl.getUniformLocation(program, "projectionVector"); - program.samplerUniform = gl.getUniformLocation(program, "uSampler"); - program.offsetVector = gl.getUniformLocation(program, "offsetVector"); - + // add those custom shaders! for (var key in this.uniforms) { + // get the uniform locations.. program[key] = gl.getUniformLocation(program, key); + + + } - + this.program = program; } @@ -4031,8 +3861,14 @@ PIXI.PixiShader.prototype.syncUniforms = function() } if(type == "f2") { + // console.log(this.program[key]) gl.uniform2f(this.program[key], this.uniforms[key].value.x, this.uniforms[key].value.y); } + else if(type == "f4") + { + // console.log(this.uniforms[key].value) + gl.uniform4fv(this.program[key], this.uniforms[key].value); + } else if(type == "mat4") { gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value); @@ -4055,6 +3891,148 @@ PIXI.PixiShader.prototype.syncUniforms = function() } +PIXI.PixiShader.defaultVertexSrc = [ + "attribute vec2 aVertexPosition;", + "attribute vec2 aTextureCoord;", + "attribute float aColor;", + + "uniform vec2 projectionVector;", + "uniform vec2 offsetVector;", + "varying vec2 vTextureCoord;", + + "varying float vColor;", + + "const vec2 center = vec2(-1.0, 1.0);", + "void main(void) {", + "gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);", + "vTextureCoord = aTextureCoord;", + "vColor = aColor;", + "}" +]; + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.StripShader = function() +{ + // the webGL program.. + this.program; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform float alpha;", + "uniform sampler2D uSampler;", + "void main(void) {", + "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));", + "gl_FragColor = gl_FragColor * alpha;", + "}" + ]; + + this.vertexSrc = [ + "attribute vec2 aVertexPosition;", + "attribute vec2 aTextureCoord;", + "attribute float aColor;", + "uniform mat3 translationMatrix;", + "uniform vec2 projectionVector;", + "varying vec2 vTextureCoord;", + "varying vec2 offsetVector;", + "varying float vColor;", + "void main(void) {", + "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);", + "v -= offsetVector.xyx;", + "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);", + "vTextureCoord = aTextureCoord;", + "vColor = aColor;", + "}" + ]; +} + +PIXI.StripShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc, this.fragmentSrc) + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get and store the uniforms for the shader + this.uSampler = gl.getUniformLocation(program, "uSampler"); + this.projectionVector = gl.getUniformLocation(program, "projectionVector"); + this.offsetVector = gl.getUniformLocation(program, "offsetVector"); + this.colorAttribute = gl.getAttribLocation(program, "aColor"); + //this.dimensions = gl.getUniformLocation(this.program, "dimensions"); + + // get and store the attributes + this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); + this.aTextureCoord = gl.getAttribLocation(program, "aTextureCoord"); + + this.translationMatrix = gl.getUniformLocation(program, "translationMatrix"); + this.alpha = gl.getUniformLocation(program, "alpha"); + + this.program = program; +} + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +PIXI.PrimitiveShader = function() +{ + // the webGL program.. + this.program; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec4 vColor;", + "void main(void) {", + "gl_FragColor = vColor;", + "}" + ]; + + this.vertexSrc = [ + "attribute vec2 aVertexPosition;", + "attribute vec4 aColor;", + "uniform mat3 translationMatrix;", + "uniform vec2 projectionVector;", + "uniform vec2 offsetVector;", + "uniform float alpha;", + "varying vec4 vColor;", + "void main(void) {", + "vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);", + "v -= offsetVector.xyx;", + "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);", + "vColor = aColor * alpha;", + "}" + ]; + +} + +PIXI.PrimitiveShader.prototype.init = function() +{ + var program = PIXI.compileProgram(this.vertexSrc, this.fragmentSrc); + + var gl = PIXI.gl; + + gl.useProgram(program); + + // get and store the uniforms for the shader + this.projectionVector = gl.getUniformLocation(program, "projectionVector"); + this.offsetVector = gl.getUniformLocation(program, "offsetVector"); + this.colorAttribute = gl.getAttribLocation(program, "aColor"); + + // get and store the attributes + this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); + + this.translationMatrix = gl.getUniformLocation(program, "translationMatrix"); + this.alpha = gl.getUniformLocation(program, "alpha"); + + this.program = program; +} /** * @author Mat Groves http://matgroves.com/ @Doormat23 @@ -4113,13 +4091,13 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) // set the matrix transform for the gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + + gl.uniformMatrix3fv(PIXI.primitiveShader.translationMatrix, false, m); - gl.uniformMatrix3fv(PIXI.primitiveProgram.translationMatrix, false, m); - - gl.uniform2f(PIXI.primitiveProgram.projectionVector, projection.x, -projection.y); - gl.uniform2f(PIXI.primitiveProgram.offsetVector, -PIXI.offset.x, -PIXI.offset.y); + gl.uniform2f(PIXI.primitiveShader.projectionVector, projection.x, -projection.y); + gl.uniform2f(PIXI.primitiveShader.offsetVector, -PIXI.offset.x, -PIXI.offset.y); - gl.uniform1f(PIXI.primitiveProgram.alpha, graphics.worldAlpha); + gl.uniform1f(PIXI.primitiveShader.alpha, graphics.worldAlpha); gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer); @@ -4128,8 +4106,8 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection) // its not even used.. but need to be set or it breaks? // only on pc though.. - gl.vertexAttribPointer(PIXI.primitiveProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 4 * 6, 0); - gl.vertexAttribPointer(PIXI.primitiveProgram.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4); + gl.vertexAttribPointer(PIXI.primitiveShader.aVertexPosition, 2, gl.FLOAT, false, 4 * 6, 0); + gl.vertexAttribPointer(PIXI.primitiveShader.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4); // set the index buffer! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer); @@ -4638,16 +4616,18 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) } } - PIXI.initDefaultShader(); - PIXI.initPrimitiveShader(); - PIXI.initDefaultStripShader(); + PIXI.initDefaultShaders(); + - -// PIXI.activateDefaultShader(); + // PIXI.activateDefaultShader(); var gl = this.gl; + + gl.useProgram(PIXI.defaultShader.program); + + PIXI.WebGLRenderer.gl = gl; this.batch = new PIXI.WebGLBatch(gl); @@ -4665,7 +4645,7 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias) this.resize(this.width, this.height); this.contextLost = false; - PIXI.pushShader(PIXI.defaultShader); + //PIXI.pushShader(PIXI.defaultShader); this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl); @@ -4727,15 +4707,6 @@ PIXI.WebGLRenderer.prototype.render = function(stage) this.__stage = stage; this.stageRenderGroup.setRenderable(stage); } - - // TODO not needed now... - // update children if need be - // best to remove first! - /*for (var i=0; i < stage.__childrenRemoved.length; i++) - { - var group = stage.__childrenRemoved[i].__renderGroup - if(group)group.removeDisplayObject(stage.__childrenRemoved[i]); - }*/ // update any textures PIXI.WebGLRenderer.updateTextures(); @@ -5475,7 +5446,7 @@ PIXI.WebGLBatch.prototype.render = function(start, end) //TODO optimize this! - var shaderProgram = PIXI.currentShader; + var shaderProgram = PIXI.defaultShader; //gl.useProgram(shaderProgram); @@ -5483,7 +5454,7 @@ PIXI.WebGLBatch.prototype.render = function(start, end) gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); // ok.. gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + gl.vertexAttribPointer(shaderProgram.aVertexPosition, 2, gl.FLOAT, false, 0, 0); // update the uvs //var isDefault = (shaderProgram == PIXI.shaderProgram) @@ -5495,7 +5466,7 @@ PIXI.WebGLBatch.prototype.render = function(start, end) gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvs); } - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); + gl.vertexAttribPointer(shaderProgram.aTextureCoord, 2, gl.FLOAT, false, 0, 0); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, this.texture._glTexture); @@ -5584,7 +5555,7 @@ PIXI.WebGLRenderGroup.prototype.render = function(projection, buffer) PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + gl.uniform2f(PIXI.defaultShader.projectionVector, projection.x, projection.y); this.filterManager.begin(projection, buffer); @@ -5622,14 +5593,10 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project PIXI.WebGLRenderer.updateTextures(); var gl = this.gl; - gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); + gl.uniform2f(PIXI.defaultShader.projectionVector, projection.x, projection.y); this.filterManager.begin(projection, buffer); - //console.log(buffer) - - //gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y); - // to do! // render part of the scene... @@ -5717,7 +5684,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project endBatch = lastRenderable; } - console.log(endBatch); + //console.log(endBatch); // TODO - need to fold this up a bit! if(startBatch == endBatch) @@ -5783,7 +5750,6 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project */ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection) { - var sta = PIXI.shaderStack.length; var worldVisible = renderable.vcount === PIXI.visibleCount @@ -6374,21 +6340,26 @@ PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite) PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) { var gl = this.gl; - var shaderProgram = PIXI.stripShaderProgram; - - - gl.useProgram(shaderProgram); + PIXI.activateStripShader(); + + var shader = PIXI.stripShader; + + var program = shader.program; + var m = PIXI.mat3.clone(strip.worldTransform); PIXI.mat3.transpose(m); +// console.log(projection) // set the matrix transform for the - gl.uniformMatrix3fv(shaderProgram.translationMatrix, false, m); - gl.uniform2f(shaderProgram.projectionVector, projection.x, projection.y); - gl.uniform1f(shaderProgram.alpha, strip.worldAlpha); + gl.uniformMatrix3fv(shader.translationMatrix, false, m); + gl.uniform2f(shader.projectionVector, projection.x, projection.y); + gl.uniform2f(shader.offsetVector, -PIXI.offset.x, -PIXI.offset.y); + + gl.uniform1f(shader.alpha, strip.worldAlpha); -/* + /* if(strip.blendMode == PIXI.blendModes.NORMAL) { gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); @@ -6399,23 +6370,22 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) } */ - + //console.log("!!") if(!strip.dirty) - { - + { gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); gl.bufferSubData(gl.ARRAY_BUFFER, 0, strip.verticies) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0); // update the uvs gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); + gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); + gl.vertexAttribPointer(shader.colorAttribute, 1, gl.FLOAT, false, 0, 0); // dont need to upload! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); @@ -6425,19 +6395,19 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) strip.dirty = false; gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0); + gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0); // update the uvs gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer); gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); + gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture); - + // console.log(strip.texture.baseTexture._glTexture) gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW) - gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0); + gl.vertexAttribPointer(shader.colorAttribute, 1, gl.FLOAT, false, 0, 0); // dont need to upload! gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer); @@ -6447,7 +6417,8 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0); - gl.useProgram(PIXI.currentProgram); + PIXI.deactivateStripShader(); + //gl.useProgram(PIXI.currentProgram); } /** @@ -6461,6 +6432,8 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection) PIXI.WebGLRenderGroup.prototype.renderTilingSprite = function(sprite, projectionMatrix) { var gl = this.gl; + + var shaderProgram = PIXI.shaderProgram; var tilePosition = sprite.tilePosition; @@ -6573,11 +6546,29 @@ PIXI.WebGLFilterManager.prototype.pushFilter = function(filterBlock) gl.bindTexture(gl.TEXTURE_2D, texture.texture); this.getBounds(filterBlock.target); - + + // addpadding? + //displayObject.filterArea.x + var filterArea = filterBlock.target.filterArea; + + var padidng = filter.padding; + filterArea.x -= padidng; + filterArea.y -= padidng; + filterArea.width += padidng * 2; + filterArea.height += padidng * 2; + + // cap filter to screen size.. + if(filterArea.x < 0)filterArea.x = 0; + if(filterArea.width > this.width)filterArea.width = this.width; + if(filterArea.y < 0)filterArea.y = 0; + if(filterArea.height > this.height)filterArea.height = this.height; + + //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, filterArea.width, filterArea.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); gl.bindFramebuffer(gl.FRAMEBUFFER, texture.frameBuffer); + // console.log(filterArea) // set view port gl.viewport(0, 0, filterArea.width, filterArea.height); @@ -6587,9 +6578,10 @@ PIXI.WebGLFilterManager.prototype.pushFilter = function(filterBlock) PIXI.offset.x = -filterArea.x; PIXI.offset.y = -filterArea.y; + //console.log(PIXI.defaultShader.projectionVector) // update projection - gl.uniform2f(PIXI.currentShader.projectionVector, filterArea.width/2, -filterArea.height/2); - gl.uniform2f(PIXI.currentShader.offsetVector, -filterArea.x, -filterArea.y); + gl.uniform2f(PIXI.defaultShader.projectionVector, filterArea.width/2, -filterArea.height/2); + gl.uniform2f(PIXI.defaultShader.offsetVector, -filterArea.x, -filterArea.y); //PIXI.primitiveProgram gl.colorMask(true, true, true, true); @@ -6668,7 +6660,9 @@ PIXI.WebGLFilterManager.prototype.popFilter = function() gl.bindTexture(gl.TEXTURE_2D, inputTexture.texture); // draw texture.. - this.applyFilterPass(filterPass, filterArea.width, filterArea.height); + //filterPass.applyFilterPass(filterArea.width, filterArea.height); + this.applyFilterPass(filterPass, filterArea, filterArea.width, filterArea.height); + // swap the textures.. var temp = inputTexture; inputTexture = outputTexture; @@ -6765,19 +6759,20 @@ PIXI.WebGLFilterManager.prototype.popFilter = function() gl.bindTexture(gl.TEXTURE_2D, texture.texture); // apply! - this.applyFilterPass(filter, sizeX, sizeY); + //filter.applyFilterPass(sizeX, sizeY); + this.applyFilterPass(filter, filterArea, sizeX, sizeY); // now restore the regular shader.. gl.useProgram(PIXI.defaultShader.program); - gl.uniform2f(PIXI.currentShader.projectionVector, sizeX/2, -sizeY/2); - gl.uniform2f(PIXI.currentShader.offsetVector, -offsetX, -offsetY); + gl.uniform2f(PIXI.defaultShader.projectionVector, sizeX/2, -sizeY/2); + gl.uniform2f(PIXI.defaultShader.offsetVector, -offsetX, -offsetY); // return the texture to the pool this.texturePool.push(texture); filterBlock._glFilterTexture = null; } -PIXI.WebGLFilterManager.prototype.applyFilterPass = function(filter, width, height) +PIXI.WebGLFilterManager.prototype.applyFilterPass = function(filter, filterArea, width, height) { // use program var gl = PIXI.gl; @@ -6801,6 +6796,16 @@ PIXI.WebGLFilterManager.prototype.applyFilterPass = function(filter, width, heig gl.uniform2f(shader.projectionVector, width/2, -height/2); gl.uniform2f(shader.offsetVector, 0,0) + if(filter.uniforms.dimensions) + { + //console.log(filter.uniforms.dimensions) + filter.uniforms.dimensions.value[0] = this.width;//width; + filter.uniforms.dimensions.value[1] = this.height;//height; + filter.uniforms.dimensions.value[2] = this.vertexArray[0]; + filter.uniforms.dimensions.value[3] = this.vertexArray[5];//filterArea.height; + // console.log(this.vertexArray[5]) + } + shader.syncUniforms(); gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); @@ -6877,38 +6882,41 @@ PIXI.WebGLFilterManager.prototype.getBounds = function(displayObject) { // TODO can be optimized! - what if there is no scale / rotation? - if(tempObject instanceof PIXI.Sprite) + if(tempObject.visible) { - width = tempObject.texture.frame.width; - height = tempObject.texture.frame.height; + if(tempObject instanceof PIXI.Sprite) + { + width = tempObject.texture.frame.width; + height = tempObject.texture.frame.height; - // TODO trim?? - aX = tempObject.anchor.x; - aY = tempObject.anchor.y; - w0 = width * (1-aX); - w1 = width * -aX; + // TODO trim?? + aX = tempObject.anchor.x; + aY = tempObject.anchor.y; + w0 = width * (1-aX); + w1 = width * -aX; - h0 = height * (1-aY); - h1 = height * -aY; + h0 = height * (1-aY); + h1 = height * -aY; - doTest = true; - } - else if(tempObject instanceof PIXI.Graphics) - { - tempObject.updateFilterBounds(); + doTest = true; + } + else if(tempObject instanceof PIXI.Graphics) + { + tempObject.updateFilterBounds(); - var bounds = tempObject.bounds; + var bounds = tempObject.bounds; - width = bounds.width; - height = bounds.height; + width = bounds.width; + height = bounds.height; - w0 = bounds.x - w1 = bounds.x + bounds.width; + w0 = bounds.x + w1 = bounds.x + bounds.width; - h0 = bounds.y - h1 = bounds.y + bounds.height; + h0 = bounds.y + h1 = bounds.y + bounds.height; - doTest = true; + doTest = true; + } } if(doTest) @@ -6957,18 +6965,18 @@ PIXI.WebGLFilterManager.prototype.getBounds = function(displayObject) doTest = false; tempObject = tempObject._iNext; + } while(tempObject != testObject) // maximum bounds is the size of the screen.. - minX = minX > 0 ? minX : 0; - minY = minY > 0 ? minY : 0; - - maxX = maxX < this.width ? maxX : this.width; - maxY = maxY < this.height ? maxY : this.height; + //minX = minX > 0 ? minX : 0; + //minY = minY > 0 ? minY : 0; displayObject.filterArea.x = minX; displayObject.filterArea.y = minY; + +// console.log(maxX+ " : " + minX) displayObject.filterArea.width = maxX - minX; displayObject.filterArea.height = maxY - minY; } @@ -11217,12 +11225,33 @@ PIXI.SpineLoader.prototype.onLoaded = function () { }; +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + + +PIXI.AbstractFilter = function(fragmentSrc, unifroms) +{ + this.passes = [this]; + this.dirty = true; + this.padding = 0; + + // set the uniforms + this.uniforms = unifroms || {}; + + this.fragmentSrc = fragmentSrc || []; +} + + /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ PIXI.ColorMatrixFilter = function() { + PIXI.AbstractFilter.call( this ); + this.passes = [this]; // set the uniforms @@ -11248,6 +11277,8 @@ PIXI.ColorMatrixFilter = function() } +PIXI.ColorMatrixFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); +PIXI.ColorMatrixFilter.prototype.constructor = PIXI.ColorMatrixFilter; Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { get: function() { @@ -11265,6 +11296,8 @@ Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { PIXI.GreyFilter = function() { + PIXI.AbstractFilter.call( this ); + this.passes = [this]; // set the uniforms @@ -11286,6 +11319,9 @@ PIXI.GreyFilter = function() ]; } +PIXI.GreyFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); +PIXI.GreyFilter.prototype.constructor = PIXI.GreyFilter; + Object.defineProperty(PIXI.GreyFilter.prototype, 'grey', { get: function() { return this.uniforms.grey.value; @@ -11303,16 +11339,35 @@ Object.defineProperty(PIXI.GreyFilter.prototype, 'grey', { PIXI.DisplacementFilter = function(texture) { + PIXI.AbstractFilter.call( this ); + this.passes = [this]; - + texture.baseTexture._powerOf2 = true; + + // set the uniforms - + //console.log() this.uniforms = { displacementMap: {type: 'sampler2D', value:texture}, scale: {type: 'f2', value:{x:30, y:30}}, - mapDimensions: {type: 'f2', value:{x:texture.width, y:texture.height}} + offset: {type: 'f2', value:{x:0, y:0}}, + mapDimensions: {type: 'f2', value:{x:1, y:5112}}, + dimensions: {type: 'f4', value:[0,0,0,0]} }; + + if(texture.baseTexture.hasLoaded) + { + this.uniforms.mapDimensions.value.x = texture.width; + this.uniforms.mapDimensions.value.y = texture.height; + } + else + { + this.boundLoadedFunction = this.onTextureLoaded.bind(this); + + texture.baseTexture.on("loaded", this.boundLoadedFunction); + } + this.fragmentSrc = [ "precision mediump float;", "varying vec2 vTextureCoord;", @@ -11320,20 +11375,26 @@ PIXI.DisplacementFilter = function(texture) "uniform sampler2D displacementMap;", "uniform sampler2D uSampler;", "uniform vec2 scale;", + "uniform vec2 offset;", + "uniform vec4 dimensions;", "uniform vec2 mapDimensions;",// = vec2(256.0, 256.0);", - "const vec2 textureDimensions = vec2(800.0, 600.0);", + // "const vec2 textureDimensions = vec2(750.0, 750.0);", "void main(void) {", "vec2 mapCords = vTextureCoord.xy;", // "mapCords -= ;", - // "mapCords.y *= -1.0;", - // "mapCords.y += 1.0;", + "mapCords += (dimensions.zw + offset)/ dimensions.xy ;", + "mapCords.y *= -1.0;", + "mapCords.y += 1.0;", "vec2 matSample = texture2D(displacementMap, mapCords).xy;", "matSample -= 0.5;", "matSample *= scale;", - "matSample /= textureDimensions;", + "matSample /= mapDimensions;", "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x + matSample.x, vTextureCoord.y + matSample.y));", "gl_FragColor.rgb = mix( gl_FragColor.rgb, gl_FragColor.rgb, 1.0);", + "vec2 cord = vTextureCoord;", + + //"gl_FragColor = texture2D(displacementMap, cord);", "gl_FragColor = gl_FragColor * vColor;", "}" @@ -11341,6 +11402,19 @@ PIXI.DisplacementFilter = function(texture) } +PIXI.DisplacementFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); +PIXI.DisplacementFilter.prototype.constructor = PIXI.DisplacementFilter; + +PIXI.DisplacementFilter.prototype.onTextureLoaded = function() +{ + + this.uniforms.mapDimensions.value.x = this.uniforms.displacementMap.value.width; + this.uniforms.mapDimensions.value.y = this.uniforms.displacementMap.value.height; + + this.uniforms.displacementMap.value.baseTexture.off("loaded", this.boundLoadedFunction) + +} + Object.defineProperty(PIXI.DisplacementFilter.prototype, 'map', { get: function() { return this.uniforms.displacementMap.value; @@ -11358,6 +11432,67 @@ Object.defineProperty(PIXI.DisplacementFilter.prototype, 'scale', { this.uniforms.scale.value = value; } }); + +Object.defineProperty(PIXI.DisplacementFilter.prototype, 'offset', { + get: function() { + return this.uniforms.offset.value; + }, + set: function(value) { + this.uniforms.offset.value = value; + } +}); +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +PIXI.PixelateFilter = function() +{ + PIXI.AbstractFilter.call( this ); + + this.passes = [this]; + + // set the uniforms + this.uniforms = { + invert: {type: 'f', value: 0}, + dimensions: {type: 'f4', value:new Float32Array([10000, 100, 10, 10])}, + pixelSize: {type: 'f2', value:{x:10, y:10}}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform vec2 testDim;", + "uniform vec4 dimensions;", + "uniform vec2 pixelSize;", + "uniform sampler2D uSampler;", + "void main(void) {", + "vec2 coord = vTextureCoord;", + + // "vec2 dim = testDim;", + "vec2 size = dimensions.xy/pixelSize;", + + "vec2 color = floor( ( vTextureCoord * size ) ) / size + pixelSize/dimensions.xy * 0.5;", + // "color += (mod(dimensions.xy, size)/dimensions.zw;", + "gl_FragColor = texture2D(uSampler, color);", + "}" + ]; + + +} + +PIXI.PixelateFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); +PIXI.PixelateFilter.prototype.constructor = PIXI.PixelateFilter; + +Object.defineProperty(PIXI.PixelateFilter.prototype, 'size', { + get: function() { + return this.uniforms.pixelSize.value; + }, + set: function(value) { + this.dirty = true; + this.uniforms.pixelSize.value = value; + } +}); /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ @@ -11366,6 +11501,8 @@ Object.defineProperty(PIXI.DisplacementFilter.prototype, 'scale', { PIXI.BlurXFilter = function() { + PIXI.AbstractFilter.call( this ); + this.passes = [this]; // set the uniforms @@ -11398,12 +11535,18 @@ PIXI.BlurXFilter = function() ]; } +PIXI.BlurXFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); +PIXI.BlurXFilter.prototype.constructor = PIXI.BlurXFilter; + + Object.defineProperty(PIXI.BlurXFilter.prototype, 'blur', { get: function() { - return this.uniforms.blur.value; + return this.uniforms.blur.value / (1/7000); }, set: function(value) { - this.uniforms.blur.value = value; + + this.dirty = true; + this.uniforms.blur.value = (1/7000) * value; } }); @@ -11415,6 +11558,8 @@ Object.defineProperty(PIXI.BlurXFilter.prototype, 'blur', { PIXI.BlurYFilter = function() { + PIXI.AbstractFilter.call( this ); + this.passes = [this]; // set the uniforms @@ -11447,12 +11592,16 @@ PIXI.BlurYFilter = function() ]; } +PIXI.BlurYFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); +PIXI.BlurYFilter.prototype.constructor = PIXI.BlurYFilter; + Object.defineProperty(PIXI.BlurYFilter.prototype, 'blur', { get: function() { - return this.uniforms.blur.value; + return this.uniforms.blur.value / (1/7000); }, set: function(value) { - this.uniforms.blur.value = value; + //this.padding = value; + this.uniforms.blur.value = (1/7000) * value; } }); @@ -11464,7 +11613,7 @@ Object.defineProperty(PIXI.BlurYFilter.prototype, 'blur', { PIXI.BlurFilter = function() { - + this.blurXFilter = new PIXI.BlurXFilter(); this.blurYFilter = new PIXI.BlurYFilter(); @@ -11506,6 +11655,8 @@ Object.defineProperty(PIXI.BlurFilter.prototype, 'blurY', { PIXI.InvertFilter = function() { + PIXI.AbstractFilter.call( this ); + this.passes = [this]; // set the uniforms @@ -11529,6 +11680,8 @@ PIXI.InvertFilter = function() } +PIXI.InvertFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); +PIXI.InvertFilter.prototype.constructor = PIXI.InvertFilter; Object.defineProperty(PIXI.InvertFilter.prototype, 'invert', { get: function() { @@ -11547,6 +11700,8 @@ Object.defineProperty(PIXI.InvertFilter.prototype, 'invert', { PIXI.SepiaFilter = function() { + PIXI.AbstractFilter.call( this ); + this.passes = [this]; // set the uniforms @@ -11571,6 +11726,9 @@ PIXI.SepiaFilter = function() } +PIXI.SepiaFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); +PIXI.SepiaFilter.prototype.constructor = PIXI.SepiaFilter; + Object.defineProperty(PIXI.SepiaFilter.prototype, 'sepia', { get: function() { return this.uniforms.sepia.value; diff --git a/bin/pixi.dev.js.map b/bin/pixi.dev.js.map index 4df448c..80d0cf8 100644 --- a/bin/pixi.dev.js.map +++ b/bin/pixi.dev.js.map @@ -25,6 +25,8 @@ "src/pixi/utils/Polyk.js", "src/pixi/renderers/webgl/WebGLShaders.js", "src/pixi/renderers/webgl/PixiShader.js", + "src/pixi/renderers/webgl/StripShader.js", + "src/pixi/renderers/webgl/PrimitiveShader.js", "src/pixi/renderers/webgl/WebGLGraphics.js", "src/pixi/renderers/webgl/WebGLRenderer.js", "src/pixi/renderers/webgl/WebGLBatch.js", @@ -47,9 +49,11 @@ "src/pixi/loaders/ImageLoader.js", "src/pixi/loaders/BitmapFontLoader.js", "src/pixi/loaders/SpineLoader.js", + "src/pixi/filters/AbstractFilter.js", "src/pixi/filters/ColorMatrixFilter.js", "src/pixi/filters/GreyFilter.js", "src/pixi/filters/DisplacementFilter.js", + "src/pixi/filters/PixelateFilter.js", "src/pixi/filters/BlurXFilter.js", "src/pixi/filters/BlurYFilter.js", "src/pixi/filters/BlurFilter.js", @@ -58,6 +62,6 @@ "src/pixi/Outro.js" ], "names": [], - "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sB;AC9jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;AClRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACngBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1+BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACjeA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACn7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACpKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACvCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC9DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACrCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,c", + "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sB;AC9jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACngBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5+BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACpgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACn7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACpKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC3CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC7GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,c", "sourceRoot": "../" } \ No newline at end of file diff --git a/bin/pixi.js b/bin/pixi.js index f89ea8c..06a68b4 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -4,12 +4,12 @@ * Copyright (c) 2012, Mat Groves * http://goodboydigital.com/ * - * Compiled: 2013-10-30 + * Compiled: 2013-11-01 * * Pixi.JS is licensed under the MIT License. * http://www.opensource.org/licenses/mit-license.php */ -!function(){function c(){return f.Matrix="undefined"!=typeof Float32Array?Float32Array:Array,f.Matrix}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}var e=this,f=f||{};f.Point=function(a,b){this.x=a||0,this.y=b||0},f.Point.prototype.clone=function(){return new f.Point(this.x,this.y)},f.Point.prototype.constructor=f.Point,f.Rectangle=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Rectangle.prototype.clone=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Rectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},f.Rectangle.prototype.constructor=f.Rectangle,f.Polygon=function(a){if(a instanceof Array||(a=Array.prototype.slice.call(arguments)),"number"==typeof a[0]){for(var b=[],c=0,d=a.length;d>c;c+=2)b.push(new f.Point(a[c],a[c+1]));a=b}this.points=a},f.Polygon.prototype.clone=function(){for(var a=[],b=0;bb!=i>b&&(h-f)*(b-g)/(i-g)+f>a;j&&(c=!c)}return c},f.Polygon.prototype.constructor=f.Polygon,f.Circle=function(a,b,c){this.x=a||0,this.y=b||0,this.radius=c||0},f.Circle.prototype.clone=function(){return new f.Circle(this.x,this.y,this.radius)},f.Circle.prototype.contains=function(a,b){if(this.radius<=0)return!1;var c=this.x-a,d=this.y-b,e=this.radius*this.radius;return c*=c,d*=d,e>=c+d},f.Circle.prototype.constructor=f.Circle,f.Ellipse=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Ellipse.prototype.clone=function(){return new f.Ellipse(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=(a-this.x)/this.width-.5,d=(b-this.y)/this.height-.5;return c*=c,d*=d,.25>c+d},f.Ellipse.getBounds=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.constructor=f.Ellipse,c(),f.mat3={},f.mat3.create=function(){var a=new f.Matrix(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat3.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat4={},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat3.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=b[0],n=b[1],o=b[2],p=b[3],q=b[4],r=b[5],s=b[6],t=b[7],u=b[8];return c[0]=m*d+n*g+o*j,c[1]=m*e+n*h+o*k,c[2]=m*f+n*i+o*l,c[3]=p*d+q*g+r*j,c[4]=p*e+q*h+r*k,c[5]=p*f+q*i+r*l,c[6]=s*d+t*g+u*j,c[7]=s*e+t*h+u*k,c[8]=s*f+t*i+u*l,c},f.mat3.clone=function(a){var b=new f.Matrix(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},f.mat3.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[5];return a[1]=a[3],a[2]=a[6],a[3]=c,a[5]=a[7],a[6]=d,a[7]=e,a}return b[0]=a[0],b[1]=a[3],b[2]=a[6],b[3]=a[1],b[4]=a[4],b[5]=a[7],b[6]=a[2],b[7]=a[5],b[8]=a[8],b},f.mat3.toMat4=function(a,b){return b||(b=f.mat4.create()),b[15]=1,b[14]=0,b[13]=0,b[12]=0,b[11]=0,b[10]=a[8],b[9]=a[7],b[8]=a[6],b[7]=0,b[6]=a[5],b[5]=a[4],b[4]=a[3],b[3]=0,b[2]=a[2],b[1]=a[1],b[0]=a[0],b},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat4.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[3],f=a[6],g=a[7],h=a[11];return a[1]=a[4],a[2]=a[8],a[3]=a[12],a[4]=c,a[6]=a[9],a[7]=a[13],a[8]=d,a[9]=f,a[11]=a[14],a[12]=e,a[13]=g,a[14]=h,a}return b[0]=a[0],b[1]=a[4],b[2]=a[8],b[3]=a[12],b[4]=a[1],b[5]=a[5],b[6]=a[9],b[7]=a[13],b[8]=a[2],b[9]=a[6],b[10]=a[10],b[11]=a[14],b[12]=a[3],b[13]=a[7],b[14]=a[11],b[15]=a[15],b},f.mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=b[0],u=b[1],v=b[2],w=b[3];return c[0]=t*d+u*h+v*l+w*p,c[1]=t*e+u*i+v*m+w*q,c[2]=t*f+u*j+v*n+w*r,c[3]=t*g+u*k+v*o+w*s,t=b[4],u=b[5],v=b[6],w=b[7],c[4]=t*d+u*h+v*l+w*p,c[5]=t*e+u*i+v*m+w*q,c[6]=t*f+u*j+v*n+w*r,c[7]=t*g+u*k+v*o+w*s,t=b[8],u=b[9],v=b[10],w=b[11],c[8]=t*d+u*h+v*l+w*p,c[9]=t*e+u*i+v*m+w*q,c[10]=t*f+u*j+v*n+w*r,c[11]=t*g+u*k+v*o+w*s,t=b[12],u=b[13],v=b[14],w=b[15],c[12]=t*d+u*h+v*l+w*p,c[13]=t*e+u*i+v*m+w*q,c[14]=t*f+u*j+v*n+w*r,c[15]=t*g+u*k+v*o+w*s,c},f.DisplayObject=function(){this.last=this,this.first=this,this.position=new f.Point,this.scale=new f.Point(1,1),this.pivot=new f.Point(0,0),this.rotation=0,this.alpha=1,this.visible=!0,this.hitArea=null,this.buttonMode=!1,this.renderable=!1,this.parent=null,this.stage=null,this.worldAlpha=1,this._interactive=!1,this.worldTransform=f.mat3.create(),this.localTransform=f.mat3.create(),this.color=[],this.dynamic=!0,this._sr=0,this._cr=1,this.filterArea=new f.Rectangle(0,0,1,1)},f.DisplayObject.prototype.constructor=f.DisplayObject,f.DisplayObject.prototype.setInteractive=function(a){this.interactive=a},Object.defineProperty(f.DisplayObject.prototype,"interactive",{get:function(){return this._interactive},set:function(a){this._interactive=a,this.stage&&(this.stage.dirty=!0)}}),Object.defineProperty(f.DisplayObject.prototype,"mask",{get:function(){return this._mask},set:function(a){a?this._mask?(a.start=this._mask.start,a.end=this._mask.end):(this.addFilter(a),a.renderable=!1):(this.removeFilter(this._mask),this._mask.renderable=!0),this._mask=a}}),Object.defineProperty(f.DisplayObject.prototype,"filters",{get:function(){return this._filters},set:function(a){if(a){this._filters&&this.removeFilter(this._filters),this.addFilter(a);for(var b=[],c=0;c=0&&b<=this.children.length))throw new Error(a+" The index "+b+" supplied is out of bounds "+this.children.length);if(void 0!=a.parent&&a.parent.removeChild(a),a.parent=this,this.stage){var c=a;do c.interactive&&(this.stage.dirty=!0),c.stage=this.stage,c=c._iNext;while(c)}var d,e,f=a.first,g=a.last;if(b==this.children.length){e=this.last;for(var h=this,i=this.last;h;)h.last==i&&(h.last=a.last),h=h.parent}else e=0==b?this:this.children[b-1].last;d=e._iNext,d&&(d._iPrev=g,g._iNext=d),f._iPrev=e,e._iNext=f,this.children.splice(b,0,a),this.__renderGroup&&(a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a),this.__renderGroup.addDisplayObjectAndChildren(a))},f.DisplayObjectContainer.prototype.swapChildren=function(){},f.DisplayObjectContainer.prototype.getChildAt=function(a){if(a>=0&&aa;a++)this.children[a].updateTransform()}},f.blendModes={},f.blendModes.NORMAL=0,f.blendModes.SCREEN=1,f.Sprite=function(a){f.DisplayObjectContainer.call(this),this.anchor=new f.Point,this.texture=a,this.blendMode=f.blendModes.NORMAL,this._width=0,this._height=0,a.baseTexture.hasLoaded?this.updateFrame=!0:(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Sprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Sprite.prototype.constructor=f.Sprite,Object.defineProperty(f.Sprite.prototype,"width",{get:function(){return this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(f.Sprite.prototype,"height",{get:function(){return this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),f.Sprite.prototype.setTexture=function(a){this.texture.baseTexture!=a.baseTexture?(this.textureChange=!0,this.texture=a,this.__renderGroup&&this.__renderGroup.updateTexture(this)):this.texture=a,this.updateFrame=!0},f.Sprite.prototype.onTextureUpdate=function(){this._width&&(this.scale.x=this._width/this.texture.frame.width),this._height&&(this.scale.y=this._height/this.texture.frame.height),this.updateFrame=!0},f.Sprite.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache"+this);return new f.Sprite(b)},f.Sprite.fromImage=function(a){var b=f.Texture.fromImage(a);return new f.Sprite(b)},f.MovieClip=function(a){f.Sprite.call(this,a[0]),this.textures=a,this.animationSpeed=1,this.loop=!0,this.onComplete=null,this.currentFrame=0,this.playing=!1},f.MovieClip.prototype=Object.create(f.Sprite.prototype),f.MovieClip.prototype.constructor=f.MovieClip,Object.defineProperty(f.MovieClip.prototype,"totalFrames",{get:function(){return this.textures.length}}),f.MovieClip.prototype.stop=function(){this.playing=!1},f.MovieClip.prototype.play=function(){this.playing=!0},f.MovieClip.prototype.gotoAndStop=function(a){this.playing=!1,this.currentFrame=a;var b=0|this.currentFrame+.5;this.setTexture(this.textures[b%this.textures.length])},f.MovieClip.prototype.gotoAndPlay=function(a){this.currentFrame=a,this.playing=!0},f.MovieClip.prototype.updateTransform=function(){if(f.Sprite.prototype.updateTransform.call(this),this.playing){this.currentFrame+=this.animationSpeed;var a=0|this.currentFrame+.5;this.loop||a=this.textures.length&&(this.gotoAndStop(this.textures.length-1),this.onComplete&&this.onComplete())}},f.FilterBlock=function(){this.visible=!0,this.renderable=!0},f.Text=function(a,b){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),f.Sprite.call(this,f.Texture.fromCanvas(this.canvas)),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.Text.prototype=Object.create(f.Sprite.prototype),f.Text.prototype.constructor=f.Text,f.Text.prototype.setStyle=function(a){a=a||{},a.font=a.font||"bold 20pt Arial",a.fill=a.fill||"black",a.align=a.align||"left",a.stroke=a.stroke||"black",a.strokeThickness=a.strokeThickness||0,a.wordWrap=a.wordWrap||!1,a.wordWrapWidth=a.wordWrapWidth||100,this.style=a,this.dirty=!0},f.Text.prototype.setText=function(a){this.text=a.toString()||" ",this.dirty=!0},f.Text.prototype.updateText=function(){this.context.font=this.style.font;var a=this.text;this.style.wordWrap&&(a=this.wordWrap(this.text));for(var b=a.split(/(?:\r\n|\r|\n)/),c=[],d=0,e=0;ee?f:arguments.callee(a,b,f,d,e):arguments.callee(a,b,c,f,e)},c=function(a,c,d){if(a.measureText(c).width<=d||c.length<1)return c;var e=b(a,c,0,c.length,d);return c.substring(0,e)+"\n"+arguments.callee(a,c.substring(e),d)},d="",e=a.split("\n"),f=0;f=2?parseInt(b[b.length-2],10):f.BitmapText.fonts[this.fontName].size,this.dirty=!0},f.BitmapText.prototype.updateText=function(){for(var a=f.BitmapText.fonts[this.fontName],b=new f.Point,c=null,d=[],e=0,g=[],h=0,i=this.fontSize/a.size,j=0;j=j;j++){var n=0;"right"==this.style.align?n=e-g[j]:"center"==this.style.align&&(n=(e-g[j])/2),m.push(n)}for(j=0;j0;)this.removeChild(this.getChildAt(0));this.updateText(),this.dirty=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.BitmapText.fonts={},f.InteractionManager=function(a){this.stage=a,this.mouse=new f.InteractionData,this.touchs={},this.tempPoint=new f.Point,this.mouseoverEnabled=!0,this.pool=[],this.interactiveItems=[],this.interactionDOMElement=null,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseOut=this.onMouseOut.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.last=0},f.InteractionManager.prototype.constructor=f.InteractionManager,f.InteractionManager.prototype.collectInteractiveSprite=function(a,b){for(var c=a.children,d=c.length,e=d-1;e>=0;e--){var f=c[e];f.interactive?(b.interactiveChildren=!0,this.interactiveItems.push(f),f.children.length>0&&this.collectInteractiveSprite(f,f)):(f.__iParent=null,f.children.length>0&&this.collectInteractiveSprite(f,b))}},f.InteractionManager.prototype.setTarget=function(a){this.target=a,null===this.interactionDOMElement&&this.setTargetDomElement(a.view),document.body.addEventListener("mouseup",this.onMouseUp,!0)},f.InteractionManager.prototype.setTargetDomElement=function(a){null!==this.interactionDOMElement&&(this.interactionDOMElement.style["-ms-content-zooming"]="",this.interactionDOMElement.style["-ms-touch-action"]="",this.interactionDOMElement.removeEventListener("mousemove",this.onMouseMove,!0),this.interactionDOMElement.removeEventListener("mousedown",this.onMouseDown,!0),this.interactionDOMElement.removeEventListener("mouseout",this.onMouseOut,!0),this.interactionDOMElement.removeEventListener("touchstart",this.onTouchStart,!0),this.interactionDOMElement.removeEventListener("touchend",this.onTouchEnd,!0),this.interactionDOMElement.removeEventListener("touchmove",this.onTouchMove,!0)),window.navigator.msPointerEnabled&&(a.style["-ms-content-zooming"]="none",a.style["-ms-touch-action"]="none"),this.interactionDOMElement=a,a.addEventListener("mousemove",this.onMouseMove,!0),a.addEventListener("mousedown",this.onMouseDown,!0),a.addEventListener("mouseout",this.onMouseOut,!0),a.addEventListener("touchstart",this.onTouchStart,!0),a.addEventListener("touchend",this.onTouchEnd,!0),a.addEventListener("touchmove",this.onTouchMove,!0)},f.InteractionManager.prototype.update=function(){if(this.target){var a=Date.now(),b=a-this.last;if(b=30*b/1e3,!(1>b)){if(this.last=a,this.dirty){this.dirty=!1;for(var c=this.interactiveItems.length,d=0;c>d;d++)this.interactiveItems[d].interactiveChildren=!1;this.interactiveItems=[],this.stage.interactive&&this.interactiveItems.push(this.stage),this.collectInteractiveSprite(this.stage,this.stage)}var e=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var d=0;e>d;d++){var f=this.interactiveItems[d];(f.mouseover||f.mouseout||f.buttonMode)&&(f.__hit=this.hitTest(f,this.mouse),this.mouse.target=f,f.__hit?(f.buttonMode&&(this.interactionDOMElement.style.cursor="pointer"),f.__isOver||(f.mouseover&&f.mouseover(this.mouse),f.__isOver=!0)):f.__isOver&&(f.mouseout&&f.mouseout(this.mouse),f.__isOver=!1))}}}},f.InteractionManager.prototype.onMouseMove=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactionDOMElement.getBoundingClientRect();this.mouse.global.x=(a.clientX-b.left)*(this.target.width/b.width),this.mouse.global.y=(a.clientY-b.top)*(this.target.height/b.height);var c=this.interactiveItems.length;this.mouse.global;for(var d=0;c>d;d++){var e=this.interactiveItems[d];e.mousemove&&e.mousemove(this.mouse)}},f.InteractionManager.prototype.onMouseDown=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactiveItems.length;this.mouse.global,this.stage;for(var c=0;b>c;c++){var d=this.interactiveItems[c];if((d.mousedown||d.click)&&(d.__mouseIsDown=!0,d.__hit=this.hitTest(d,this.mouse),d.__hit&&(d.mousedown&&d.mousedown(this.mouse),d.__isDown=!0,!d.interactiveChildren)))break}},f.InteractionManager.prototype.onMouseOut=function(){var a=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var b=0;a>b;b++){var c=this.interactiveItems[b];c.__isOver&&(this.mouse.target=c,c.mouseout&&c.mouseout(this.mouse),c.__isOver=!1)}},f.InteractionManager.prototype.onMouseUp=function(a){this.mouse.originalEvent=a||window.event,this.mouse.global;for(var b=this.interactiveItems.length,c=!1,d=0;b>d;d++){var e=this.interactiveItems[d];(e.mouseup||e.mouseupoutside||e.click)&&(e.__hit=this.hitTest(e,this.mouse),e.__hit&&!c?(e.mouseup&&e.mouseup(this.mouse),e.__isDown&&e.click&&e.click(this.mouse),e.interactiveChildren||(c=!0)):e.__isDown&&e.mouseupoutside&&e.mouseupoutside(this.mouse),e.__isDown=!1)}},f.InteractionManager.prototype.hitTest=function(a,b){var c=b.global;if(a.vcount!==f.visibleCount)return!1;var d=a instanceof f.Sprite,e=a.worldTransform,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=1/(g*k+h*-j),n=k*m*c.x+-h*m*c.y+(l*h-i*k)*m,o=g*m*c.y+-j*m*c.x+(-l*g+i*j)*m;if(b.target=a,a.hitArea&&a.hitArea.contains)return a.hitArea.contains(n,o)?(b.target=a,!0):!1;if(d){var p,q=a.texture.frame.width,r=a.texture.frame.height,s=-q*a.anchor.x;if(n>s&&s+q>n&&(p=-r*a.anchor.y,o>p&&p+r>o))return b.target=a,!0}for(var t=a.children.length,u=0;t>u;u++){var v=a.children[u],w=this.hitTest(v,b);if(w)return b.target=a,!0}return!1},f.InteractionManager.prototype.onTouchMove=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;dd;d++){var h=this.interactiveItems[d];h.touchmove&&h.touchmove(f)}},f.InteractionManager.prototype.onTouchStart=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i];if((j.touchstart||j.tap)&&(j.__hit=this.hitTest(j,g),j.__hit&&(j.touchstart&&j.touchstart(g),j.__isDown=!0,j.__touchData=g,!j.interactiveChildren)))break}}},f.InteractionManager.prototype.onTouchEnd=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i],k=j.__touchData;j.__hit=this.hitTest(j,f),k==f&&(f.originalEvent=a||window.event,(j.touchend||j.tap)&&(j.__hit&&!g?(j.touchend&&j.touchend(f),j.__isDown&&j.tap&&j.tap(f),j.interactiveChildren||(g=!0)):j.__isDown&&j.touchendoutside&&j.touchendoutside(f),j.__isDown=!1),j.__touchData=null)}this.pool.push(f),this.touchs[e.identifier]=null}},f.InteractionData=function(){this.global=new f.Point,this.local=new f.Point,this.target,this.originalEvent},f.InteractionData.prototype.getLocalPosition=function(a){var b=a.worldTransform,c=this.global,d=b[0],e=b[1],g=b[2],h=b[3],i=b[4],j=b[5],k=1/(d*i+e*-h);return new f.Point(i*k*c.x+-e*k*c.y+(j*e-g*i)*k,d*k*c.y+-h*k*c.x+(-j*d+g*h)*k)},f.InteractionData.prototype.constructor=f.InteractionData,f.Stage=function(a){f.DisplayObjectContainer.call(this),this.worldTransform=f.mat3.create(),this.interactive=!0,this.interactionManager=new f.InteractionManager(this),this.dirty=!0,this.__childrenAdded=[],this.__childrenRemoved=[],this.stage=this,this.stage.hitArea=new f.Rectangle(0,0,1e5,1e5),this.setBackgroundColor(a),this.worldVisible=!0},f.Stage.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Stage.prototype.constructor=f.Stage,f.Stage.prototype.setInteractionDelegate=function(a){this.interactionManager.setTargetDomElement(a)},f.Stage.prototype.updateTransform=function(){this.worldAlpha=1,this.vcount=f.visibleCount;for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform();this.dirty&&(this.dirty=!1,this.interactionManager.dirty=!0),this.interactive&&this.interactionManager.update()},f.Stage.prototype.setBackgroundColor=function(a){this.backgroundColor=a||0,this.backgroundColorSplit=d(this.backgroundColor);var b=this.backgroundColor.toString(16);b="000000".substr(0,6-b.length)+b,this.backgroundColorString="#"+b},f.Stage.prototype.getMousePosition=function(){return this.interactionManager.mouse.global};for(var h=0,i=["ms","moz","webkit","o"],j=0;j>>>>>>>>"),console.log("_");var b=0,c=a.first;for(console.log(c);c._iNext;)if(b++,c=c._iNext,console.log(c),b>100){console.log("BREAK");break}},f.EventTarget=function(){var a={};this.addEventListener=this.on=function(b,c){void 0===a[b]&&(a[b]=[]),-1===a[b].indexOf(c)&&a[b].push(c)},this.dispatchEvent=this.emit=function(b){if(a[b.type]&&a[b.type].length)for(var c=0,d=a[b.type].length;d>c;c++)a[b.type][c](b)},this.removeEventListener=this.off=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)}},f.autoDetectRenderer=function(a,b,c,d,e){a||(a=800),b||(b=600);var g=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}();if(g){var h=-1!=navigator.userAgent.toLowerCase().indexOf("msie");g=!h}return g?new f.WebGLRenderer(a,b,c,d,e):new f.CanvasRenderer(a,b,c,d)},f.PolyK={},f.PolyK.Triangulate=function(a){var b=!0,c=a.length>>1;if(3>c)return[];for(var d=[],e=[],g=0;c>g;g++)e.push(g);for(var g=0,h=c;h>3;){var i=e[(g+0)%h],j=e[(g+1)%h],k=e[(g+2)%h],l=a[2*i],m=a[2*i+1],n=a[2*j],o=a[2*j+1],p=a[2*k],q=a[2*k+1],r=!1;if(f.PolyK._convex(l,m,n,o,p,q,b)){r=!0;for(var s=0;h>s;s++){var t=e[s];if(t!=i&&t!=j&&t!=k&&f.PolyK._PointInTriangle(a[2*t],a[2*t+1],l,m,n,o,p,q)){r=!1;break}}}if(r)d.push(i,j,k),e.splice((g+1)%h,1),h--,g=0;else if(g++>3*h){if(!b)return console.log("PIXI Warning: shape too complex to fill"),[];var d=[];e=[];for(var g=0;c>g;g++)e.push(g);g=0,h=c,b=!1}}return d.push(e[0],e[1],e[2]),d},f.PolyK._PointInTriangle=function(a,b,c,d,e,f,g,h){var i=g-c,j=h-d,k=e-c,l=f-d,m=a-c,n=b-d,o=i*i+j*j,p=i*k+j*l,q=i*m+j*n,r=k*k+l*l,s=k*m+l*n,t=1/(o*r-p*p),u=(r*q-p*s)*t,v=(o*s-p*q)*t;return u>=0&&v>=0&&1>u+v},f.PolyK._convex=function(a,b,c,d,e,f,g){return(b-d)*(e-c)+(c-a)*(f-d)>=0==g},f.shaderFragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));","gl_FragColor = gl_FragColor * vColor;","}"],f.shaderVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","varying float vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"],f.stripShaderFragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying float vColor;","uniform float alpha;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));","gl_FragColor = gl_FragColor * alpha;","}"],f.stripShaderVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","varying vec2 vTextureCoord;","varying float vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"],f.primitiveShaderFragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","gl_FragColor = vColor;","}"],f.primitiveShaderVertexSrc=["attribute vec2 aVertexPosition;","attribute vec4 aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform float alpha;","varying vec4 vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","vColor = aColor * alpha;","}"],f.shaderStack=[],f.initPrimitiveShader=function(){var a=f.gl,b=f.compileProgram(f.primitiveShaderVertexSrc,f.primitiveShaderFragmentSrc);a.useProgram(b),b.vertexPositionAttribute=a.getAttribLocation(b,"aVertexPosition"),b.colorAttribute=a.getAttribLocation(b,"aColor"),b.projectionVector=a.getUniformLocation(b,"projectionVector"),b.offsetVector=a.getUniformLocation(b,"offsetVector"),b.translationMatrix=a.getUniformLocation(b,"translationMatrix"),b.alpha=a.getUniformLocation(b,"alpha"),f.primitiveProgram=b -},f.initDefaultShader=function(){f.frameBufferStack=[],f.frameBufferPool=[],f.defaultShader=new f.PixiShader,f.defaultShader.init(),f.pushShader(f.defaultShader)},f.initDefaultStripShader=function(){var a=this.gl,b=f.compileProgram(f.stripShaderVertexSrc,f.stripShaderFragmentSrc);a.useProgram(b),b.vertexPositionAttribute=a.getAttribLocation(b,"aVertexPosition"),b.projectionVector=a.getUniformLocation(b,"projectionVector"),b.textureCoordAttribute=a.getAttribLocation(b,"aTextureCoord"),b.translationMatrix=a.getUniformLocation(b,"translationMatrix"),b.alpha=a.getUniformLocation(b,"alpha"),b.colorAttribute=a.getAttribLocation(b,"aColor"),b.projectionVector=a.getUniformLocation(b,"projectionVector"),b.samplerUniform=a.getUniformLocation(b,"uSampler"),f.stripShaderProgram=b},f.CompileVertexShader=function(a,b){return f._CompileShader(a,b,a.VERTEX_SHADER)},f.CompileFragmentShader=function(a,b){return f._CompileShader(a,b,a.FRAGMENT_SHADER)},f._CompileShader=function(a,b,c){var d=b.join("\n"),e=a.createShader(c);return a.shaderSource(e,d),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)?e:(alert(a.getShaderInfoLog(e)),null)},f.compileProgram=function(a,b){var c=f.gl,d=f.CompileFragmentShader(c,b),e=f.CompileVertexShader(c,a),g=c.createProgram();return c.attachShader(g,e),c.attachShader(g,d),c.linkProgram(g),c.getProgramParameter(g,c.LINK_STATUS)||alert("Could not initialise shaders"),g},f.pushShader=function(a){var b=f.gl;b.colorMask(!0,!0,!0,!0),b.viewport(0,0,this.width,this.height),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),f.shaderStack.push(a);var c=a.program;b.useProgram(c),b.enableVertexAttribArray(c.vertexPositionAttribute),b.enableVertexAttribArray(c.colorAttribute),b.enableVertexAttribArray(c.textureCoordAttribute),a.syncUniforms(),f.currentShader=c},f.popShader=function(){var a=f.gl;f.shaderStack.pop();var b=f.shaderStack[f.shaderStack.length-1].program;a.useProgram(b),f.currentShader=b},f.activatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.primitiveProgram),a.disableVertexAttribArray(f.currentShader.textureCoordAttribute)},f.deactivatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.currentShader),a.enableVertexAttribArray(f.currentShader.textureCoordAttribute)},f.PixiShader=function(){this.program,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;","}"]},f.PixiShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc||f.shaderVertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"),a.vertexPositionAttribute=b.getAttribLocation(a,"aVertexPosition"),a.colorAttribute=b.getAttribLocation(a,"aColor"),a.textureCoordAttribute=b.getAttribLocation(a,"aTextureCoord"),a.projectionVector=b.getUniformLocation(a,"projectionVector"),a.samplerUniform=b.getUniformLocation(a,"uSampler"),a.offsetVector=b.getUniformLocation(a,"offsetVector");for(var c in this.uniforms)a[c]=b.getUniformLocation(a,c);this.program=a},f.PixiShader.prototype.syncUniforms=function(){var a=f.gl;for(var b in this.uniforms){var c=this.uniforms[b].type;if("f"==c&&a.uniform1f(this.program[b],this.uniforms[b].value),"f2"==c)a.uniform2f(this.program[b],this.uniforms[b].value.x,this.uniforms[b].value.y);else if("mat4"==c)a.uniformMatrix4fv(this.program[b],!1,this.uniforms[b].value);else if("sampler2D"==c){var d=this.uniforms[b].value;a.activeTexture(a.TEXTURE1),a.bindTexture(a.TEXTURE_2D,d.baseTexture._glTexture),a.uniform1i(this.program[b],1)}}},f.WebGLGraphics=function(){},f.WebGLGraphics.renderGraphics=function(a,b){var c=f.gl;a._webGL||(a._webGL={points:[],indices:[],lastIndex:0,buffer:c.createBuffer(),indexBuffer:c.createBuffer()}),a.dirty&&(a.dirty=!1,a.clearDirty&&(a.clearDirty=!1,a._webGL.lastIndex=0,a._webGL.points=[],a._webGL.indices=[]),f.WebGLGraphics.updateGraphics(a)),f.activatePrimitiveShader();var d=f.mat3.clone(a.worldTransform);f.mat3.transpose(d),c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA),c.uniformMatrix3fv(f.primitiveProgram.translationMatrix,!1,d),c.uniform2f(f.primitiveProgram.projectionVector,b.x,-b.y),c.uniform2f(f.primitiveProgram.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(f.primitiveProgram.alpha,a.worldAlpha),c.bindBuffer(c.ARRAY_BUFFER,a._webGL.buffer),c.vertexAttribPointer(f.primitiveProgram.vertexPositionAttribute,2,c.FLOAT,!1,24,0),c.vertexAttribPointer(f.primitiveProgram.colorAttribute,4,c.FLOAT,!1,24,8),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),c.drawElements(c.TRIANGLE_STRIP,a._webGL.indices.length,c.UNSIGNED_SHORT,0),f.deactivatePrimitiveShader()},f.WebGLGraphics.updateGraphics=function(a){for(var b=a._webGL.lastIndex;b3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){var e=new f.Point(c[0],c[1]),g=new f.Point(c[c.length-2],c[c.length-1]);if(e.x==g.x&&e.y==g.y){c.pop(),c.pop(),g=new f.Point(c[c.length-2],c[c.length-1]);var h=g.x+.5*(e.x-g.x),i=g.y+.5*(e.y-g.y);c.unshift(h,i),c.push(h,i)}var j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E=b.points,F=b.indices,G=c.length/2,H=c.length,I=E.length/6,J=a.lineWidth/2,K=d(a.lineColor),L=a.lineAlpha,M=K[0]*L,N=K[1]*L,O=K[2]*L;j=c[0],k=c[1],l=c[2],m=c[3],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,E.push(j-p,k-q,M,N,O,L),E.push(j+p,k+q,M,N,O,L);for(var P=1;G-1>P;P++)j=c[2*(P-1)],k=c[2*(P-1)+1],l=c[2*P],m=c[2*P+1],n=c[2*(P+1)],o=c[2*(P+1)+1],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,r=-(m-o),s=l-n,D=Math.sqrt(r*r+s*s),r/=D,s/=D,r*=J,s*=J,v=-q+k-(-q+m),w=-p+l-(-p+j),x=(-p+j)*(-q+m)-(-p+l)*(-q+k),y=-s+o-(-s+m),z=-r+l-(-r+n),A=(-r+n)*(-s+m)-(-r+l)*(-s+o),B=v*z-y*w,0==B&&(B+=1),px=(w*A-z*x)/B,py=(y*x-v*A)/B,C=(px-l)*(px-l)+(py-m)+(py-m),C>19600?(t=p-r,u=q-s,D=Math.sqrt(t*t+u*u),t/=D,u/=D,t*=J,u*=J,E.push(l-t,m-u),E.push(M,N,O,L),E.push(l+t,m+u),E.push(M,N,O,L),E.push(l-t,m-u),E.push(M,N,O,L),H++):(E.push(px,py),E.push(M,N,O,L),E.push(l-(px-l),m-(py-m)),E.push(M,N,O,L));j=c[2*(G-2)],k=c[2*(G-2)+1],l=c[2*(G-1)],m=c[2*(G-1)+1],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,E.push(l-p,m-q),E.push(M,N,O,L),E.push(l+p,m+q),E.push(M,N,O,L),F.push(I);for(var P=0;H>P;P++)F.push(I++);F.push(I-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShader(),f.initPrimitiveShader(),f.initDefaultStripShader();var j=this.gl;f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,f.pushShader(f.defaultShader),this.stageRenderGroup=new f.WebGLRenderGroup(this.gl)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){f.shaderStack.length;var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;a.open?a.data instanceof Array?this.filterManager.pushFilter(a):(c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,255),c.stencilOp(c.KEEP,c.KEEP,c.REPLACE),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,255),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)):a.data instanceof Array?this.filterManager.popFilter():c.disable(c.STENCIL_TEST)},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl,d=f.stripShaderProgram;c.useProgram(d);var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.vertexPositionAttribute,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.textureCoordAttribute,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.vertexPositionAttribute,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.textureCoordAttribute,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),c.useProgram(f.currentProgram)},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(){this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a),a.filterPasses[0],this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var c=this.texturePool.pop();c||(c=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,c.texture),this.getBounds(a.target);var d=a.target.filterArea;b.bindFramebuffer(b.FRAMEBUFFER,c.frameBuffer),b.viewport(0,0,d.width,d.height),f.projection.x=d.width/2,f.projection.y=-d.height/2,f.offset.x=-d.x,f.offset.y=-d.y,b.uniform2f(f.currentShader.projectionVector,d.width/2,-d.height/2),b.uniform2f(f.currentShader.offsetVector,-d.x,-d.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=c},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;hs?s:E,E=E>t?t:E,E=E>u?u:E,E=E>v?v:E,F=F>w?w:F,F=F>x?x:F,F=F>y?y:F,F=F>z?z:F,C=s>C?s:C,C=t>C?t:C,C=u>C?u:C,C=v>C?v:C,D=w>D?w:D,D=x>D?x:D,D=y>D?y:D,D=z>D?z:D),l=!1,A=A._iNext}while(A!=B);E=E>0?E:0,F=F>0?F:0,C=C0&&(f.Texture.frameUpdates=[])},f.CanvasRenderer.prototype.resize=function(a,b){this.width=a,this.height=b,this.view.width=a,this.view.height=b},f.CanvasRenderer.prototype.renderDisplayObject=function(a){var b,c=this.context;c.globalCompositeOperation="source-over";var d=a.last._iNext;a=a.first;do if(b=a.worldTransform,a.visible)if(a.renderable){if(a instanceof f.Sprite){var e=a.texture.frame;e&&e.width&&e.height&&(c.globalAlpha=a.worldAlpha,c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),c.drawImage(a.texture.baseTexture.source,e.x,e.y,e.width,e.height,a.anchor.x*-e.width,a.anchor.y*-e.height,e.width,e.height))}else if(a instanceof f.Strip)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderStrip(a);else if(a instanceof f.TilingSprite)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderTilingSprite(a);else if(a instanceof f.CustomRenderable)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),a.renderCanvas(this);else if(a instanceof f.Graphics)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),f.CanvasGraphics.renderGraphics(a,c);else if(a instanceof f.FilterBlock&&a.data instanceof f.Graphics){var g=a.data;if(a.open){c.save();var h=g.alpha,i=g.worldTransform;c.setTransform(i[0],i[3],i[1],i[4],i[2],i[5]),g.worldAlpha=.5,c.worldAlpha=0,f.CanvasGraphics.renderGraphicsMask(g,c),c.clip(),g.worldAlpha=h}else c.restore()}a=a._iNext}else a=a._iNext;else a=a.last._iNext;while(a!=d)},f.CanvasRenderer.prototype.renderStripFlat=function(a){var b=this.context,c=a.verticies;a.uvs;var d=c.length/2;this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},f.CanvasRenderer.prototype.renderTilingSprite=function(a){var b=this.context;b.globalAlpha=a.worldAlpha,a.__tilePattern||(a.__tilePattern=b.createPattern(a.texture.baseTexture.source,"repeat")),b.beginPath();var c=a.tilePosition,d=a.tileScale;b.scale(d.x,d.y),b.translate(c.x,c.y),b.fillStyle=a.__tilePattern,b.fillRect(-c.x,-c.y,a.width/d.x,a.height/d.y),b.scale(1/d.x,1/d.y),b.translate(-c.x,-c.y),b.closePath()},f.CanvasRenderer.prototype.renderStrip=function(a){var b=this.context,c=a.verticies,d=a.uvs,e=c.length/2;this.count++;for(var f=1;e-2>f;f++){var g=2*f,h=c[g],i=c[g+2],j=c[g+4],k=c[g+1],l=c[g+3],m=c[g+5],n=d[g]*a.texture.width,o=d[g+2]*a.texture.width,p=d[g+4]*a.texture.width,q=d[g+1]*a.texture.height,r=d[g+3]*a.texture.height,s=d[g+5]*a.texture.height;b.save(),b.beginPath(),b.moveTo(h,k),b.lineTo(i,l),b.lineTo(j,m),b.closePath(),b.clip();var t=n*r+q*p+o*s-r*p-q*o-n*s,u=h*r+q*j+i*s-r*j-q*i-h*s,v=n*i+h*p+o*j-i*p-h*o-n*j,w=n*r*j+q*i*p+h*o*s-h*r*p-q*o*j-n*i*s,x=k*r+q*m+l*s-r*m-q*l-k*s,y=n*l+k*p+o*m-l*p-k*o-n*m,z=n*r*m+q*l*p+k*o*s-k*r*p-q*o*m-n*l*s;b.transform(u/t,x/t,v/t,y/t,w/t,z/t),b.drawImage(a.texture.baseTexture.source,0,0),b.restore()}},f.CanvasGraphics=function(){},f.CanvasGraphics.renderGraphics=function(a,b){for(var c=a.worldAlpha,d=0;d1&&(c=1,console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var d=0;1>d;d++){var e=a.graphicsData[d],g=e.points;if(e.type==f.Graphics.POLY){b.beginPath(),b.moveTo(g[0],g[1]);for(var h=1;hb?b:d,e=b+m>e?b+m:e,g=g>c?b:g,h=c+n>h?c+n:h}else if(k===f.Graphics.CIRC||k===f.Graphics.ELIP){b=a.x,c=a.y;var o=a.radius+l/2;d=d>b-o?b-o:d,e=b+o>e?b+o:e,g=g>c-o?c-o:g,h=c+o>h?c+o:h}else for(var p=0;pb-l?b-l:d,e=b+l>e?b+l:e,g=g>c-l?c-l:g,h=c+l>h?c+l:h}this.bounds=new f.Rectangle(d,g,e-d,h-g)}},f.Graphics.POLY=0,f.Graphics.RECT=1,f.Graphics.CIRC=2,f.Graphics.ELIP=3,f.Strip=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.blendMode=f.blendModes.NORMAL;try{this.uvs=new Float32Array([0,1,1,1,1,0,0,1]),this.verticies=new Float32Array([0,0,0,0,0,0,0,0,0]),this.colors=new Float32Array([1,1,1,1]),this.indices=new Uint16Array([0,1,2,3])}catch(d){this.uvs=[0,1,1,1,1,0,0,1],this.verticies=[0,0,0,0,0,0,0,0,0],this.colors=[1,1,1,1],this.indices=[0,1,2,3]}this.width=b,this.height=c,a.baseTexture.hasLoaded?(this.width=this.texture.frame.width,this.height=this.texture.frame.height,this.updateFrame=!0):(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Strip.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Strip.prototype.constructor=f.Strip,f.Strip.prototype.setTexture=function(a){this.texture=a,this.width=a.frame.width,this.height=a.frame.height,this.updateFrame=!0},f.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Rope=function(a,b){f.Strip.call(this,a),this.points=b;try{this.verticies=new Float32Array(4*b.length),this.uvs=new Float32Array(4*b.length),this.colors=new Float32Array(2*b.length),this.indices=new Uint16Array(2*b.length)}catch(c){this.verticies=verticies,this.uvs=uvs,this.colors=colors,this.indices=indices}this.refresh()},f.Rope.prototype=Object.create(f.Strip.prototype),f.Rope.prototype.constructor=f.Rope,f.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=this.indices,d=this.colors,e=a[0],f=a[0];this.count-=.2,b[0]=0,b[1]=1,b[2]=0,b[3]=1,d[0]=1,d[1]=1,c[0]=0,c[1]=1;for(var g=a.length,h=1;g>h;h++){var f=a[h],i=4*h,j=h/(g-1);h%2?(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1):(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1),i=2*h,d[i]=1,d[i+1]=1,i=2*h,c[i]=i,c[i+1]=i+1,e=f}}},f.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var b,c=this.verticies,d=a[0],e={x:0,y:0},g=a[0];this.count-=.2,c[0]=g.x+e.x,c[1]=g.y+e.y,c[2]=g.x-e.x,c[3]=g.y-e.y;for(var h=a.length,i=1;h>i;i++){var g=a[i],j=4*i;b=i1&&(k=1);var l=Math.sqrt(e.x*e.x+e.y*e.y),m=this.texture.height/2;e.x/=l,e.y/=l,e.x*=m,e.y*=m,c[j]=g.x+e.x,c[j+1]=g.y+e.y,c[j+2]=g.x-e.x,c[j+3]=g.y-e.y,d=g}f.DisplayObjectContainer.prototype.updateTransform.call(this)}},f.Rope.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.width=b,this.height=c,this.tileScale=new f.Point(1,1),this.tilePosition=new f.Point(0,0),this.renderable=!0,this.blendMode=f.blendModes.NORMAL},f.TilingSprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.TilingSprite.prototype.constructor=f.TilingSprite,f.TilingSprite.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Spine=function(a){if(f.DisplayObjectContainer.call(this),this.spineData=f.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new l.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new l.AnimationStateData(this.spineData),this.state=new l.AnimationState(this.stateData),this.slotContainers=[];for(var b=0,c=this.skeleton.drawOrder.length;c>b;b++){var d=this.skeleton.drawOrder[b],e=d.attachment,g=new f.DisplayObjectContainer;if(this.slotContainers.push(g),this.addChild(g),e instanceof l.RegionAttachment){var h=e.rendererObject.name,i=this.createSprite(d,e.rendererObject);d.currentSprite=i,d.currentSpriteName=h,g.addChild(i)}}},f.Spine.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Spine.prototype.constructor=f.Spine,f.Spine.prototype.updateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var b=this.skeleton.drawOrder,c=0,d=b.length;d>c;c++){var e=b[c],g=e.attachment,h=this.slotContainers[c];if(g instanceof l.RegionAttachment){if(g.rendererObject&&(!e.currentSpriteName||e.currentSpriteName!=g.name)){var i=g.rendererObject.name;if(void 0!==e.currentSprite&&(e.currentSprite.visible=!1),e.sprites=e.sprites||{},void 0!==e.sprites[i])e.sprites[i].visible=!0;else{var j=this.createSprite(e,g.rendererObject);h.addChild(j)}e.currentSprite=e.sprites[i],e.currentSpriteName=i}h.visible=!0;var k=e.bone;h.position.x=k.worldX+g.x*k.m00+g.y*k.m01,h.position.y=k.worldY+g.x*k.m10+g.y*k.m11,h.scale.x=k.worldScaleX,h.scale.y=k.worldScaleY,h.rotation=-(e.bone.worldRotation*Math.PI/180)}else h.visible=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.Spine.prototype.createSprite=function(a,b){var c=f.TextureCache[b.name]?b.name:b.name+".png",d=new f.Sprite(f.Texture.fromFrame(c));return d.scale=b.scale,d.rotation=b.rotation,d.anchor.x=d.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[b.name]=d,d};var l={};l.BoneData=function(a,b){this.name=a,this.parent=b},l.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1},l.SlotData=function(a,b){this.name=a,this.boneData=b},l.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null},l.Bone=function(a,b){this.data=a,this.parent=b,this.setToSetupPose()},l.Bone.yDown=!1,l.Bone.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,updateWorldTransform:function(a,b){var c=this.parent;null!=c?(this.worldX=this.x*c.m00+this.y*c.m01+c.worldX,this.worldY=this.x*c.m10+this.y*c.m11+c.worldY,this.worldScaleX=c.worldScaleX*this.scaleX,this.worldScaleY=c.worldScaleY*this.scaleY,this.worldRotation=c.worldRotation+this.rotation):(this.worldX=this.x,this.worldY=this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotation);var d=this.worldRotation*Math.PI/180,e=Math.cos(d),f=Math.sin(d);this.m00=e*this.worldScaleX,this.m10=f*this.worldScaleX,this.m01=-f*this.worldScaleY,this.m11=e*this.worldScaleY,a&&(this.m00=-this.m00,this.m01=-this.m01),b&&(this.m10=-this.m10,this.m11=-this.m11),l.Bone.yDown&&(this.m10=-this.m10,this.m11=-this.m11)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY}},l.Slot=function(a,b,c){this.data=a,this.skeleton=b,this.bone=c,this.setToSetupPose()},l.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,setAttachment:function(a){this.attachment=a,this._attachmentTime=this.skeleton.time},setAttachmentTime:function(a){this._attachmentTime=this.skeleton.time-a},getAttachmentTime:function(){return this.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},l.Skin=function(a){this.name=a,this.attachments={}},l.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},l.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},l.Animation.prototype={apply:function(a,b,c){c&&0!=this.duration&&(b%=this.duration);for(var d=this.timelines,e=0,f=d.length;f>e;e++)d[e].apply(a,b,1)},mix:function(a,b,c,d){c&&0!=this.duration&&(b%=this.duration);for(var e=this.timelines,f=0,g=e.length;g>f;f++)e[f].apply(a,b,d)}},l.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(0==e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},l.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},l.Curves=function(a){this.curves=[],this.curves.length=6*(a-1)},l.Curves.prototype={setLinear:function(a){this.curves[6*a]=0},setStepped:function(a){this.curves[6*a]=-1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=6*a,r=this.curves;r[q]=b*i+m*j+o*h,r[q+1]=c*i+n*j+p*h,r[q+2]=m*k+o*l,r[q+3]=n*k+p*l,r[q+4]=o*l,r[q+5]=p*l},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=6*a,d=this.curves,e=d[c];if(!e)return b;if(-1==e)return 0;for(var f=d[c+1],g=d[c+2],h=d[c+3],i=d[c+4],j=d[c+5],k=e,l=f,m=8;;){if(k>=b){var n=k-e,o=l-f;return o+(l-o)*(b-n)/(k-n)}if(0==m)break;m--,e+=g,f+=h,g+=i,h+=j,k+=e,l+=f}return l+(1-l)*(b-k)/(1-k)}},l.RotateTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=2*a},l.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-2]){for(var f=e.data.rotation+d[d.length-1]-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;return e.rotation+=f*c,void 0}var g=l.binarySearch(d,b,2),h=d[g-1],i=d[g],j=1-(b-i)/(d[g-2]-i);j=this.curves.getCurvePercent(g/2-1,j);for(var f=d[g+1]-h;f>180;)f-=360;for(;-180>f;)f+=360;for(f=e.data.rotation+(h+f*j)-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;e.rotation+=f*c}}},l.TranslateTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=3*a},l.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.x+=(e.data.x+d[d.length-2]-e.x)*c,e.y+=(e.data.y+d[d.length-1]-e.y)*c,void 0;var f=l.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.x+=(e.data.x+g+(d[f+1]-g)*j-e.x)*c,e.y+=(e.data.y+h+(d[f+2]-h)*j-e.y)*c}}},l.ScaleTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=3*a},l.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.scaleX+=(e.data.scaleX-1+d[d.length-2]-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+d[d.length-1]-e.scaleY)*c,void 0;var f=l.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.scaleX+=(e.data.scaleX-1+g+(d[f+1]-g)*j-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+h+(d[f+2]-h)*j-e.scaleY)*c}}},l.ColorTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=5*a},l.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(c,d){c*=5,this.frames[c]=d,this.frames[c+1]=r,this.frames[c+2]=g,this.frames[c+3]=b,this.frames[c+4]=a},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-5]){var f=d.length-1;return e.r=d[f-3],e.g=d[f-2],e.b=d[f-1],e.a=d[f],void 0}var g=l.binarySearch(d,b,5),h=d[g-4],i=d[g-3],j=d[g-2],k=d[g-1],m=d[g],n=1-(b-m)/(d[g-5]-m);n=this.curves.getCurvePercent(g/5-1,n);var o=h+(d[g+1]-h)*n,p=i+(d[g+2]-i)*n,q=j+(d[g+3]-j)*n,r=k+(d[g+4]-k)*n;1>c?(e.r+=(o-e.r)*c,e.g+=(p-e.g)*c,e.b+=(q-e.b)*c,e.a+=(r-e.a)*c):(e.r=o,e.g=p,e.b=q,e.a=r)}}},l.AttachmentTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},l.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b){var c=this.frames;if(!(b=c[c.length-1]?c.length-1:l.binarySearch(c,b,1)-1;var e=this.attachmentNames[d];a.slots[this.slotIndex].setAttachment(e?a.getAttachmentBySlotIndex(this.slotIndex,e):null)}}},l.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.animations=[]},l.SkeletonData.prototype={defaultSkin:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},l.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,c=a.bones.length;c>b;b++){var d=a.bones[b],e=d.parent?this.bones[a.bones.indexOf(d.parent)]:null;this.bones.push(new l.Bone(d,e))}this.slots=[],this.drawOrder=[];for(var b=0,c=a.slots.length;c>b;b++){var f=a.slots[b],g=this.bones[a.bones.indexOf(f.boneData)],h=new l.Slot(f,this,g);this.slots.push(h),this.drawOrder.push(h)}},l.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateWorldTransform:function(){for(var a=this.flipX,b=this.flipY,c=this.bones,d=0,e=c.length;e>d;d++)c[d].updateWorldTransform(a,b)},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose()},setSlotsToSetupPose:function(){for(var a=this.slots,b=0,c=a.length;c>b;b++)a[b].setToSetupPose(b)},getRootBone:function(){return 0==this.bones.length?null:this.bones[0]},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a);if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){this.skin&&a&&a._attachAll(this,this.skin),this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.size;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachment(d,b),null==g))throw"Attachment not found: "+b+", for slot: "+a;return f.setAttachment(g),void 0}}throw"Slot not found: "+a},update:function(a){time+=a}},l.AttachmentType={region:0},l.RegionAttachment=function(){this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},l.RegionAttachment.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,c=-this.width/2*this.scaleX+this.regionOffsetX*a,d=-this.height/2*this.scaleY+this.regionOffsetY*b,e=c+this.regionWidth*a,f=d+this.regionHeight*b,g=this.rotation*Math.PI/180,h=Math.cos(g),i=Math.sin(g),j=c*h+this.x,k=c*i,l=d*h+this.y,m=d*i,n=e*h+this.x,o=e*i,p=f*h+this.y,q=f*i,r=this.offset;r[0]=j-m,r[1]=l+k,r[2]=j-q,r[3]=p+k,r[4]=n-q,r[5]=p+o,r[6]=n-m,r[7]=l+o},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},l.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},l.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=this.animationToMixTime[a.name+":"+b.name];return c?c:this.defaultMix}},l.AnimationState=function(a){this.data=a,this.queue=[]},l.AnimationState.prototype={current:null,previous:null,currentTime:0,previousTime:0,currentLoop:!1,previousLoop:!1,mixTime:0,mixDuration:0,update:function(a){if(this.currentTime+=a,this.previousTime+=a,this.mixTime+=a,this.queue.length>0){var b=this.queue[0];this.currentTime>=b.delay&&(this._setAnimation(b.animation,b.loop),this.queue.shift())}},apply:function(a){if(this.current)if(this.previous){this.previous.apply(a,this.previousTime,this.previousLoop);var b=this.mixTime/this.mixDuration;b>=1&&(b=1,this.previous=null),this.current.mix(a,this.currentTime,this.currentLoop,b)}else this.current.apply(a,this.currentTime,this.currentLoop)},clearAnimation:function(){this.previous=null,this.current=null,this.queue.length=0},_setAnimation:function(a,b){this.previous=null,a&&this.current&&(this.mixDuration=this.data.getMix(this.current,a),this.mixDuration>0&&(this.mixTime=0,this.previous=this.current,this.previousTime=this.currentTime,this.previousLoop=this.currentLoop)),this.current=a,this.currentLoop=b,this.currentTime=0},setAnimationByName:function(a,b){var c=this.data.skeletonData.findAnimation(a);if(!c)throw"Animation not found: "+a;this.setAnimation(c,b)},setAnimation:function(a,b){this.queue.length=0,this._setAnimation(a,b)},addAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;this.addAnimation(d,b,c)},addAnimation:function(a,b,c){var d={};if(d.animation=a,d.loop=b,!c||0>=c){var e=0==this.queue.length?this.current:this.queue[this.queue.length-1].animation;c=null!=e?e.duration-this.data.getMix(e,a)+(c||0):0}d.delay=c,this.queue.push(d)},isComplete:function(){return!this.current||this.currentTime>=this.current.duration}},l.SkeletonJson=function(a){this.attachmentLoader=a},l.SkeletonJson.prototype={scale:1,readSkeletonData:function(a){for(var b=new l.SkeletonData,c=a.bones,d=0,e=c.length;e>d;d++){var f=c[d],g=null;if(f.parent&&(g=b.findBone(f.parent),!g))throw"Parent bone not found: "+f.parent;var h=new l.BoneData(f.name,g);h.length=(f.length||0)*this.scale,h.x=(f.x||0)*this.scale,h.y=(f.y||0)*this.scale,h.rotation=f.rotation||0,h.scaleX=f.scaleX||1,h.scaleY=f.scaleY||1,b.bones.push(h)}for(var i=a.slots,d=0,e=i.length;e>d;d++){var j=i[d],h=b.findBone(j.bone);if(!h)throw"Slot bone not found: "+j.bone;var k=new l.SlotData(j.name,h),m=j.color;m&&(k.r=l.SkeletonJson.toColor(m,0),k.g=l.SkeletonJson.toColor(m,1),k.b=l.SkeletonJson.toColor(m,2),k.a=l.SkeletonJson.toColor(m,3)),k.attachmentName=j.attachment,b.slots.push(k)}var n=a.skins;for(var o in n)if(n.hasOwnProperty(o)){var p=n[o],q=new l.Skin(o);for(var r in p)if(p.hasOwnProperty(r)){var s=b.findSlotIndex(r),t=p[r];for(var u in t)if(t.hasOwnProperty(u)){var v=this.readAttachment(q,u,t[u]);null!=v&&q.addAttachment(s,u,v)}}b.skins.push(q),"default"==q.name&&(b.defaultSkin=q)}var w=a.animations;for(var x in w)w.hasOwnProperty(x)&&this.readAnimation(x,w[x],b);return b},readAttachment:function(a,b,c){b=c.name||b;var d=l.AttachmentType[c.type||"region"];if(d==l.AttachmentType.region){var e=new l.RegionAttachment; -return e.x=(c.x||0)*this.scale,e.y=(c.y||0)*this.scale,e.scaleX=c.scaleX||1,e.scaleY=c.scaleY||1,e.rotation=c.rotation||0,e.width=(c.width||32)*this.scale,e.height=(c.height||32)*this.scale,e.updateOffset(),e.rendererObject={},e.rendererObject.name=b,e.rendererObject.scale={},e.rendererObject.scale.x=e.scaleX,e.rendererObject.scale.y=e.scaleY,e.rendererObject.rotation=-e.rotation*Math.PI/180,e}throw"Unknown attachment type: "+d},readAnimation:function(a,b,c){var d=[],e=0,f=b.bones;for(var g in f)if(f.hasOwnProperty(g)){var h=c.findBoneIndex(g);if(-1==h)throw"Bone not found: "+g;var i=f[g];for(var j in i)if(i.hasOwnProperty(j)){var k=i[j];if("rotate"==j){var m=new l.RotateTimeline(k.length);m.boneIndex=h;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o];m.setFrame(n,q.time,q.angle),l.SkeletonJson.readCurve(m,n,q),n++}d.push(m),e=Math.max(e,m.frames[2*m.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var m,r=1;"scale"==j?m=new l.ScaleTimeline(k.length):(m=new l.TranslateTimeline(k.length),r=this.scale),m.boneIndex=h;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;m.setFrame(n,q.time,s,t),l.SkeletonJson.readCurve(m,n,q),n++}d.push(m),e=Math.max(e,m.frames[3*m.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var m=new l.ColorTimeline(k.length);m.slotIndex=x;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=l.SkeletonJson.toColor(y,0),A=l.SkeletonJson.toColor(y,1),B=l.SkeletonJson.toColor(y,2),C=l.SkeletonJson.toColor(y,3);m.setFrame(n,q.time,z,A,B,C),l.SkeletonJson.readCurve(m,n,q),n++}d.push(m),e=Math.max(e,m.frames[5*m.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var m=new l.AttachmentTimeline(k.length);m.slotIndex=x;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o];m.setFrame(n++,q.time,q.name)}d.push(m),e=Math.max(e,m.frames[m.getFrameCount()-1])}}}c.animations.push(new l.Animation(a,d,e))}},l.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},l.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},l.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new l.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new l.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new l.AtlasPage,e.name=f,e.format=l.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=l.Atlas.TextureFilter[d[0]],e.magFilter=l.Atlas.TextureFilter[d[1]];var m=c.readValue();e.uWrap=l.Atlas.TextureWrap.clampToEdge,e.vWrap=l.Atlas.TextureWrap.clampToEdge,"x"==m?e.uWrap=l.Atlas.TextureWrap.repeat:"y"==m?e.vWrap=l.Atlas.TextureWrap.repeat:"xy"==m&&(e.uWrap=e.vWrap=l.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},l.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},l.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},l.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},l.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},l.AtlasPage=function(){},l.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},l.AtlasRegion=function(){},l.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},l.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},l.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},l.AtlasAttachmentLoader=function(a){this.atlas=a},l.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case l.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new l.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},l.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;h>16)/255,(255&a>>8)/255,(255&a)/255]}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}var e=this,f=f||{};f.Point=function(a,b){this.x=a||0,this.y=b||0},f.Point.prototype.clone=function(){return new f.Point(this.x,this.y)},f.Point.prototype.constructor=f.Point,f.Rectangle=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Rectangle.prototype.clone=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Rectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},f.Rectangle.prototype.constructor=f.Rectangle,f.Polygon=function(a){if(a instanceof Array||(a=Array.prototype.slice.call(arguments)),"number"==typeof a[0]){for(var b=[],c=0,d=a.length;d>c;c+=2)b.push(new f.Point(a[c],a[c+1]));a=b}this.points=a},f.Polygon.prototype.clone=function(){for(var a=[],b=0;bb!=i>b&&(h-f)*(b-g)/(i-g)+f>a;j&&(c=!c)}return c},f.Polygon.prototype.constructor=f.Polygon,f.Circle=function(a,b,c){this.x=a||0,this.y=b||0,this.radius=c||0},f.Circle.prototype.clone=function(){return new f.Circle(this.x,this.y,this.radius)},f.Circle.prototype.contains=function(a,b){if(this.radius<=0)return!1;var c=this.x-a,d=this.y-b,e=this.radius*this.radius;return c*=c,d*=d,e>=c+d},f.Circle.prototype.constructor=f.Circle,f.Ellipse=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Ellipse.prototype.clone=function(){return new f.Ellipse(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=(a-this.x)/this.width-.5,d=(b-this.y)/this.height-.5;return c*=c,d*=d,.25>c+d},f.Ellipse.getBounds=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.constructor=f.Ellipse,c(),f.mat3={},f.mat3.create=function(){var a=new f.Matrix(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat3.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat4={},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat3.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=b[0],n=b[1],o=b[2],p=b[3],q=b[4],r=b[5],s=b[6],t=b[7],u=b[8];return c[0]=m*d+n*g+o*j,c[1]=m*e+n*h+o*k,c[2]=m*f+n*i+o*l,c[3]=p*d+q*g+r*j,c[4]=p*e+q*h+r*k,c[5]=p*f+q*i+r*l,c[6]=s*d+t*g+u*j,c[7]=s*e+t*h+u*k,c[8]=s*f+t*i+u*l,c},f.mat3.clone=function(a){var b=new f.Matrix(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},f.mat3.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[5];return a[1]=a[3],a[2]=a[6],a[3]=c,a[5]=a[7],a[6]=d,a[7]=e,a}return b[0]=a[0],b[1]=a[3],b[2]=a[6],b[3]=a[1],b[4]=a[4],b[5]=a[7],b[6]=a[2],b[7]=a[5],b[8]=a[8],b},f.mat3.toMat4=function(a,b){return b||(b=f.mat4.create()),b[15]=1,b[14]=0,b[13]=0,b[12]=0,b[11]=0,b[10]=a[8],b[9]=a[7],b[8]=a[6],b[7]=0,b[6]=a[5],b[5]=a[4],b[4]=a[3],b[3]=0,b[2]=a[2],b[1]=a[1],b[0]=a[0],b},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat4.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[3],f=a[6],g=a[7],h=a[11];return a[1]=a[4],a[2]=a[8],a[3]=a[12],a[4]=c,a[6]=a[9],a[7]=a[13],a[8]=d,a[9]=f,a[11]=a[14],a[12]=e,a[13]=g,a[14]=h,a}return b[0]=a[0],b[1]=a[4],b[2]=a[8],b[3]=a[12],b[4]=a[1],b[5]=a[5],b[6]=a[9],b[7]=a[13],b[8]=a[2],b[9]=a[6],b[10]=a[10],b[11]=a[14],b[12]=a[3],b[13]=a[7],b[14]=a[11],b[15]=a[15],b},f.mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=b[0],u=b[1],v=b[2],w=b[3];return c[0]=t*d+u*h+v*l+w*p,c[1]=t*e+u*i+v*m+w*q,c[2]=t*f+u*j+v*n+w*r,c[3]=t*g+u*k+v*o+w*s,t=b[4],u=b[5],v=b[6],w=b[7],c[4]=t*d+u*h+v*l+w*p,c[5]=t*e+u*i+v*m+w*q,c[6]=t*f+u*j+v*n+w*r,c[7]=t*g+u*k+v*o+w*s,t=b[8],u=b[9],v=b[10],w=b[11],c[8]=t*d+u*h+v*l+w*p,c[9]=t*e+u*i+v*m+w*q,c[10]=t*f+u*j+v*n+w*r,c[11]=t*g+u*k+v*o+w*s,t=b[12],u=b[13],v=b[14],w=b[15],c[12]=t*d+u*h+v*l+w*p,c[13]=t*e+u*i+v*m+w*q,c[14]=t*f+u*j+v*n+w*r,c[15]=t*g+u*k+v*o+w*s,c},f.DisplayObject=function(){this.last=this,this.first=this,this.position=new f.Point,this.scale=new f.Point(1,1),this.pivot=new f.Point(0,0),this.rotation=0,this.alpha=1,this.visible=!0,this.hitArea=null,this.buttonMode=!1,this.renderable=!1,this.parent=null,this.stage=null,this.worldAlpha=1,this._interactive=!1,this.worldTransform=f.mat3.create(),this.localTransform=f.mat3.create(),this.color=[],this.dynamic=!0,this._sr=0,this._cr=1,this.filterArea=new f.Rectangle(0,0,1,1)},f.DisplayObject.prototype.constructor=f.DisplayObject,f.DisplayObject.prototype.setInteractive=function(a){this.interactive=a},Object.defineProperty(f.DisplayObject.prototype,"interactive",{get:function(){return this._interactive},set:function(a){this._interactive=a,this.stage&&(this.stage.dirty=!0)}}),Object.defineProperty(f.DisplayObject.prototype,"mask",{get:function(){return this._mask},set:function(a){a?this._mask?(a.start=this._mask.start,a.end=this._mask.end):(this.addFilter(a),a.renderable=!1):(this.removeFilter(this._mask),this._mask.renderable=!0),this._mask=a}}),Object.defineProperty(f.DisplayObject.prototype,"filters",{get:function(){return this._filters},set:function(a){if(a){this._filters&&this.removeFilter(this._filters),this.addFilter(a);for(var b=[],c=0;c=0&&b<=this.children.length))throw new Error(a+" The index "+b+" supplied is out of bounds "+this.children.length);if(void 0!=a.parent&&a.parent.removeChild(a),a.parent=this,this.stage){var c=a;do c.interactive&&(this.stage.dirty=!0),c.stage=this.stage,c=c._iNext;while(c)}var d,e,f=a.first,g=a.last;if(b==this.children.length){e=this.last;for(var h=this,i=this.last;h;)h.last==i&&(h.last=a.last),h=h.parent}else e=0==b?this:this.children[b-1].last;d=e._iNext,d&&(d._iPrev=g,g._iNext=d),f._iPrev=e,e._iNext=f,this.children.splice(b,0,a),this.__renderGroup&&(a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a),this.__renderGroup.addDisplayObjectAndChildren(a))},f.DisplayObjectContainer.prototype.swapChildren=function(){},f.DisplayObjectContainer.prototype.getChildAt=function(a){if(a>=0&&aa;a++)this.children[a].updateTransform()}},f.blendModes={},f.blendModes.NORMAL=0,f.blendModes.SCREEN=1,f.Sprite=function(a){f.DisplayObjectContainer.call(this),this.anchor=new f.Point,this.texture=a,this.blendMode=f.blendModes.NORMAL,this._width=0,this._height=0,a.baseTexture.hasLoaded?this.updateFrame=!0:(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Sprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Sprite.prototype.constructor=f.Sprite,Object.defineProperty(f.Sprite.prototype,"width",{get:function(){return this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(f.Sprite.prototype,"height",{get:function(){return this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),f.Sprite.prototype.setTexture=function(a){this.texture.baseTexture!=a.baseTexture?(this.textureChange=!0,this.texture=a,this.__renderGroup&&this.__renderGroup.updateTexture(this)):this.texture=a,this.updateFrame=!0},f.Sprite.prototype.onTextureUpdate=function(){this._width&&(this.scale.x=this._width/this.texture.frame.width),this._height&&(this.scale.y=this._height/this.texture.frame.height),this.updateFrame=!0},f.Sprite.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache"+this);return new f.Sprite(b)},f.Sprite.fromImage=function(a){var b=f.Texture.fromImage(a);return new f.Sprite(b)},f.MovieClip=function(a){f.Sprite.call(this,a[0]),this.textures=a,this.animationSpeed=1,this.loop=!0,this.onComplete=null,this.currentFrame=0,this.playing=!1},f.MovieClip.prototype=Object.create(f.Sprite.prototype),f.MovieClip.prototype.constructor=f.MovieClip,Object.defineProperty(f.MovieClip.prototype,"totalFrames",{get:function(){return this.textures.length}}),f.MovieClip.prototype.stop=function(){this.playing=!1},f.MovieClip.prototype.play=function(){this.playing=!0},f.MovieClip.prototype.gotoAndStop=function(a){this.playing=!1,this.currentFrame=a;var b=0|this.currentFrame+.5;this.setTexture(this.textures[b%this.textures.length])},f.MovieClip.prototype.gotoAndPlay=function(a){this.currentFrame=a,this.playing=!0},f.MovieClip.prototype.updateTransform=function(){if(f.Sprite.prototype.updateTransform.call(this),this.playing){this.currentFrame+=this.animationSpeed;var a=0|this.currentFrame+.5;this.loop||a=this.textures.length&&(this.gotoAndStop(this.textures.length-1),this.onComplete&&this.onComplete())}},f.FilterBlock=function(){this.visible=!0,this.renderable=!0},f.Text=function(a,b){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),f.Sprite.call(this,f.Texture.fromCanvas(this.canvas)),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.Text.prototype=Object.create(f.Sprite.prototype),f.Text.prototype.constructor=f.Text,f.Text.prototype.setStyle=function(a){a=a||{},a.font=a.font||"bold 20pt Arial",a.fill=a.fill||"black",a.align=a.align||"left",a.stroke=a.stroke||"black",a.strokeThickness=a.strokeThickness||0,a.wordWrap=a.wordWrap||!1,a.wordWrapWidth=a.wordWrapWidth||100,this.style=a,this.dirty=!0},f.Text.prototype.setText=function(a){this.text=a.toString()||" ",this.dirty=!0},f.Text.prototype.updateText=function(){this.context.font=this.style.font;var a=this.text;this.style.wordWrap&&(a=this.wordWrap(this.text));for(var b=a.split(/(?:\r\n|\r|\n)/),c=[],d=0,e=0;ee?f:arguments.callee(a,b,f,d,e):arguments.callee(a,b,c,f,e)},c=function(a,c,d){if(a.measureText(c).width<=d||c.length<1)return c;var e=b(a,c,0,c.length,d);return c.substring(0,e)+"\n"+arguments.callee(a,c.substring(e),d)},d="",e=a.split("\n"),f=0;f=2?parseInt(b[b.length-2],10):f.BitmapText.fonts[this.fontName].size,this.dirty=!0},f.BitmapText.prototype.updateText=function(){for(var a=f.BitmapText.fonts[this.fontName],b=new f.Point,c=null,d=[],e=0,g=[],h=0,i=this.fontSize/a.size,j=0;j=j;j++){var n=0;"right"==this.style.align?n=e-g[j]:"center"==this.style.align&&(n=(e-g[j])/2),m.push(n)}for(j=0;j0;)this.removeChild(this.getChildAt(0));this.updateText(),this.dirty=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.BitmapText.fonts={},f.InteractionManager=function(a){this.stage=a,this.mouse=new f.InteractionData,this.touchs={},this.tempPoint=new f.Point,this.mouseoverEnabled=!0,this.pool=[],this.interactiveItems=[],this.interactionDOMElement=null,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseOut=this.onMouseOut.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.last=0},f.InteractionManager.prototype.constructor=f.InteractionManager,f.InteractionManager.prototype.collectInteractiveSprite=function(a,b){for(var c=a.children,d=c.length,e=d-1;e>=0;e--){var f=c[e];f.interactive?(b.interactiveChildren=!0,this.interactiveItems.push(f),f.children.length>0&&this.collectInteractiveSprite(f,f)):(f.__iParent=null,f.children.length>0&&this.collectInteractiveSprite(f,b))}},f.InteractionManager.prototype.setTarget=function(a){this.target=a,null===this.interactionDOMElement&&this.setTargetDomElement(a.view),document.body.addEventListener("mouseup",this.onMouseUp,!0)},f.InteractionManager.prototype.setTargetDomElement=function(a){null!==this.interactionDOMElement&&(this.interactionDOMElement.style["-ms-content-zooming"]="",this.interactionDOMElement.style["-ms-touch-action"]="",this.interactionDOMElement.removeEventListener("mousemove",this.onMouseMove,!0),this.interactionDOMElement.removeEventListener("mousedown",this.onMouseDown,!0),this.interactionDOMElement.removeEventListener("mouseout",this.onMouseOut,!0),this.interactionDOMElement.removeEventListener("touchstart",this.onTouchStart,!0),this.interactionDOMElement.removeEventListener("touchend",this.onTouchEnd,!0),this.interactionDOMElement.removeEventListener("touchmove",this.onTouchMove,!0)),window.navigator.msPointerEnabled&&(a.style["-ms-content-zooming"]="none",a.style["-ms-touch-action"]="none"),this.interactionDOMElement=a,a.addEventListener("mousemove",this.onMouseMove,!0),a.addEventListener("mousedown",this.onMouseDown,!0),a.addEventListener("mouseout",this.onMouseOut,!0),a.addEventListener("touchstart",this.onTouchStart,!0),a.addEventListener("touchend",this.onTouchEnd,!0),a.addEventListener("touchmove",this.onTouchMove,!0)},f.InteractionManager.prototype.update=function(){if(this.target){var a=Date.now(),b=a-this.last;if(b=30*b/1e3,!(1>b)){if(this.last=a,this.dirty){this.dirty=!1;for(var c=this.interactiveItems.length,d=0;c>d;d++)this.interactiveItems[d].interactiveChildren=!1;this.interactiveItems=[],this.stage.interactive&&this.interactiveItems.push(this.stage),this.collectInteractiveSprite(this.stage,this.stage)}var e=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var d=0;e>d;d++){var f=this.interactiveItems[d];(f.mouseover||f.mouseout||f.buttonMode)&&(f.__hit=this.hitTest(f,this.mouse),this.mouse.target=f,f.__hit?(f.buttonMode&&(this.interactionDOMElement.style.cursor="pointer"),f.__isOver||(f.mouseover&&f.mouseover(this.mouse),f.__isOver=!0)):f.__isOver&&(f.mouseout&&f.mouseout(this.mouse),f.__isOver=!1))}}}},f.InteractionManager.prototype.onMouseMove=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactionDOMElement.getBoundingClientRect();this.mouse.global.x=(a.clientX-b.left)*(this.target.width/b.width),this.mouse.global.y=(a.clientY-b.top)*(this.target.height/b.height);var c=this.interactiveItems.length;this.mouse.global;for(var d=0;c>d;d++){var e=this.interactiveItems[d];e.mousemove&&e.mousemove(this.mouse)}},f.InteractionManager.prototype.onMouseDown=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactiveItems.length;this.mouse.global,this.stage;for(var c=0;b>c;c++){var d=this.interactiveItems[c];if((d.mousedown||d.click)&&(d.__mouseIsDown=!0,d.__hit=this.hitTest(d,this.mouse),d.__hit&&(d.mousedown&&d.mousedown(this.mouse),d.__isDown=!0,!d.interactiveChildren)))break}},f.InteractionManager.prototype.onMouseOut=function(){var a=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var b=0;a>b;b++){var c=this.interactiveItems[b];c.__isOver&&(this.mouse.target=c,c.mouseout&&c.mouseout(this.mouse),c.__isOver=!1)}},f.InteractionManager.prototype.onMouseUp=function(a){this.mouse.originalEvent=a||window.event,this.mouse.global;for(var b=this.interactiveItems.length,c=!1,d=0;b>d;d++){var e=this.interactiveItems[d];(e.mouseup||e.mouseupoutside||e.click)&&(e.__hit=this.hitTest(e,this.mouse),e.__hit&&!c?(e.mouseup&&e.mouseup(this.mouse),e.__isDown&&e.click&&e.click(this.mouse),e.interactiveChildren||(c=!0)):e.__isDown&&e.mouseupoutside&&e.mouseupoutside(this.mouse),e.__isDown=!1)}},f.InteractionManager.prototype.hitTest=function(a,b){var c=b.global;if(a.vcount!==f.visibleCount)return!1;var d=a instanceof f.Sprite,e=a.worldTransform,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=1/(g*k+h*-j),n=k*m*c.x+-h*m*c.y+(l*h-i*k)*m,o=g*m*c.y+-j*m*c.x+(-l*g+i*j)*m;if(b.target=a,a.hitArea&&a.hitArea.contains)return a.hitArea.contains(n,o)?(b.target=a,!0):!1;if(d){var p,q=a.texture.frame.width,r=a.texture.frame.height,s=-q*a.anchor.x;if(n>s&&s+q>n&&(p=-r*a.anchor.y,o>p&&p+r>o))return b.target=a,!0}for(var t=a.children.length,u=0;t>u;u++){var v=a.children[u],w=this.hitTest(v,b);if(w)return b.target=a,!0}return!1},f.InteractionManager.prototype.onTouchMove=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;dd;d++){var h=this.interactiveItems[d];h.touchmove&&h.touchmove(f)}},f.InteractionManager.prototype.onTouchStart=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i];if((j.touchstart||j.tap)&&(j.__hit=this.hitTest(j,g),j.__hit&&(j.touchstart&&j.touchstart(g),j.__isDown=!0,j.__touchData=g,!j.interactiveChildren)))break}}},f.InteractionManager.prototype.onTouchEnd=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i],k=j.__touchData;j.__hit=this.hitTest(j,f),k==f&&(f.originalEvent=a||window.event,(j.touchend||j.tap)&&(j.__hit&&!g?(j.touchend&&j.touchend(f),j.__isDown&&j.tap&&j.tap(f),j.interactiveChildren||(g=!0)):j.__isDown&&j.touchendoutside&&j.touchendoutside(f),j.__isDown=!1),j.__touchData=null)}this.pool.push(f),this.touchs[e.identifier]=null}},f.InteractionData=function(){this.global=new f.Point,this.local=new f.Point,this.target,this.originalEvent},f.InteractionData.prototype.getLocalPosition=function(a){var b=a.worldTransform,c=this.global,d=b[0],e=b[1],g=b[2],h=b[3],i=b[4],j=b[5],k=1/(d*i+e*-h);return new f.Point(i*k*c.x+-e*k*c.y+(j*e-g*i)*k,d*k*c.y+-h*k*c.x+(-j*d+g*h)*k)},f.InteractionData.prototype.constructor=f.InteractionData,f.Stage=function(a){f.DisplayObjectContainer.call(this),this.worldTransform=f.mat3.create(),this.interactive=!0,this.interactionManager=new f.InteractionManager(this),this.dirty=!0,this.__childrenAdded=[],this.__childrenRemoved=[],this.stage=this,this.stage.hitArea=new f.Rectangle(0,0,1e5,1e5),this.setBackgroundColor(a),this.worldVisible=!0},f.Stage.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Stage.prototype.constructor=f.Stage,f.Stage.prototype.setInteractionDelegate=function(a){this.interactionManager.setTargetDomElement(a)},f.Stage.prototype.updateTransform=function(){this.worldAlpha=1,this.vcount=f.visibleCount;for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform();this.dirty&&(this.dirty=!1,this.interactionManager.dirty=!0),this.interactive&&this.interactionManager.update()},f.Stage.prototype.setBackgroundColor=function(a){this.backgroundColor=a||0,this.backgroundColorSplit=d(this.backgroundColor);var b=this.backgroundColor.toString(16);b="000000".substr(0,6-b.length)+b,this.backgroundColorString="#"+b},f.Stage.prototype.getMousePosition=function(){return this.interactionManager.mouse.global};for(var h=0,i=["ms","moz","webkit","o"],j=0;j>>>>>>>>"),console.log("_");var b=0,c=a.first;for(console.log(c);c._iNext;)if(b++,c=c._iNext,console.log(c),b>100){console.log("BREAK");break}},f.EventTarget=function(){var a={};this.addEventListener=this.on=function(b,c){void 0===a[b]&&(a[b]=[]),-1===a[b].indexOf(c)&&a[b].push(c)},this.dispatchEvent=this.emit=function(b){if(a[b.type]&&a[b.type].length)for(var c=0,d=a[b.type].length;d>c;c++)a[b.type][c](b)},this.removeEventListener=this.off=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)}},f.autoDetectRenderer=function(a,b,c,d,e){a||(a=800),b||(b=600);var g=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}();if(g){var h=-1!=navigator.userAgent.toLowerCase().indexOf("msie");g=!h}return g?new f.WebGLRenderer(a,b,c,d,e):new f.CanvasRenderer(a,b,c,d)},f.PolyK={},f.PolyK.Triangulate=function(a){var b=!0,c=a.length>>1;if(3>c)return[];for(var d=[],e=[],g=0;c>g;g++)e.push(g);for(var g=0,h=c;h>3;){var i=e[(g+0)%h],j=e[(g+1)%h],k=e[(g+2)%h],l=a[2*i],m=a[2*i+1],n=a[2*j],o=a[2*j+1],p=a[2*k],q=a[2*k+1],r=!1;if(f.PolyK._convex(l,m,n,o,p,q,b)){r=!0;for(var s=0;h>s;s++){var t=e[s];if(t!=i&&t!=j&&t!=k&&f.PolyK._PointInTriangle(a[2*t],a[2*t+1],l,m,n,o,p,q)){r=!1;break}}}if(r)d.push(i,j,k),e.splice((g+1)%h,1),h--,g=0;else if(g++>3*h){if(!b)return console.log("PIXI Warning: shape too complex to fill"),[];var d=[];e=[];for(var g=0;c>g;g++)e.push(g);g=0,h=c,b=!1}}return d.push(e[0],e[1],e[2]),d},f.PolyK._PointInTriangle=function(a,b,c,d,e,f,g,h){var i=g-c,j=h-d,k=e-c,l=f-d,m=a-c,n=b-d,o=i*i+j*j,p=i*k+j*l,q=i*m+j*n,r=k*k+l*l,s=k*m+l*n,t=1/(o*r-p*p),u=(r*q-p*s)*t,v=(o*s-p*q)*t;return u>=0&&v>=0&&1>u+v},f.PolyK._convex=function(a,b,c,d,e,f,g){return(b-d)*(e-c)+(c-a)*(f-d)>=0==g},f.initDefaultShaders=function(){f.primitiveShader=new f.PrimitiveShader,f.primitiveShader.init(),f.stripShader=new f.StripShader,f.stripShader.init(),f.defaultShader=new f.PixiShader,f.defaultShader.init();var a=f.gl,b=f.defaultShader.program;a.useProgram(b),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.primitiveShader.program),a.disableVertexAttribArray(f.defaultShader.aTextureCoord)},f.deactivatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activateStripShader=function(){var a=f.gl;a.useProgram(f.stripShader.program)},f.deactivateStripShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program)},f.CompileVertexShader=function(a,b){return f._CompileShader(a,b,a.VERTEX_SHADER)},f.CompileFragmentShader=function(a,b){return f._CompileShader(a,b,a.FRAGMENT_SHADER)},f._CompileShader=function(a,b,c){var d=b.join("\n"),e=a.createShader(c);return a.shaderSource(e,d),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)?e:(console.log(a.getShaderInfoLog(e)),null)},f.compileProgram=function(a,b){var c=f.gl,d=f.CompileFragmentShader(c,b),e=f.CompileVertexShader(c,a),g=c.createProgram();return c.attachShader(g,e),c.attachShader(g,d),c.linkProgram(g),c.getProgramParameter(g,c.LINK_STATUS)||console.log("Could not initialise shaders"),g},f.PixiShader=function(){this.program,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;","}"]},f.PixiShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc||f.PixiShader.defaultVertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"); +for(var c in this.uniforms)a[c]=b.getUniformLocation(a,c);this.program=a},f.PixiShader.prototype.syncUniforms=function(){var a=f.gl;for(var b in this.uniforms){var c=this.uniforms[b].type;if("f"==c&&a.uniform1f(this.program[b],this.uniforms[b].value),"f2"==c)a.uniform2f(this.program[b],this.uniforms[b].value.x,this.uniforms[b].value.y);else if("f4"==c)a.uniform4fv(this.program[b],this.uniforms[b].value);else if("mat4"==c)a.uniformMatrix4fv(this.program[b],!1,this.uniforms[b].value);else if("sampler2D"==c){var d=this.uniforms[b].value;a.activeTexture(a.TEXTURE1),a.bindTexture(a.TEXTURE_2D,d.baseTexture._glTexture),a.uniform1i(this.program[b],1)}}},f.PixiShader.defaultVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","varying float vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"],f.StripShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying float vColor;","uniform float alpha;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));","gl_FragColor = gl_FragColor * alpha;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","varying vec2 vTextureCoord;","varying vec2 offsetVector;","varying float vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"]},f.StripShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.PrimitiveShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","gl_FragColor = vColor;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec4 aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform float alpha;","varying vec4 vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","vColor = aColor * alpha;","}"]},f.PrimitiveShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.WebGLGraphics=function(){},f.WebGLGraphics.renderGraphics=function(a,b){var c=f.gl;a._webGL||(a._webGL={points:[],indices:[],lastIndex:0,buffer:c.createBuffer(),indexBuffer:c.createBuffer()}),a.dirty&&(a.dirty=!1,a.clearDirty&&(a.clearDirty=!1,a._webGL.lastIndex=0,a._webGL.points=[],a._webGL.indices=[]),f.WebGLGraphics.updateGraphics(a)),f.activatePrimitiveShader();var d=f.mat3.clone(a.worldTransform);f.mat3.transpose(d),c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA),c.uniformMatrix3fv(f.primitiveShader.translationMatrix,!1,d),c.uniform2f(f.primitiveShader.projectionVector,b.x,-b.y),c.uniform2f(f.primitiveShader.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(f.primitiveShader.alpha,a.worldAlpha),c.bindBuffer(c.ARRAY_BUFFER,a._webGL.buffer),c.vertexAttribPointer(f.primitiveShader.aVertexPosition,2,c.FLOAT,!1,24,0),c.vertexAttribPointer(f.primitiveShader.colorAttribute,4,c.FLOAT,!1,24,8),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),c.drawElements(c.TRIANGLE_STRIP,a._webGL.indices.length,c.UNSIGNED_SHORT,0),f.deactivatePrimitiveShader()},f.WebGLGraphics.updateGraphics=function(a){for(var b=a._webGL.lastIndex;b3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){var e=new f.Point(c[0],c[1]),g=new f.Point(c[c.length-2],c[c.length-1]);if(e.x==g.x&&e.y==g.y){c.pop(),c.pop(),g=new f.Point(c[c.length-2],c[c.length-1]);var h=g.x+.5*(e.x-g.x),i=g.y+.5*(e.y-g.y);c.unshift(h,i),c.push(h,i)}var j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E=b.points,F=b.indices,G=c.length/2,H=c.length,I=E.length/6,J=a.lineWidth/2,K=d(a.lineColor),L=a.lineAlpha,M=K[0]*L,N=K[1]*L,O=K[2]*L;j=c[0],k=c[1],l=c[2],m=c[3],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,E.push(j-p,k-q,M,N,O,L),E.push(j+p,k+q,M,N,O,L);for(var P=1;G-1>P;P++)j=c[2*(P-1)],k=c[2*(P-1)+1],l=c[2*P],m=c[2*P+1],n=c[2*(P+1)],o=c[2*(P+1)+1],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,r=-(m-o),s=l-n,D=Math.sqrt(r*r+s*s),r/=D,s/=D,r*=J,s*=J,v=-q+k-(-q+m),w=-p+l-(-p+j),x=(-p+j)*(-q+m)-(-p+l)*(-q+k),y=-s+o-(-s+m),z=-r+l-(-r+n),A=(-r+n)*(-s+m)-(-r+l)*(-s+o),B=v*z-y*w,0==B&&(B+=1),px=(w*A-z*x)/B,py=(y*x-v*A)/B,C=(px-l)*(px-l)+(py-m)+(py-m),C>19600?(t=p-r,u=q-s,D=Math.sqrt(t*t+u*u),t/=D,u/=D,t*=J,u*=J,E.push(l-t,m-u),E.push(M,N,O,L),E.push(l+t,m+u),E.push(M,N,O,L),E.push(l-t,m-u),E.push(M,N,O,L),H++):(E.push(px,py),E.push(M,N,O,L),E.push(l-(px-l),m-(py-m)),E.push(M,N,O,L));j=c[2*(G-2)],k=c[2*(G-2)+1],l=c[2*(G-1)],m=c[2*(G-1)+1],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,E.push(l-p,m-q),E.push(M,N,O,L),E.push(l+p,m+q),E.push(M,N,O,L),F.push(I);for(var P=0;H>P;P++)F.push(I++);F.push(I-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;a.open?a.data instanceof Array?this.filterManager.pushFilter(a):(c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,255),c.stencilOp(c.KEEP,c.KEEP,c.REPLACE),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,255),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)):a.data instanceof Array?this.filterManager.popFilter():c.disable(c.STENCIL_TEST)},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(){this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;hs?s:E,E=E>t?t:E,E=E>u?u:E,E=E>v?v:E,F=F>w?w:F,F=F>x?x:F,F=F>y?y:F,F=F>z?z:F,C=s>C?s:C,C=t>C?t:C,C=u>C?u:C,C=v>C?v:C,D=w>D?w:D,D=x>D?x:D,D=y>D?y:D,D=z>D?z:D),l=!1,A=A._iNext}while(A!=B);a.filterArea.x=E,a.filterArea.y=F,a.filterArea.width=C-E,a.filterArea.height=D-F},f.FilterTexture=function(a,b){var c=f.gl;this.frameBuffer=c.createFramebuffer(),this.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,this.texture),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.bindFramebuffer(c.FRAMEBUFFER,this.framebuffer),c.bindFramebuffer(c.FRAMEBUFFER,this.frameBuffer),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,this.texture,0),this.resize(a,b)},f.FilterTexture.prototype.resize=function(a,b){this.width=a,this.height=b;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a,b,0,c.RGBA,c.UNSIGNED_BYTE,null)},f.CanvasRenderer=function(a,b,c,d){this.transparent=d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.context=this.view.getContext("2d"),this.refresh=!0,this.view.width=this.width,this.view.height=this.height,this.count=0},f.CanvasRenderer.prototype.constructor=f.CanvasRenderer,f.CanvasRenderer.prototype.render=function(a){f.texturesToUpdate=[],f.texturesToDestroy=[],f.visibleCount++,a.updateTransform(),this.view.style.backgroundColor==a.backgroundColorString||this.transparent||(this.view.style.backgroundColor=a.backgroundColorString),this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.width,this.height),this.renderDisplayObject(a),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0&&(f.Texture.frameUpdates=[])},f.CanvasRenderer.prototype.resize=function(a,b){this.width=a,this.height=b,this.view.width=a,this.view.height=b},f.CanvasRenderer.prototype.renderDisplayObject=function(a){var b,c=this.context;c.globalCompositeOperation="source-over";var d=a.last._iNext;a=a.first;do if(b=a.worldTransform,a.visible)if(a.renderable){if(a instanceof f.Sprite){var e=a.texture.frame;e&&e.width&&e.height&&(c.globalAlpha=a.worldAlpha,c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),c.drawImage(a.texture.baseTexture.source,e.x,e.y,e.width,e.height,a.anchor.x*-e.width,a.anchor.y*-e.height,e.width,e.height))}else if(a instanceof f.Strip)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderStrip(a);else if(a instanceof f.TilingSprite)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderTilingSprite(a);else if(a instanceof f.CustomRenderable)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),a.renderCanvas(this);else if(a instanceof f.Graphics)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),f.CanvasGraphics.renderGraphics(a,c);else if(a instanceof f.FilterBlock&&a.data instanceof f.Graphics){var g=a.data;if(a.open){c.save();var h=g.alpha,i=g.worldTransform;c.setTransform(i[0],i[3],i[1],i[4],i[2],i[5]),g.worldAlpha=.5,c.worldAlpha=0,f.CanvasGraphics.renderGraphicsMask(g,c),c.clip(),g.worldAlpha=h}else c.restore()}a=a._iNext}else a=a._iNext;else a=a.last._iNext;while(a!=d)},f.CanvasRenderer.prototype.renderStripFlat=function(a){var b=this.context,c=a.verticies;a.uvs;var d=c.length/2;this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},f.CanvasRenderer.prototype.renderTilingSprite=function(a){var b=this.context;b.globalAlpha=a.worldAlpha,a.__tilePattern||(a.__tilePattern=b.createPattern(a.texture.baseTexture.source,"repeat")),b.beginPath();var c=a.tilePosition,d=a.tileScale;b.scale(d.x,d.y),b.translate(c.x,c.y),b.fillStyle=a.__tilePattern,b.fillRect(-c.x,-c.y,a.width/d.x,a.height/d.y),b.scale(1/d.x,1/d.y),b.translate(-c.x,-c.y),b.closePath()},f.CanvasRenderer.prototype.renderStrip=function(a){var b=this.context,c=a.verticies,d=a.uvs,e=c.length/2;this.count++;for(var f=1;e-2>f;f++){var g=2*f,h=c[g],i=c[g+2],j=c[g+4],k=c[g+1],l=c[g+3],m=c[g+5],n=d[g]*a.texture.width,o=d[g+2]*a.texture.width,p=d[g+4]*a.texture.width,q=d[g+1]*a.texture.height,r=d[g+3]*a.texture.height,s=d[g+5]*a.texture.height;b.save(),b.beginPath(),b.moveTo(h,k),b.lineTo(i,l),b.lineTo(j,m),b.closePath(),b.clip();var t=n*r+q*p+o*s-r*p-q*o-n*s,u=h*r+q*j+i*s-r*j-q*i-h*s,v=n*i+h*p+o*j-i*p-h*o-n*j,w=n*r*j+q*i*p+h*o*s-h*r*p-q*o*j-n*i*s,x=k*r+q*m+l*s-r*m-q*l-k*s,y=n*l+k*p+o*m-l*p-k*o-n*m,z=n*r*m+q*l*p+k*o*s-k*r*p-q*o*m-n*l*s;b.transform(u/t,x/t,v/t,y/t,w/t,z/t),b.drawImage(a.texture.baseTexture.source,0,0),b.restore()}},f.CanvasGraphics=function(){},f.CanvasGraphics.renderGraphics=function(a,b){for(var c=a.worldAlpha,d=0;d1&&(c=1,console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var d=0;1>d;d++){var e=a.graphicsData[d],g=e.points;if(e.type==f.Graphics.POLY){b.beginPath(),b.moveTo(g[0],g[1]);for(var h=1;hb?b:d,e=b+m>e?b+m:e,g=g>c?b:g,h=c+n>h?c+n:h}else if(k===f.Graphics.CIRC||k===f.Graphics.ELIP){b=a.x,c=a.y;var o=a.radius+l/2;d=d>b-o?b-o:d,e=b+o>e?b+o:e,g=g>c-o?c-o:g,h=c+o>h?c+o:h}else for(var p=0;pb-l?b-l:d,e=b+l>e?b+l:e,g=g>c-l?c-l:g,h=c+l>h?c+l:h}this.bounds=new f.Rectangle(d,g,e-d,h-g)}},f.Graphics.POLY=0,f.Graphics.RECT=1,f.Graphics.CIRC=2,f.Graphics.ELIP=3,f.Strip=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.blendMode=f.blendModes.NORMAL;try{this.uvs=new Float32Array([0,1,1,1,1,0,0,1]),this.verticies=new Float32Array([0,0,0,0,0,0,0,0,0]),this.colors=new Float32Array([1,1,1,1]),this.indices=new Uint16Array([0,1,2,3])}catch(d){this.uvs=[0,1,1,1,1,0,0,1],this.verticies=[0,0,0,0,0,0,0,0,0],this.colors=[1,1,1,1],this.indices=[0,1,2,3]}this.width=b,this.height=c,a.baseTexture.hasLoaded?(this.width=this.texture.frame.width,this.height=this.texture.frame.height,this.updateFrame=!0):(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Strip.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Strip.prototype.constructor=f.Strip,f.Strip.prototype.setTexture=function(a){this.texture=a,this.width=a.frame.width,this.height=a.frame.height,this.updateFrame=!0},f.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Rope=function(a,b){f.Strip.call(this,a),this.points=b;try{this.verticies=new Float32Array(4*b.length),this.uvs=new Float32Array(4*b.length),this.colors=new Float32Array(2*b.length),this.indices=new Uint16Array(2*b.length)}catch(c){this.verticies=verticies,this.uvs=uvs,this.colors=colors,this.indices=indices}this.refresh()},f.Rope.prototype=Object.create(f.Strip.prototype),f.Rope.prototype.constructor=f.Rope,f.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=this.indices,d=this.colors,e=a[0],f=a[0];this.count-=.2,b[0]=0,b[1]=1,b[2]=0,b[3]=1,d[0]=1,d[1]=1,c[0]=0,c[1]=1;for(var g=a.length,h=1;g>h;h++){var f=a[h],i=4*h,j=h/(g-1);h%2?(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1):(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1),i=2*h,d[i]=1,d[i+1]=1,i=2*h,c[i]=i,c[i+1]=i+1,e=f}}},f.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var b,c=this.verticies,d=a[0],e={x:0,y:0},g=a[0];this.count-=.2,c[0]=g.x+e.x,c[1]=g.y+e.y,c[2]=g.x-e.x,c[3]=g.y-e.y;for(var h=a.length,i=1;h>i;i++){var g=a[i],j=4*i;b=i1&&(k=1);var l=Math.sqrt(e.x*e.x+e.y*e.y),m=this.texture.height/2;e.x/=l,e.y/=l,e.x*=m,e.y*=m,c[j]=g.x+e.x,c[j+1]=g.y+e.y,c[j+2]=g.x-e.x,c[j+3]=g.y-e.y,d=g}f.DisplayObjectContainer.prototype.updateTransform.call(this)}},f.Rope.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.width=b,this.height=c,this.tileScale=new f.Point(1,1),this.tilePosition=new f.Point(0,0),this.renderable=!0,this.blendMode=f.blendModes.NORMAL},f.TilingSprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.TilingSprite.prototype.constructor=f.TilingSprite,f.TilingSprite.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Spine=function(a){if(f.DisplayObjectContainer.call(this),this.spineData=f.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new l.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new l.AnimationStateData(this.spineData),this.state=new l.AnimationState(this.stateData),this.slotContainers=[];for(var b=0,c=this.skeleton.drawOrder.length;c>b;b++){var d=this.skeleton.drawOrder[b],e=d.attachment,g=new f.DisplayObjectContainer;if(this.slotContainers.push(g),this.addChild(g),e instanceof l.RegionAttachment){var h=e.rendererObject.name,i=this.createSprite(d,e.rendererObject);d.currentSprite=i,d.currentSpriteName=h,g.addChild(i)}}},f.Spine.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Spine.prototype.constructor=f.Spine,f.Spine.prototype.updateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var b=this.skeleton.drawOrder,c=0,d=b.length;d>c;c++){var e=b[c],g=e.attachment,h=this.slotContainers[c];if(g instanceof l.RegionAttachment){if(g.rendererObject&&(!e.currentSpriteName||e.currentSpriteName!=g.name)){var i=g.rendererObject.name;if(void 0!==e.currentSprite&&(e.currentSprite.visible=!1),e.sprites=e.sprites||{},void 0!==e.sprites[i])e.sprites[i].visible=!0;else{var j=this.createSprite(e,g.rendererObject);h.addChild(j)}e.currentSprite=e.sprites[i],e.currentSpriteName=i}h.visible=!0;var k=e.bone;h.position.x=k.worldX+g.x*k.m00+g.y*k.m01,h.position.y=k.worldY+g.x*k.m10+g.y*k.m11,h.scale.x=k.worldScaleX,h.scale.y=k.worldScaleY,h.rotation=-(e.bone.worldRotation*Math.PI/180)}else h.visible=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.Spine.prototype.createSprite=function(a,b){var c=f.TextureCache[b.name]?b.name:b.name+".png",d=new f.Sprite(f.Texture.fromFrame(c));return d.scale=b.scale,d.rotation=b.rotation,d.anchor.x=d.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[b.name]=d,d};var l={};l.BoneData=function(a,b){this.name=a,this.parent=b},l.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1},l.SlotData=function(a,b){this.name=a,this.boneData=b},l.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null},l.Bone=function(a,b){this.data=a,this.parent=b,this.setToSetupPose()},l.Bone.yDown=!1,l.Bone.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,updateWorldTransform:function(a,b){var c=this.parent;null!=c?(this.worldX=this.x*c.m00+this.y*c.m01+c.worldX,this.worldY=this.x*c.m10+this.y*c.m11+c.worldY,this.worldScaleX=c.worldScaleX*this.scaleX,this.worldScaleY=c.worldScaleY*this.scaleY,this.worldRotation=c.worldRotation+this.rotation):(this.worldX=this.x,this.worldY=this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotation);var d=this.worldRotation*Math.PI/180,e=Math.cos(d),f=Math.sin(d);this.m00=e*this.worldScaleX,this.m10=f*this.worldScaleX,this.m01=-f*this.worldScaleY,this.m11=e*this.worldScaleY,a&&(this.m00=-this.m00,this.m01=-this.m01),b&&(this.m10=-this.m10,this.m11=-this.m11),l.Bone.yDown&&(this.m10=-this.m10,this.m11=-this.m11)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY}},l.Slot=function(a,b,c){this.data=a,this.skeleton=b,this.bone=c,this.setToSetupPose()},l.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,setAttachment:function(a){this.attachment=a,this._attachmentTime=this.skeleton.time},setAttachmentTime:function(a){this._attachmentTime=this.skeleton.time-a},getAttachmentTime:function(){return this.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},l.Skin=function(a){this.name=a,this.attachments={}},l.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},l.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},l.Animation.prototype={apply:function(a,b,c){c&&0!=this.duration&&(b%=this.duration);for(var d=this.timelines,e=0,f=d.length;f>e;e++)d[e].apply(a,b,1)},mix:function(a,b,c,d){c&&0!=this.duration&&(b%=this.duration);for(var e=this.timelines,f=0,g=e.length;g>f;f++)e[f].apply(a,b,d)}},l.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(0==e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},l.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},l.Curves=function(a){this.curves=[],this.curves.length=6*(a-1)},l.Curves.prototype={setLinear:function(a){this.curves[6*a]=0},setStepped:function(a){this.curves[6*a]=-1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=6*a,r=this.curves;r[q]=b*i+m*j+o*h,r[q+1]=c*i+n*j+p*h,r[q+2]=m*k+o*l,r[q+3]=n*k+p*l,r[q+4]=o*l,r[q+5]=p*l},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=6*a,d=this.curves,e=d[c];if(!e)return b;if(-1==e)return 0;for(var f=d[c+1],g=d[c+2],h=d[c+3],i=d[c+4],j=d[c+5],k=e,l=f,m=8;;){if(k>=b){var n=k-e,o=l-f;return o+(l-o)*(b-n)/(k-n)}if(0==m)break;m--,e+=g,f+=h,g+=i,h+=j,k+=e,l+=f}return l+(1-l)*(b-k)/(1-k)}},l.RotateTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=2*a},l.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-2]){for(var f=e.data.rotation+d[d.length-1]-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;return e.rotation+=f*c,void 0}var g=l.binarySearch(d,b,2),h=d[g-1],i=d[g],j=1-(b-i)/(d[g-2]-i);j=this.curves.getCurvePercent(g/2-1,j);for(var f=d[g+1]-h;f>180;)f-=360;for(;-180>f;)f+=360;for(f=e.data.rotation+(h+f*j)-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;e.rotation+=f*c}}},l.TranslateTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=3*a},l.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.x+=(e.data.x+d[d.length-2]-e.x)*c,e.y+=(e.data.y+d[d.length-1]-e.y)*c,void 0;var f=l.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.x+=(e.data.x+g+(d[f+1]-g)*j-e.x)*c,e.y+=(e.data.y+h+(d[f+2]-h)*j-e.y)*c}}},l.ScaleTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=3*a},l.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.scaleX+=(e.data.scaleX-1+d[d.length-2]-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+d[d.length-1]-e.scaleY)*c,void 0;var f=l.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.scaleX+=(e.data.scaleX-1+g+(d[f+1]-g)*j-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+h+(d[f+2]-h)*j-e.scaleY)*c}}},l.ColorTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=5*a},l.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(c,d){c*=5,this.frames[c]=d,this.frames[c+1]=r,this.frames[c+2]=g,this.frames[c+3]=b,this.frames[c+4]=a},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-5]){var f=d.length-1;return e.r=d[f-3],e.g=d[f-2],e.b=d[f-1],e.a=d[f],void 0}var g=l.binarySearch(d,b,5),h=d[g-4],i=d[g-3],j=d[g-2],k=d[g-1],m=d[g],n=1-(b-m)/(d[g-5]-m);n=this.curves.getCurvePercent(g/5-1,n);var o=h+(d[g+1]-h)*n,p=i+(d[g+2]-i)*n,q=j+(d[g+3]-j)*n,r=k+(d[g+4]-k)*n;1>c?(e.r+=(o-e.r)*c,e.g+=(p-e.g)*c,e.b+=(q-e.b)*c,e.a+=(r-e.a)*c):(e.r=o,e.g=p,e.b=q,e.a=r)}}},l.AttachmentTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},l.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b){var c=this.frames;if(!(b=c[c.length-1]?c.length-1:l.binarySearch(c,b,1)-1;var e=this.attachmentNames[d];a.slots[this.slotIndex].setAttachment(e?a.getAttachmentBySlotIndex(this.slotIndex,e):null)}}},l.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.animations=[]},l.SkeletonData.prototype={defaultSkin:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},l.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,c=a.bones.length;c>b;b++){var d=a.bones[b],e=d.parent?this.bones[a.bones.indexOf(d.parent)]:null;this.bones.push(new l.Bone(d,e))}this.slots=[],this.drawOrder=[];for(var b=0,c=a.slots.length;c>b;b++){var f=a.slots[b],g=this.bones[a.bones.indexOf(f.boneData)],h=new l.Slot(f,this,g);this.slots.push(h),this.drawOrder.push(h)}},l.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateWorldTransform:function(){for(var a=this.flipX,b=this.flipY,c=this.bones,d=0,e=c.length;e>d;d++)c[d].updateWorldTransform(a,b)},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose()},setSlotsToSetupPose:function(){for(var a=this.slots,b=0,c=a.length;c>b;b++)a[b].setToSetupPose(b)},getRootBone:function(){return 0==this.bones.length?null:this.bones[0]},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a);if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){this.skin&&a&&a._attachAll(this,this.skin),this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.size;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachment(d,b),null==g))throw"Attachment not found: "+b+", for slot: "+a;return f.setAttachment(g),void 0}}throw"Slot not found: "+a},update:function(a){time+=a}},l.AttachmentType={region:0},l.RegionAttachment=function(){this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},l.RegionAttachment.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,c=-this.width/2*this.scaleX+this.regionOffsetX*a,d=-this.height/2*this.scaleY+this.regionOffsetY*b,e=c+this.regionWidth*a,f=d+this.regionHeight*b,g=this.rotation*Math.PI/180,h=Math.cos(g),i=Math.sin(g),j=c*h+this.x,k=c*i,l=d*h+this.y,m=d*i,n=e*h+this.x,o=e*i,p=f*h+this.y,q=f*i,r=this.offset;r[0]=j-m,r[1]=l+k,r[2]=j-q,r[3]=p+k,r[4]=n-q,r[5]=p+o,r[6]=n-m,r[7]=l+o},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},l.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},l.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=this.animationToMixTime[a.name+":"+b.name];return c?c:this.defaultMix}},l.AnimationState=function(a){this.data=a,this.queue=[]},l.AnimationState.prototype={current:null,previous:null,currentTime:0,previousTime:0,currentLoop:!1,previousLoop:!1,mixTime:0,mixDuration:0,update:function(a){if(this.currentTime+=a,this.previousTime+=a,this.mixTime+=a,this.queue.length>0){var b=this.queue[0];this.currentTime>=b.delay&&(this._setAnimation(b.animation,b.loop),this.queue.shift())}},apply:function(a){if(this.current)if(this.previous){this.previous.apply(a,this.previousTime,this.previousLoop);var b=this.mixTime/this.mixDuration;b>=1&&(b=1,this.previous=null),this.current.mix(a,this.currentTime,this.currentLoop,b)}else this.current.apply(a,this.currentTime,this.currentLoop)},clearAnimation:function(){this.previous=null,this.current=null,this.queue.length=0},_setAnimation:function(a,b){this.previous=null,a&&this.current&&(this.mixDuration=this.data.getMix(this.current,a),this.mixDuration>0&&(this.mixTime=0,this.previous=this.current,this.previousTime=this.currentTime,this.previousLoop=this.currentLoop)),this.current=a,this.currentLoop=b,this.currentTime=0},setAnimationByName:function(a,b){var c=this.data.skeletonData.findAnimation(a);if(!c)throw"Animation not found: "+a;this.setAnimation(c,b)},setAnimation:function(a,b){this.queue.length=0,this._setAnimation(a,b)},addAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;this.addAnimation(d,b,c)},addAnimation:function(a,b,c){var d={};if(d.animation=a,d.loop=b,!c||0>=c){var e=0==this.queue.length?this.current:this.queue[this.queue.length-1].animation;c=null!=e?e.duration-this.data.getMix(e,a)+(c||0):0}d.delay=c,this.queue.push(d)},isComplete:function(){return!this.current||this.currentTime>=this.current.duration}},l.SkeletonJson=function(a){this.attachmentLoader=a},l.SkeletonJson.prototype={scale:1,readSkeletonData:function(a){for(var b=new l.SkeletonData,c=a.bones,d=0,e=c.length;e>d;d++){var f=c[d],g=null;if(f.parent&&(g=b.findBone(f.parent),!g))throw"Parent bone not found: "+f.parent;var h=new l.BoneData(f.name,g);h.length=(f.length||0)*this.scale,h.x=(f.x||0)*this.scale,h.y=(f.y||0)*this.scale,h.rotation=f.rotation||0,h.scaleX=f.scaleX||1,h.scaleY=f.scaleY||1,b.bones.push(h)}for(var i=a.slots,d=0,e=i.length;e>d;d++){var j=i[d],h=b.findBone(j.bone);if(!h)throw"Slot bone not found: "+j.bone;var k=new l.SlotData(j.name,h),m=j.color;m&&(k.r=l.SkeletonJson.toColor(m,0),k.g=l.SkeletonJson.toColor(m,1),k.b=l.SkeletonJson.toColor(m,2),k.a=l.SkeletonJson.toColor(m,3)),k.attachmentName=j.attachment,b.slots.push(k)}var n=a.skins;for(var o in n)if(n.hasOwnProperty(o)){var p=n[o],q=new l.Skin(o);for(var r in p)if(p.hasOwnProperty(r)){var s=b.findSlotIndex(r),t=p[r];for(var u in t)if(t.hasOwnProperty(u)){var v=this.readAttachment(q,u,t[u]);null!=v&&q.addAttachment(s,u,v)}}b.skins.push(q),"default"==q.name&&(b.defaultSkin=q)}var w=a.animations;for(var x in w)w.hasOwnProperty(x)&&this.readAnimation(x,w[x],b);return b},readAttachment:function(a,b,c){b=c.name||b;var d=l.AttachmentType[c.type||"region"];if(d==l.AttachmentType.region){var e=new l.RegionAttachment;return e.x=(c.x||0)*this.scale,e.y=(c.y||0)*this.scale,e.scaleX=c.scaleX||1,e.scaleY=c.scaleY||1,e.rotation=c.rotation||0,e.width=(c.width||32)*this.scale,e.height=(c.height||32)*this.scale,e.updateOffset(),e.rendererObject={},e.rendererObject.name=b,e.rendererObject.scale={},e.rendererObject.scale.x=e.scaleX,e.rendererObject.scale.y=e.scaleY,e.rendererObject.rotation=-e.rotation*Math.PI/180,e +}throw"Unknown attachment type: "+d},readAnimation:function(a,b,c){var d=[],e=0,f=b.bones;for(var g in f)if(f.hasOwnProperty(g)){var h=c.findBoneIndex(g);if(-1==h)throw"Bone not found: "+g;var i=f[g];for(var j in i)if(i.hasOwnProperty(j)){var k=i[j];if("rotate"==j){var m=new l.RotateTimeline(k.length);m.boneIndex=h;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o];m.setFrame(n,q.time,q.angle),l.SkeletonJson.readCurve(m,n,q),n++}d.push(m),e=Math.max(e,m.frames[2*m.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var m,r=1;"scale"==j?m=new l.ScaleTimeline(k.length):(m=new l.TranslateTimeline(k.length),r=this.scale),m.boneIndex=h;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;m.setFrame(n,q.time,s,t),l.SkeletonJson.readCurve(m,n,q),n++}d.push(m),e=Math.max(e,m.frames[3*m.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var m=new l.ColorTimeline(k.length);m.slotIndex=x;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=l.SkeletonJson.toColor(y,0),A=l.SkeletonJson.toColor(y,1),B=l.SkeletonJson.toColor(y,2),C=l.SkeletonJson.toColor(y,3);m.setFrame(n,q.time,z,A,B,C),l.SkeletonJson.readCurve(m,n,q),n++}d.push(m),e=Math.max(e,m.frames[5*m.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var m=new l.AttachmentTimeline(k.length);m.slotIndex=x;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o];m.setFrame(n++,q.time,q.name)}d.push(m),e=Math.max(e,m.frames[m.getFrameCount()-1])}}}c.animations.push(new l.Animation(a,d,e))}},l.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},l.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},l.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new l.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new l.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new l.AtlasPage,e.name=f,e.format=l.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=l.Atlas.TextureFilter[d[0]],e.magFilter=l.Atlas.TextureFilter[d[1]];var m=c.readValue();e.uWrap=l.Atlas.TextureWrap.clampToEdge,e.vWrap=l.Atlas.TextureWrap.clampToEdge,"x"==m?e.uWrap=l.Atlas.TextureWrap.repeat:"y"==m?e.vWrap=l.Atlas.TextureWrap.repeat:"xy"==m&&(e.uWrap=e.vWrap=l.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},l.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},l.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},l.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},l.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},l.AtlasPage=function(){},l.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},l.AtlasRegion=function(){},l.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},l.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},l.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},l.AtlasAttachmentLoader=function(a){this.atlas=a},l.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case l.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new l.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},l.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;haN{WQE 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 BH&p-t literal 0 HcmV?d00001 diff --git a/examples/example 15 - Filters/displacement_BG.jpg b/examples/example 15 - Filters/displacement_BG.jpg index ab5c5cc7ffff213084df53ff90b3f77b6fd7a9fb..100b0cb0f671c7fac13bd95fe08b5d9d3f9385a8 100644 GIT binary patch delta 61304 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⁢mXW!^JW9de2dfb|k8x@gg+bd`+q3=eMV$ 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%0A5S? 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

RAft@f|?mM}OiK3p2YFVabps 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 + + + + + + + diff --git a/examples/example 15 - Filters/indexDisplacement_2.html b/examples/example 15 - Filters/indexDisplacement_2.html new file mode 100644 index 0000000..a20409b --- /dev/null +++ b/examples/example 15 - Filters/indexDisplacement_2.html @@ -0,0 +1,162 @@ + + + + pixi.js example 15 - Filters + + + + + + + + + + diff --git a/examples/example 15 - Filters/zeldaWaves.png b/examples/example 15 - Filters/zeldaWaves.png new file mode 100644 index 0000000000000000000000000000000000000000..01552c061c49d3fbb709cccbc7a328ad7e520aed GIT binary patch literal 38032 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 + + + + +

+
+
+ +

+ +
+
+ API Docs for: 1.3.0 +
+
+
+ + +
+
+ Show: + + + + + + + +
+ + +
+
+
+

AbstractFilter Class

+
+ + + + + + + + + + + Module: PIXI + + + + +
+ + + +
+

This is the base class for creating a pixi.js filter. Currently only webGL supports filters. +If you want to make a custom filter this should be your base class.

+ +
+ + +
+

Constructor

+
+

AbstractFilter

+ + +
+ (
    + +
  • + + fragmentSrc + +
  • + +
  • + + unifroms + +
  • + +
) +
+ + + + + + + + + + + + + + + + +
+ + + +

+ + Defined in + + + + + src/pixi/filters/AbstractFilter.js:6 + +

+ + + + + +
+ +
+ +
+ + +
+

Parameters:

+ +
    + +
  • + + fragmentSrc + Object + + + + +
    + +
    + + +
  • + +
  • + + unifroms + Object + + + + +
    + +
    + + +
  • + +
+
+ + + + + +
+ +
+ + +
+ + +
+
+

Item Index

+ + + + +
+

Properties

+ + +
+ + + + + +
+ + + + +
+

Properties

+ + +
+

passes

+ Array an array of filter objects + + + + + private + + + + + + +
+ + + +

+ + Defined in + + + + + src/pixi/filters/AbstractFilter.js:16 + +

+ + + + +
+ +
+

An array of passes - some filters contain a few steps this array simply stores the steps in a liniear fashion. +For example the blur filter has two passes blurX and blurY.

+ +
+ + + + + + +
+ + +
+

uniforms

+ Unknown + + + + + private + + + + + + +
+ + + +

+ + Defined in + + + + + src/pixi/filters/AbstractFilter.js:29 + +

+ + + + +
+ +
+ +
+ + + + + + +
+ + +
+ + + + + +
+
+ +
+
+
+
+
+
+ + + + + + + + + + diff --git a/docs/classes/AssetLoader.html b/docs/classes/AssetLoader.html index 71c3f58..49df281 100644 --- a/docs/classes/AssetLoader.html +++ b/docs/classes/AssetLoader.html @@ -3,11 +3,11 @@ AssetLoader - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
-

+

@@ -41,71 +41,95 @@ @@ -145,16 +169,21 @@

AssetLoader Class

- - -
- Extends EventTarget +
+ Uses +
+ + @@ -170,9 +199,12 @@
-

A Class that loads a bunch of images / sprite sheet / bitmap font files. Once the assets have been loaded they are added to the PIXI Texture cache and can be accessed easily through PIXI.Texture.fromImage() and PIXI.Sprite.fromImage() -When all items have been loaded this class will dispatch a "onLoaded" event -As each individual item is loaded this class will dispatch a "onProgress" event

+

A Class that loads a bunch of images / sprite sheet / bitmap font files. Once the +assets have been loaded they are added to the PIXI Texture cache and can be accessed +easily through PIXI.Texture.fromImage() and PIXI.Sprite.fromImage() +When all items have been loaded this class will dispatch a "onLoaded" event +As each individual item is loaded this class will dispatch a "onProgress" event

+
@@ -191,6 +223,12 @@ As each individual item is loaded this class will dispatch a "onProgress" event< +
  • + + crossorigin + +
  • + )
    @@ -220,7 +258,7 @@ As each individual item is loaded this class will dispatch a "onProgress" event< - src/pixi/loaders/AssetLoader.js:5 + src/pixi/loaders/AssetLoader.js:5

    @@ -243,13 +281,33 @@ As each individual item is loaded this class will dispatch a "onProgress" event<
  • assetURLs - Array + Array
    -

    an array of image/sprite sheet urls that you would like loaded supported. Supported image formats include "jpeg", "jpg", "png", "gif". Supported sprite sheet data formats only include "JSON" at this time. Supported bitmap font data formats include "xml" and "fnt".

    +

    an array of image/sprite sheet urls that you would like loaded + supported. Supported image formats include "jpeg", "jpg", "png", "gif". Supported + sprite sheet data formats only include "JSON" at this time. Supported bitmap font + data formats include "xml" and "fnt".

    + +
    + + +
  • + +
  • + + crossorigin + Boolean + + + + +
    +

    Whether requests should be treated as crossorigin

    +
    @@ -272,6 +330,8 @@ As each individual item is loaded this class will dispatch a "onProgress" event<
  • Index
  • +
  • Methods
  • +
  • Properties
  • @@ -286,18 +346,54 @@ As each individual item is loaded this class will dispatch a "onProgress" event<

    Item Index

    +
    +

    Methods

    + + +
    +

    Properties

    - @@ -480,6 +525,13 @@ http://www.bmglyph.com/ for mac.

      +
    • + _interactive + + + +
    • +
    • alpha @@ -499,6 +551,27 @@ http://www.bmglyph.com/ for mac.

      +
    • + +
    • + color + + + +
    • + +
    • + dynamic + + + +
    • + +
    • + filters + + +
    • @@ -513,6 +586,13 @@ http://www.bmglyph.com/ for mac.

      +
    • + +
    • + localTransform + + +
    • @@ -541,6 +621,13 @@ http://www.bmglyph.com/ for mac.

      +
    • + +
    • + renderable + + +
    • @@ -569,6 +656,20 @@ http://www.bmglyph.com/ for mac.

      +
    • + +
    • + worldAlpha + + + +
    • + +
    • + worldTransform + + +
    @@ -594,7 +695,7 @@ http://www.bmglyph.com/ for mac.

  • - DisplayObject + child
  • @@ -620,11 +721,11 @@ http://www.bmglyph.com/ for mac.

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:42 + src/pixi/display/DisplayObjectContainer.js:32

    @@ -636,6 +737,7 @@ http://www.bmglyph.com/ for mac.

    Adds a child to the container.

    +
    @@ -646,14 +748,15 @@ http://www.bmglyph.com/ for mac.

  • - DisplayObject + child DisplayObject
    - +

    The DisplayObject to add to the container

    +
    @@ -678,7 +781,7 @@ http://www.bmglyph.com/ for mac.

  • - DisplayObject + child
  • @@ -710,11 +813,11 @@ http://www.bmglyph.com/ for mac.

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:139 + src/pixi/display/DisplayObjectContainer.js:120

    @@ -726,6 +829,7 @@ http://www.bmglyph.com/ for mac.

    Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown

    +
    @@ -736,14 +840,15 @@ http://www.bmglyph.com/ for mac.

  • - DisplayObject + child DisplayObject
    - +

    The child to add

    +
    @@ -758,7 +863,8 @@ http://www.bmglyph.com/ for mac.

    - +

    The index to place the child in

    +
    @@ -809,11 +915,11 @@ http://www.bmglyph.com/ for mac.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:109 + src/pixi/display/DisplayObject.js:174

    @@ -825,6 +931,7 @@ http://www.bmglyph.com/ for mac.

    A callback that is used when the users clicks on the displayObject with their mouse

    +
    @@ -836,7 +943,7 @@ http://www.bmglyph.com/ for mac.

  • interactionData - InteractionData + InteractionData @@ -893,11 +1000,11 @@ http://www.bmglyph.com/ for mac.

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:274 + src/pixi/display/DisplayObjectContainer.js:256

    @@ -909,6 +1016,7 @@ http://www.bmglyph.com/ for mac.

    Returns the Child at the specified index

    +
    @@ -926,7 +1034,8 @@ http://www.bmglyph.com/ for mac.

    - +

    The index to get the child from

    +
    @@ -977,11 +1086,11 @@ http://www.bmglyph.com/ for mac.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:115 + src/pixi/display/DisplayObject.js:180

    @@ -993,6 +1102,7 @@ http://www.bmglyph.com/ for mac.

    A callback that is used when the user clicks the mouse down over the sprite

    +
    @@ -1004,7 +1114,7 @@ http://www.bmglyph.com/ for mac.

  • interactionData - InteractionData + InteractionData @@ -1061,11 +1171,11 @@ http://www.bmglyph.com/ for mac.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:141 + src/pixi/display/DisplayObject.js:206

    @@ -1077,6 +1187,7 @@ http://www.bmglyph.com/ for mac.

    A callback that is used when the users mouse leaves the displayObject

    +
    @@ -1088,7 +1199,7 @@ http://www.bmglyph.com/ for mac.

  • interactionData - InteractionData + InteractionData @@ -1145,11 +1256,11 @@ http://www.bmglyph.com/ for mac.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:135 + src/pixi/display/DisplayObject.js:200

    @@ -1161,6 +1272,7 @@ http://www.bmglyph.com/ for mac.

    A callback that is used when the users mouse rolls over the displayObject

    +
    @@ -1172,7 +1284,7 @@ http://www.bmglyph.com/ for mac.

  • interactionData - InteractionData + InteractionData @@ -1229,11 +1341,11 @@ http://www.bmglyph.com/ for mac.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:121 + src/pixi/display/DisplayObject.js:186

    @@ -1246,6 +1358,7 @@ http://www.bmglyph.com/ for mac.

    A callback that is used when the user releases the mouse that was over the displayObject for this callback to be fired the mouse must have been pressed down over the displayObject

    +
    @@ -1257,7 +1370,7 @@ for this callback to be fired the mouse must have been pressed down over the dis
  • interactionData - InteractionData + InteractionData @@ -1314,11 +1427,11 @@ for this callback to be fired the mouse must have been pressed down over the dis

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:128 + src/pixi/display/DisplayObject.js:193

    @@ -1331,6 +1444,7 @@ for this callback to be fired the mouse must have been pressed down over the dis

    A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject for this callback to be fired, The touch must have started over the displayObject

    +
    @@ -1342,7 +1456,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • interactionData - InteractionData + InteractionData @@ -1373,7 +1487,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • - DisplayObject + child
  • @@ -1399,11 +1513,11 @@ for this callback to be fired, The touch must have started over the displayObjec

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:291 + src/pixi/display/DisplayObjectContainer.js:274

    @@ -1415,6 +1529,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    Removes a child from the container.

    +
    @@ -1425,14 +1540,15 @@ for this callback to be fired, The touch must have started over the displayObjec
  • - DisplayObject + child DisplayObject
    - +

    The DisplayObject to remove

    +
    @@ -1448,7 +1564,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • -
    +

    setInteractive

    @@ -1468,6 +1584,8 @@ for this callback to be fired, The touch must have started over the displayObjec + deprecated + @@ -1483,16 +1601,18 @@ for this callback to be fired, The touch must have started over the displayObjec

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:193 + src/pixi/display/DisplayObject.js:247

    +

    Deprecated: Simply set the `interactive` property directly

    +
    @@ -1500,6 +1620,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default Instead of using this function you can now simply set the interactive property to true or false

    +
    @@ -1575,7 +1696,7 @@ Instead of using this function you can now simply set the interactive property t - src/pixi/text/BitmapText.js:44 + src/pixi/text/BitmapText.js:46

    @@ -1587,6 +1708,7 @@ Instead of using this function you can now simply set the interactive property t

    Set the style of the text

    +
    @@ -1605,6 +1727,7 @@ Instead of using this function you can now simply set the interactive property t

    The style parameters

    +
    @@ -1617,7 +1740,8 @@ Instead of using this function you can now simply set the interactive property t
    -

    The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously)

    +

    The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously)

    +
    @@ -1631,7 +1755,8 @@ Instead of using this function you can now simply set the interactive property t
    -

    An alignment of the multiline text ("left", "center" or "right")

    +

    An alignment of the multiline text ("left", "center" or "right")

    +
    @@ -1693,7 +1818,7 @@ Instead of using this function you can now simply set the interactive property t - src/pixi/text/BitmapText.js:33 + src/pixi/text/BitmapText.js:34

    @@ -1705,6 +1830,7 @@ Instead of using this function you can now simply set the interactive property t

    Set the copy for the text object

    +
    @@ -1723,6 +1849,7 @@ Instead of using this function you can now simply set the interactive property t

    The copy that you would like the text to display

    +
    @@ -1738,7 +1865,7 @@ Instead of using this function you can now simply set the interactive property t
    -
    +

    swapChildren

    @@ -1747,13 +1874,13 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child
  • - DisplayObject2 + child2
  • @@ -1766,6 +1893,8 @@ Instead of using this function you can now simply set the interactive property t + private + @@ -1779,11 +1908,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:227 + src/pixi/display/DisplayObjectContainer.js:207

    @@ -1794,7 +1923,8 @@ Instead of using this function you can now simply set the interactive property t
    -

    Swaps the depth of 2 displayObjects

    +

    [NYI] Swaps the depth of 2 displayObjects

    +
    @@ -1805,7 +1935,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child DisplayObject @@ -1820,7 +1950,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject2 + child2 DisplayObject @@ -1878,11 +2008,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:152 + src/pixi/display/DisplayObject.js:217

    @@ -1895,6 +2025,7 @@ Instead of using this function you can now simply set the interactive property t

    A callback that is used when the users taps on the sprite with their finger basically a touch version of click

    +
    @@ -1906,7 +2037,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -1963,11 +2094,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:165 + src/pixi/display/DisplayObject.js:230

    @@ -1979,6 +2110,7 @@ basically a touch version of click

    A callback that is used when the user releases a touch over the displayObject

    +
    @@ -1990,7 +2122,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -2047,11 +2179,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:171 + src/pixi/display/DisplayObject.js:236

    @@ -2064,6 +2196,7 @@ basically a touch version of click

    A callback that is used when the user releases the touch that was over the displayObject for this callback to be fired, The touch must have started over the sprite

    +
    @@ -2075,7 +2208,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -2132,11 +2265,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:159 + src/pixi/display/DisplayObject.js:224

    @@ -2147,7 +2280,8 @@ for this callback to be fired, The touch must have started over the sprite

  • -

    A callback that is used when the user touch's over the displayObject

    +

    A callback that is used when the user touch's over the displayObject

    +
    @@ -2159,7 +2293,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -2178,6 +2312,120 @@ for this callback to be fired, The touch must have started over the sprite

    +
  • + + +
    +

    updateText

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/text/BitmapText.js:67 + +

    + + + + + +
    + +
    +

    Renders text

    + +
    + + + + + + +
    + + +
    +

    updateTransform

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/text/BitmapText.js:142 + +

    + + + + + +
    + +
    +

    Updates the transfor of this object

    + +
    + + + + + +
    @@ -2189,6 +2437,50 @@ for this callback to be fired, The touch must have started over the sprite

    Properties

    +
    +

    _interactive

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:115 + +

    + + + + +
    + +
    +

    [read-only] Whether or not the object is interactive, do not toggle directly! use the interactive property

    + +
    + + + + + + +
    + +

    alpha

    Number @@ -2205,11 +2497,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:43 + src/pixi/display/DisplayObject.js:47

    @@ -2220,6 +2512,7 @@ for this callback to be fired, The touch must have started over the sprite

    The opacity of the object.

    +
    @@ -2246,11 +2539,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:98 + src/pixi/display/DisplayObject.js:72

    @@ -2261,6 +2554,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is used to indicate if the displayObject should display a mouse hand cursor on rollover

    +
    @@ -2273,7 +2567,7 @@ for this callback to be fired, The touch must have started over the sprite

    children

    - Array + Array @@ -2287,11 +2581,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:16 + src/pixi/display/DisplayObjectContainer.js:18

    @@ -2302,6 +2596,139 @@ for this callback to be fired, The touch must have started over the sprite

    [read-only] The of children of this container.

    + +
    + + + + + + +
    + + +
    +

    color

    + Array<> + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:145 + +

    + + + + +
    + +
    +

    [NYI] Unkown

    + +
    + + + + + + +
    + + +
    +

    dynamic

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:154 + +

    + + + + +
    + +
    +

    [NYI] Holds whether or not this object is dynamic, for rendering optimization

    + +
    + + + + + + +
    + + +
    +

    filters

    + Array An array of filters + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:318 + +

    + + + + +
    + +
    +

    Sets the filters for the displayObject. +* IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer. +To remove filters simply set this property to 'null'

    +
    @@ -2314,7 +2741,7 @@ for this callback to be fired, The touch must have started over the sprite

    hitArea

    - Rectangle + Rectangle | Circle | Ellipse | Polygon @@ -2328,11 +2755,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:72 + src/pixi/display/DisplayObject.js:63

    @@ -2344,6 +2771,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is the defined area that will pick up mouse / touch events. It is null by default. Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children)

    +
    @@ -2370,11 +2798,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:204 + src/pixi/display/DisplayObject.js:260

    @@ -2385,6 +2813,53 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Indicates if the sprite will have touch and mouse interactivity. It is false by default

    + +
    + + +

    Default: false

    + + + + + +
    + + +
    +

    localTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:135 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object locally

    +
    @@ -2397,7 +2872,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    mask

    - PIXI.Graphics + Graphics @@ -2411,11 +2886,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:222 + src/pixi/display/DisplayObject.js:280

    @@ -2428,6 +2903,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. To remove a mask, set this property to null.

    +
    @@ -2454,11 +2930,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:58 + src/pixi/display/DisplayObject.js:88

    @@ -2469,6 +2945,7 @@ To remove a mask, set this property to null.

    [read-only] The display object container that contains this display object.

    +
    @@ -2495,11 +2972,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:29 + src/pixi/display/DisplayObject.js:31

    @@ -2510,6 +2987,7 @@ To remove a mask, set this property to null.

    The pivot point of the displayObject that it rotates around

    +
    @@ -2536,11 +3014,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:15 + src/pixi/display/DisplayObject.js:15

    @@ -2551,6 +3029,49 @@ To remove a mask, set this property to null.

    The coordinate of the object relative to the local coordinates of the parent.

    + +
    + + + + + + +
    + + +
    +

    renderable

    + Boolean + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:80 + +

    + + + + +
    + +
    +

    Can this object be rendered

    +
    @@ -2577,11 +3098,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:36 + src/pixi/display/DisplayObject.js:39

    @@ -2592,6 +3113,7 @@ To remove a mask, set this property to null.

    The rotation of the object in radians.

    +
    @@ -2618,11 +3140,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:22 + src/pixi/display/DisplayObject.js:23

    @@ -2633,6 +3155,7 @@ To remove a mask, set this property to null.

    The scale factor of the object.

    +
    @@ -2659,11 +3182,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:65 + src/pixi/display/DisplayObject.js:97

    @@ -2674,6 +3197,7 @@ To remove a mask, set this property to null.

    [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage.

    +
    @@ -2700,11 +3224,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:50 + src/pixi/display/DisplayObject.js:55

    @@ -2715,6 +3239,93 @@ To remove a mask, set this property to null.

    The visibility of the object.

    + +
    + + + + + + +
    + + +
    +

    worldAlpha

    + Number + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:106 + +

    + + + + +
    + +
    +

    [read-only] The multiplied alpha of the displayobject

    + +
    + + + + + + +
    + + +
    +

    worldTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:125 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object based on world (parent) factors

    +
    @@ -2740,13 +3351,13 @@ To remove a mask, set this property to null.

    - + - - - - - - + + + + + + diff --git a/docs/classes/BlurFilter.html b/docs/classes/BlurFilter.html new file mode 100644 index 0000000..d168b03 --- /dev/null +++ b/docs/classes/BlurFilter.html @@ -0,0 +1,426 @@ + + + + + BlurFilter - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    BlurFilter Class

    +
    + + + + + + + + + + + Module: PIXI + + + + +
    + + + +
    +

    The BlurFilter applies a Gaussian blur to an object. + The strength of the blur can be set for x- and y-axis separately (always relative to the stage).

    + +
    + + + +
    + + +
    +
    +

    Item Index

    + + + + +
    +

    Properties

    + + +
    + + + + + +
    + + + + +
    +

    Properties

    + + +
    +

    blur

    + Number the strength of the blur + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/filters/BlurFilter.js:24 + +

    + + + + +
    + +
    +

    Sets the strength of both the blurX and blurY properties simultaneously

    + +
    + + +

    Default: 2

    + + + + + +
    + + +
    +

    blurX

    + Number the strength of the blurX + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/filters/BlurFilter.js:40 + +

    + + + + +
    + +
    +

    Sets the strength of the blurX property simultaneously

    + +
    + + +

    Default: 2

    + + + + + +
    + + +
    +

    blurY

    + Number the strength of the blurY + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/filters/BlurFilter.js:56 + +

    + + + + +
    + +
    +

    Sets the strength of the blurX property simultaneously

    + +
    + + +

    Default: 2

    + + + + + +
    + + +
    + + + + + +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/classes/CanvasGraphics.html b/docs/classes/CanvasGraphics.html index 0e44412..252ac5e 100644 --- a/docs/classes/CanvasGraphics.html +++ b/docs/classes/CanvasGraphics.html @@ -3,11 +3,11 @@ CanvasGraphics - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -150,7 +174,7 @@ @@ -167,6 +191,7 @@

    A set of functions used by the webGL renderer to draw the primitive graphics data

    +
    @@ -176,6 +201,8 @@
  • Index
  • +
  • Methods
  • + @@ -186,6 +213,68 @@

    Item Index

    +
    +

    Methods

    + + +
    + @@ -195,6 +284,669 @@
    +
    +

    Methods

    + + +
    +

    buildCircle

    + + +
    + (
      + +
    • + + graphics + +
    • + +
    • + + webGLData + +
    • + +
    ) +
    + + + + + + + + private + + + + + + static + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLGraphics.js:204 + +

    + + + + + +
    + +
    +

    Builds a circle to draw

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + graphics + Graphics + + + + +
      + +
      + + +
    • + +
    • + + webGLData + Object + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    buildLine

    + + +
    + (
      + +
    • + + graphics + +
    • + +
    • + + webGLData + +
    • + +
    ) +
    + + + + + + + + private + + + + + + static + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLGraphics.js:272 + +

    + + + + + +
    + +
    +

    Builds a line to draw

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + graphics + Graphics + + + + +
      + +
      + + +
    • + +
    • + + webGLData + Object + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    buildPoly

    + + +
    + (
      + +
    • + + graphics + +
    • + +
    • + + webGLData + +
    • + +
    ) +
    + + + + + + + + private + + + + + + static + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLGraphics.js:463 + +

    + + + + + +
    + +
    +

    Builds a polygon to draw

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + graphics + Graphics + + + + +
      + +
      + + +
    • + +
    • + + webGLData + Object + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    buildRectangle

    + + +
    + (
      + +
    • + + graphics + +
    • + +
    • + + webGLData + +
    • + +
    ) +
    + + + + + + + + private + + + + + + static + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLGraphics.js:139 + +

    + + + + + +
    + +
    +

    Builds a rectangle to draw

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + graphics + Graphics + + + + +
      + +
      + + +
    • + +
    • + + webGLData + Object + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    renderGraphics

    + + +
    + (
      + +
    • + + graphics + +
    • + +
    • + + projection + +
    • + +
    ) +
    + + + + + + + + private + + + + + + static + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLGraphics.js:15 + +

    + + + + + +
    + +
    +

    Renders the graphics object

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + graphics + Graphics + + + + +
      + +
      + + +
    • + +
    • + + projection + Object + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    updateGraphics

    + + +
    + (
      + +
    • + + graphics + +
    • + +
    ) +
    + + + + + + + + private + + + + + + static + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLGraphics.js:87 + +

    + + + + + +
    + +
    +

    Updates the graphics object

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + graphics + Graphics + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    + @@ -210,13 +962,13 @@
    - + - - - - - - + + + + + + diff --git a/docs/classes/CanvasRenderer.html b/docs/classes/CanvasRenderer.html index bcc7dba..4baa9ad 100644 --- a/docs/classes/CanvasRenderer.html +++ b/docs/classes/CanvasRenderer.html @@ -3,11 +3,11 @@ CanvasRenderer - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -150,7 +174,7 @@ @@ -168,6 +192,7 @@

    the CanvasRenderer draws the stage and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. Dont forget to add the view to your DOM or you will not see anything :)

    +
    @@ -182,13 +207,13 @@ Dont forget to add the view to your DOM or you will not see anything :)

  • - width + width=0
  • - height + height=0
  • @@ -200,7 +225,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

  • - transparent + transparent=false
  • @@ -233,7 +258,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    - src/pixi/renderers/canvas/CanvasRenderer.js:6 + src/pixi/renderers/canvas/CanvasRenderer.js:6

    @@ -255,7 +280,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

  • - width + width=0 Number @@ -263,6 +288,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    the width of the canvas view

    +
    @@ -270,7 +296,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

  • - height + height=0 Number @@ -278,6 +304,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    the height of the canvas view

    +
    @@ -293,6 +320,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    the canvas to use as a view, optional

    +
    @@ -300,7 +328,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

  • - transparent + transparent=false Boolean @@ -308,6 +336,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    the transparency of the render view, default false

    +
    @@ -354,6 +383,41 @@ Dont forget to add the view to your DOM or you will not see anything :)

    +
  • + +
  • + renderDisplayObject + + + +
  • + +
  • + renderStrip + + + +
  • + +
  • + renderStripFlat + + + +
  • + +
  • + renderTilingSprite + + + +
  • + +
  • + resize + + +
  • @@ -450,7 +514,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    - src/pixi/renderers/canvas/CanvasRenderer.js:66 + src/pixi/renderers/canvas/CanvasRenderer.js:66

    @@ -462,6 +526,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    Renders the stage to its canvas view

    +
    @@ -480,6 +545,482 @@ Dont forget to add the view to your DOM or you will not see anything :)

    the Stage element to be rendered

    + +
    + + + + + +
    + + + + + +
    + + +
    +

    renderDisplayObject

    + + +
    + (
      + +
    • + + displayObject + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/canvas/CanvasRenderer.js:129 + +

    + + + + + +
    + +
    +

    Renders a display object

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + displayObject + DisplayObject + + + + +
      +

      The displayObject to render

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    renderStrip

    + + +
    + (
      + +
    • + + strip + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/canvas/CanvasRenderer.js:320 + +

    + + + + + +
    + +
    +

    Renders a strip

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + strip + Strip + + + + +
      +

      The Strip to render

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    renderStripFlat

    + + +
    + (
      + +
    • + + strip + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/canvas/CanvasRenderer.js:250 + +

    + + + + + +
    + +
    +

    Renders a flat strip

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + strip + Strip + + + + +
      +

      The Strip to render

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    renderTilingSprite

    + + +
    + (
      + +
    • + + sprite + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/canvas/CanvasRenderer.js:287 + +

    + + + + + +
    + +
    +

    Renders a tiling sprite

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + sprite + TilingSprite + + + + +
      +

      The tilingsprite to render

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    resize

    + + +
    + (
      + +
    • + + width + +
    • + +
    • + + height + +
    • + +
    ) +
    + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/canvas/CanvasRenderer.js:113 + +

    + + + + + +
    + +
    +

    resizes the canvas view to the specified width and height

    + +
    + + +
    +

    Parameters:

    + +
    - + - - - - - - + + + + + + diff --git a/docs/classes/Circle.html b/docs/classes/Circle.html index e67296d..5558388 100644 --- a/docs/classes/Circle.html +++ b/docs/classes/Circle.html @@ -3,11 +3,11 @@ Circle - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -150,7 +174,7 @@ @@ -166,7 +190,8 @@
    - +

    The Circle object can be used to specify a hit area for displayobjects

    +
    @@ -226,7 +251,7 @@ - src/pixi/core/Circle.js:5 + src/pixi/core/Circle.js:5

    @@ -256,6 +281,7 @@

    The X coord of the upper-left corner of the framing rectangle of this circle

    +
    @@ -271,6 +297,7 @@

    The Y coord of the upper-left corner of the framing rectangle of this circle

    +
    @@ -286,6 +313,7 @@

    The radius of the circle

    +
    @@ -395,7 +423,7 @@ - + Circle @@ -422,7 +450,7 @@ - src/pixi/core/Circle.js:36 + src/pixi/core/Circle.js:38

    @@ -433,7 +461,8 @@
    - +

    Creates a clone of this Circle instance

    +
    @@ -445,7 +474,10 @@
    - a copy of the polygon + Circle: + +

    a copy of the polygon

    +
    @@ -480,7 +512,7 @@ - + Boolean @@ -507,7 +539,7 @@ - src/pixi/core/Circle.js:45 + src/pixi/core/Circle.js:49

    @@ -518,7 +550,8 @@
    - +

    Checks if the x, and y coords passed to this function are contained within this circle

    +
    @@ -537,6 +570,7 @@

    The X coord of the point to test

    +
    @@ -552,6 +586,7 @@

    The Y coord of the point to test

    +
    @@ -568,7 +603,10 @@
    - if the x/y coords are within this polygon + Boolean: + +

    if the x/y coords are within this polygon

    +
    @@ -609,7 +647,7 @@ - src/pixi/core/Circle.js:28 + src/pixi/core/Circle.js:30

    @@ -655,7 +693,7 @@ - src/pixi/core/Circle.js:14 + src/pixi/core/Circle.js:16

    @@ -701,7 +739,7 @@ - src/pixi/core/Circle.js:21 + src/pixi/core/Circle.js:23

    @@ -739,13 +777,13 @@ - + - - - - - - + + + + + + diff --git a/docs/classes/ColorMatrixFilter.html b/docs/classes/ColorMatrixFilter.html new file mode 100644 index 0000000..babe305 --- /dev/null +++ b/docs/classes/ColorMatrixFilter.html @@ -0,0 +1,319 @@ + + + + + ColorMatrixFilter - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    ColorMatrixFilter Class

    +
    + + + + + + + + + + + Module: PIXI + + + + +
    + + + +
    +

    The ColorMatrixFilter class lets you apply a 4x4 matrix transformation on the RGBA + color and alpha values of every pixel on your displayObject to produce a result + with a new set of RGBA color and alpha values. Its pretty powerful!

    + +
    + + + +
    + + +
    +
    +

    Item Index

    + + + + +
    +

    Properties

    + + +
    + + + + + +
    + + + + +
    +

    Properties

    + + +
    +

    matrix

    + Array and array of 26 numbers + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/filters/ColorMatrixFilter.js:45 + +

    + + + + +
    + +
    +

    Sets the matrix of the color matrix filter

    + +
    + + +

    Default: [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]

    + + + + + +
    + + +
    + + + + + +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/classes/CustomRenderable.html b/docs/classes/CustomRenderable.html index 4866fb0..5b50c47 100644 --- a/docs/classes/CustomRenderable.html +++ b/docs/classes/CustomRenderable.html @@ -3,11 +3,11 @@ CustomRenderable - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -154,7 +178,7 @@ @@ -170,7 +194,8 @@
    -

    Need to finalize this a bit more but works! Its in but will be working on this feature properly next..:)

    +

    This object is one that will allow you to specify custom rendering functions based on render type

    +
    @@ -208,7 +233,7 @@ - src/pixi/extras/CustomRenderable.js:6 + src/pixi/extras/CustomRenderable.js:6

    @@ -261,6 +286,13 @@ + + +
  • + initWebGL + + +
  • @@ -298,11 +330,27 @@
  • -
  • +
  • + renderCanvas + + + +
  • + +
  • + renderWebGL + + + +
  • + +
  • setInteractive + deprecated +
  • @@ -343,6 +391,13 @@ @@ -476,11 +580,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:109 + src/pixi/display/DisplayObject.js:174

    @@ -492,6 +596,7 @@

    A callback that is used when the users clicks on the displayObject with their mouse

    +
    @@ -503,7 +608,7 @@
  • interactionData - InteractionData + InteractionData @@ -522,6 +627,95 @@ +
  • + + +
    +

    initWebGL

    + + +
    + (
      + +
    • + + renderer + +
    • + +
    ) +
    + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/extras/CustomRenderable.js:35 + +

    + + + + + +
    + +
    +

    If this object is being rendered by a WebGLRenderer it will call this callback to initialize

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + renderer + WebGLRenderer + + + + +
      +

      The renderer instance

      + +
      + + +
    • + +
    +
    + + + + +
    @@ -560,11 +754,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:115 + src/pixi/display/DisplayObject.js:180

    @@ -576,6 +770,7 @@

    A callback that is used when the user clicks the mouse down over the sprite

    +
    @@ -587,7 +782,7 @@
  • interactionData - InteractionData + InteractionData @@ -644,11 +839,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:141 + src/pixi/display/DisplayObject.js:206

    @@ -660,6 +855,7 @@

    A callback that is used when the users mouse leaves the displayObject

    +
    @@ -671,7 +867,7 @@
  • interactionData - InteractionData + InteractionData @@ -728,11 +924,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:135 + src/pixi/display/DisplayObject.js:200

    @@ -744,6 +940,7 @@

    A callback that is used when the users mouse rolls over the displayObject

    +
    @@ -755,7 +952,7 @@
  • interactionData - InteractionData + InteractionData @@ -812,11 +1009,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:121 + src/pixi/display/DisplayObject.js:186

    @@ -829,6 +1026,7 @@

    A callback that is used when the user releases the mouse that was over the displayObject for this callback to be fired the mouse must have been pressed down over the displayObject

    +
    @@ -840,7 +1038,7 @@ for this callback to be fired the mouse must have been pressed down over the dis
  • interactionData - InteractionData + InteractionData @@ -897,11 +1095,11 @@ for this callback to be fired the mouse must have been pressed down over the dis

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:128 + src/pixi/display/DisplayObject.js:193

    @@ -914,6 +1112,7 @@ for this callback to be fired the mouse must have been pressed down over the dis

    A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject for this callback to be fired, The touch must have started over the displayObject

    +
    @@ -925,7 +1124,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • interactionData - InteractionData + InteractionData @@ -947,8 +1146,8 @@ for this callback to be fired, The touch must have started over the displayObjec
  • -
    -

    setInteractive

    +
    +

    renderCanvas

    @@ -956,7 +1155,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • - interactive + renderer
  • @@ -981,12 +1180,15 @@ for this callback to be fired, The touch must have started over the displayObjec
    -

    Inherited from - DisplayObject: + +

    + + Defined in + - src/pixi/display/DisplayObject.js:193 + src/pixi/extras/CustomRenderable.js:24

    @@ -994,11 +1196,191 @@ for this callback to be fired, The touch must have started over the displayObjec +
    + +
    +

    If this object is being rendered by a CanvasRenderer it will call this callback

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + renderer + CanvasRenderer + + + + +
      +

      The renderer instance

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    renderWebGL

    + + +
    + (
      + +
    • + + renderer + +
    • + +
    ) +
    + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/extras/CustomRenderable.js:46 + +

    + + + + + +
    + +
    +

    If this object is being rendered by a WebGLRenderer it will call this callback

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + renderer + WebGLRenderer + + + + +
      +

      The renderer instance

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    setInteractive

    + + +
    + (
      + +
    • + + interactive + +
    • + +
    ) +
    + + + + + + deprecated + + + + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:247 + +

    + + + +

    Deprecated: Simply set the `interactive` property directly

    + + +

    [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default Instead of using this function you can now simply set the interactive property to true or false

    +
    @@ -1067,11 +1449,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:152 + src/pixi/display/DisplayObject.js:217

    @@ -1084,6 +1466,7 @@ Instead of using this function you can now simply set the interactive property t

    A callback that is used when the users taps on the sprite with their finger basically a touch version of click

    +
    @@ -1095,7 +1478,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -1152,11 +1535,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:165 + src/pixi/display/DisplayObject.js:230

    @@ -1168,6 +1551,7 @@ basically a touch version of click

    A callback that is used when the user releases a touch over the displayObject

    +
    @@ -1179,7 +1563,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -1236,11 +1620,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:171 + src/pixi/display/DisplayObject.js:236

    @@ -1253,6 +1637,7 @@ basically a touch version of click

    A callback that is used when the user releases the touch that was over the displayObject for this callback to be fired, The touch must have started over the sprite

    +
    @@ -1264,7 +1649,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -1321,11 +1706,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:159 + src/pixi/display/DisplayObject.js:224

    @@ -1336,7 +1721,8 @@ for this callback to be fired, The touch must have started over the sprite

  • -

    A callback that is used when the user touch's over the displayObject

    +

    A callback that is used when the user touch's over the displayObject

    +
    @@ -1348,7 +1734,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -1378,6 +1764,50 @@ for this callback to be fired, The touch must have started over the sprite

    Properties

    +
    +

    _interactive

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:115 + +

    + + + + +
    + +
    +

    [read-only] Whether or not the object is interactive, do not toggle directly! use the interactive property

    + +
    + + + + + + +
    + +

    alpha

    Number @@ -1394,11 +1824,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:43 + src/pixi/display/DisplayObject.js:47

    @@ -1409,6 +1839,7 @@ for this callback to be fired, The touch must have started over the sprite

    The opacity of the object.

    +
    @@ -1435,11 +1866,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:98 + src/pixi/display/DisplayObject.js:72

    @@ -1450,6 +1881,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is used to indicate if the displayObject should display a mouse hand cursor on rollover

    +
    @@ -1460,9 +1892,97 @@ for this callback to be fired, The touch must have started over the sprite

    -
    -

    hitArea

    - Rectangle +
    +

    color

    + Array<> + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:145 + +

    + + + + +
    + +
    +

    [NYI] Unkown

    + +
    + + + + + + +
    + + +
    +

    dynamic

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:154 + +

    + + + + +
    + +
    +

    [NYI] Holds whether or not this object is dynamic, for rendering optimization

    + +
    + + + + + + +
    + + +
    +

    filters

    + Array An array of filters @@ -1476,11 +1996,55 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:72 + src/pixi/display/DisplayObject.js:318 + +

    + + + + +
    + +
    +

    Sets the filters for the displayObject. +* IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer. +To remove filters simply set this property to 'null'

    + +
    + + + + + + +
    + + +
    +

    hitArea

    + Rectangle | Circle | Ellipse | Polygon + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:63

    @@ -1492,6 +2056,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is the defined area that will pick up mouse / touch events. It is null by default. Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children)

    +
    @@ -1518,11 +2083,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:204 + src/pixi/display/DisplayObject.js:260

    @@ -1533,6 +2098,53 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Indicates if the sprite will have touch and mouse interactivity. It is false by default

    + +
    + + +

    Default: false

    + + + + + +
    + + +
    +

    localTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:135 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object locally

    +
    @@ -1545,7 +2157,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    mask

    - PIXI.Graphics + Graphics @@ -1559,11 +2171,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:222 + src/pixi/display/DisplayObject.js:280

    @@ -1576,6 +2188,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. To remove a mask, set this property to null.

    +
    @@ -1602,11 +2215,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:58 + src/pixi/display/DisplayObject.js:88

    @@ -1617,6 +2230,7 @@ To remove a mask, set this property to null.

    [read-only] The display object container that contains this display object.

    +
    @@ -1643,11 +2257,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:29 + src/pixi/display/DisplayObject.js:31

    @@ -1658,6 +2272,7 @@ To remove a mask, set this property to null.

    The pivot point of the displayObject that it rotates around

    +
    @@ -1684,11 +2299,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:15 + src/pixi/display/DisplayObject.js:15

    @@ -1699,6 +2314,49 @@ To remove a mask, set this property to null.

    The coordinate of the object relative to the local coordinates of the parent.

    + +
    + + + + + + +
    + + +
    +

    renderable

    + Boolean + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:80 + +

    + + + + +
    + +
    +

    Can this object be rendered

    +
    @@ -1725,11 +2383,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:36 + src/pixi/display/DisplayObject.js:39

    @@ -1740,6 +2398,7 @@ To remove a mask, set this property to null.

    The rotation of the object in radians.

    +
    @@ -1766,11 +2425,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:22 + src/pixi/display/DisplayObject.js:23

    @@ -1781,6 +2440,7 @@ To remove a mask, set this property to null.

    The scale factor of the object.

    +
    @@ -1807,11 +2467,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:65 + src/pixi/display/DisplayObject.js:97

    @@ -1822,6 +2482,7 @@ To remove a mask, set this property to null.

    [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage.

    +
    @@ -1848,11 +2509,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:50 + src/pixi/display/DisplayObject.js:55

    @@ -1863,6 +2524,93 @@ To remove a mask, set this property to null.

    The visibility of the object.

    + +
    + + + + + + +
    + + +
    +

    worldAlpha

    + Number + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:106 + +

    + + + + +
    + +
    +

    [read-only] The multiplied alpha of the displayobject

    + +
    + + + + + + +
    + + +
    +

    worldTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:125 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object based on world (parent) factors

    +
    @@ -1888,13 +2636,13 @@ To remove a mask, set this property to null.

  • - + - - - - - - + + + + + + diff --git a/docs/classes/DisplacementFilter.html b/docs/classes/DisplacementFilter.html new file mode 100644 index 0000000..753b93b --- /dev/null +++ b/docs/classes/DisplacementFilter.html @@ -0,0 +1,421 @@ + + + + + DisplacementFilter - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    DisplacementFilter Class

    +
    + + + + + + + + + + + Module: PIXI + + + + +
    + + + +
    +

    The DisplacementFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object. + You can use this filter to apply all manor of crazy warping effects + Currently the r property of the texture is used offset the x and the g propery of the texture is used to offset the y.

    + +
    + + + +
    + + +
    +
    +

    Item Index

    + + + + +
    +

    Properties

    + + +
    + + + + + +
    + + + + +
    +

    Properties

    + + +
    +

    map

    + Texture + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/filters/DisplacementFilter.js:92 + +

    + + + + +
    + +
    +

    The texture used for the displacemtent map * must be power of 2 texture at the moment

    + +
    + + + + + + +
    + + +
    +

    offset

    + Point + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/filters/DisplacementFilter.js:122 + +

    + + + + +
    + +
    +

    The offset used to move the displacement map.

    + +
    + + + + + + +
    + + +
    +

    scale

    + Point + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/filters/DisplacementFilter.js:107 + +

    + + + + +
    + +
    +

    The multiplier used to scale the displacement result from the map calculation.

    + +
    + + + + + + +
    + + +
    + + + + + +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/classes/DisplayObject.html b/docs/classes/DisplayObject.html index 12cec79..adecad4 100644 --- a/docs/classes/DisplayObject.html +++ b/docs/classes/DisplayObject.html @@ -3,11 +3,11 @@ DisplayObject - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -150,7 +174,7 @@ @@ -166,7 +190,8 @@
    -

    this is the base class for all objects that are rendered on the screen.

    +

    The base class for all objects that are rendered on the screen.

    +
    @@ -204,7 +229,7 @@ - src/pixi/display/DisplayObject.js:5 + src/pixi/display/DisplayObject.js:5

    @@ -294,11 +319,13 @@ -
  • +
  • setInteractive + deprecated +
  • @@ -339,6 +366,13 @@ @@ -479,7 +562,7 @@ - src/pixi/display/DisplayObject.js:109 + src/pixi/display/DisplayObject.js:174

    @@ -491,6 +574,7 @@

    A callback that is used when the users clicks on the displayObject with their mouse

    +
    @@ -502,7 +586,7 @@
  • interactionData - InteractionData + InteractionData @@ -566,7 +650,7 @@ - src/pixi/display/DisplayObject.js:115 + src/pixi/display/DisplayObject.js:180

    @@ -578,6 +662,7 @@

    A callback that is used when the user clicks the mouse down over the sprite

    +
    @@ -589,7 +674,7 @@
  • interactionData - InteractionData + InteractionData @@ -653,7 +738,7 @@ - src/pixi/display/DisplayObject.js:141 + src/pixi/display/DisplayObject.js:206

    @@ -665,6 +750,7 @@

    A callback that is used when the users mouse leaves the displayObject

    +
    @@ -676,7 +762,7 @@
  • interactionData - InteractionData + InteractionData @@ -740,7 +826,7 @@ - src/pixi/display/DisplayObject.js:135 + src/pixi/display/DisplayObject.js:200

    @@ -752,6 +838,7 @@

    A callback that is used when the users mouse rolls over the displayObject

    +
    @@ -763,7 +850,7 @@
  • interactionData - InteractionData + InteractionData @@ -827,7 +914,7 @@ - src/pixi/display/DisplayObject.js:121 + src/pixi/display/DisplayObject.js:186

    @@ -840,6 +927,7 @@

    A callback that is used when the user releases the mouse that was over the displayObject for this callback to be fired the mouse must have been pressed down over the displayObject

    +
    @@ -851,7 +939,7 @@ for this callback to be fired the mouse must have been pressed down over the dis
  • interactionData - InteractionData + InteractionData @@ -915,7 +1003,7 @@ for this callback to be fired the mouse must have been pressed down over the dis - src/pixi/display/DisplayObject.js:128 + src/pixi/display/DisplayObject.js:193

    @@ -928,6 +1016,7 @@ for this callback to be fired the mouse must have been pressed down over the dis

    A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject for this callback to be fired, The touch must have started over the displayObject

    +
    @@ -939,7 +1028,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • interactionData - InteractionData + InteractionData @@ -961,7 +1050,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • -
    +

    setInteractive

    @@ -981,6 +1070,8 @@ for this callback to be fired, The touch must have started over the displayObjec + deprecated + @@ -1003,12 +1094,14 @@ for this callback to be fired, The touch must have started over the displayObjec - src/pixi/display/DisplayObject.js:193 + src/pixi/display/DisplayObject.js:247

    +

    Deprecated: Simply set the `interactive` property directly

    +
    @@ -1016,6 +1109,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default Instead of using this function you can now simply set the interactive property to true or false

    +
    @@ -1091,7 +1185,7 @@ Instead of using this function you can now simply set the interactive property t - src/pixi/display/DisplayObject.js:152 + src/pixi/display/DisplayObject.js:217

    @@ -1104,6 +1198,7 @@ Instead of using this function you can now simply set the interactive property t

    A callback that is used when the users taps on the sprite with their finger basically a touch version of click

    +
    @@ -1115,7 +1210,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -1179,7 +1274,7 @@ basically a touch version of click

    - src/pixi/display/DisplayObject.js:165 + src/pixi/display/DisplayObject.js:230

    @@ -1191,6 +1286,7 @@ basically a touch version of click

    A callback that is used when the user releases a touch over the displayObject

    +
    @@ -1202,7 +1298,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -1266,7 +1362,7 @@ basically a touch version of click

    - src/pixi/display/DisplayObject.js:171 + src/pixi/display/DisplayObject.js:236

    @@ -1279,6 +1375,7 @@ basically a touch version of click

    A callback that is used when the user releases the touch that was over the displayObject for this callback to be fired, The touch must have started over the sprite

    +
    @@ -1290,7 +1387,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -1354,7 +1451,7 @@ for this callback to be fired, The touch must have started over the sprite

    - src/pixi/display/DisplayObject.js:159 + src/pixi/display/DisplayObject.js:224

    @@ -1365,7 +1462,8 @@ for this callback to be fired, The touch must have started over the sprite

  • -

    A callback that is used when the user touch's over the displayObject

    +

    A callback that is used when the user touch's over the displayObject

    +
    @@ -1377,7 +1475,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -1407,6 +1505,53 @@ for this callback to be fired, The touch must have started over the sprite

    Properties

    +
    +

    _interactive

    + Boolean + + + + + private + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/display/DisplayObject.js:115 + +

    + + + + +
    + +
    +

    [read-only] Whether or not the object is interactive, do not toggle directly! use the interactive property

    + +
    + + + + + + +
    + +

    alpha

    Number @@ -1430,7 +1575,7 @@ for this callback to be fired, The touch must have started over the sprite

    - src/pixi/display/DisplayObject.js:43 + src/pixi/display/DisplayObject.js:47

    @@ -1441,6 +1586,7 @@ for this callback to be fired, The touch must have started over the sprite

    The opacity of the object.

    +
    @@ -1474,7 +1620,7 @@ for this callback to be fired, The touch must have started over the sprite

    - src/pixi/display/DisplayObject.js:98 + src/pixi/display/DisplayObject.js:72

    @@ -1485,6 +1631,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is used to indicate if the displayObject should display a mouse hand cursor on rollover

    +
    @@ -1495,9 +1642,103 @@ for this callback to be fired, The touch must have started over the sprite

    -
    -

    hitArea

    - Rectangle +
    +

    color

    + Array<> + + + + + private + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/display/DisplayObject.js:145 + +

    + + + + +
    + +
    +

    [NYI] Unkown

    + +
    + + + + + + +
    + + +
    +

    dynamic

    + Boolean + + + + + private + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/display/DisplayObject.js:154 + +

    + + + + +
    + +
    +

    [NYI] Holds whether or not this object is dynamic, for rendering optimization

    + +
    + + + + + + +
    + + +
    +

    filters

    + Array An array of filters @@ -1518,7 +1759,54 @@ for this callback to be fired, The touch must have started over the sprite

    - src/pixi/display/DisplayObject.js:72 + src/pixi/display/DisplayObject.js:318 + +

    + + + + +
    + +
    +

    Sets the filters for the displayObject. +* IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer. +To remove filters simply set this property to 'null'

    + +
    + + + + + + +
    + + +
    +

    hitArea

    + Rectangle | Circle | Ellipse | Polygon + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/display/DisplayObject.js:63

    @@ -1530,6 +1818,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is the defined area that will pick up mouse / touch events. It is null by default. Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children)

    +
    @@ -1563,7 +1852,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction - src/pixi/display/DisplayObject.js:204 + src/pixi/display/DisplayObject.js:260

    @@ -1574,6 +1863,56 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Indicates if the sprite will have touch and mouse interactivity. It is false by default

    + +
    + + +

    Default: false

    + + + + + +
    + + +
    +

    localTransform

    + Mat3 + + + + + private + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/display/DisplayObject.js:135 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object locally

    +
    @@ -1586,7 +1925,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    mask

    - PIXI.Graphics + Graphics @@ -1607,7 +1946,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction - src/pixi/display/DisplayObject.js:222 + src/pixi/display/DisplayObject.js:280

    @@ -1620,6 +1959,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. To remove a mask, set this property to null.

    +
    @@ -1653,7 +1993,7 @@ To remove a mask, set this property to null.

    - src/pixi/display/DisplayObject.js:58 + src/pixi/display/DisplayObject.js:88

    @@ -1664,6 +2004,7 @@ To remove a mask, set this property to null.

    [read-only] The display object container that contains this display object.

    +
    @@ -1697,7 +2038,7 @@ To remove a mask, set this property to null.

    - src/pixi/display/DisplayObject.js:29 + src/pixi/display/DisplayObject.js:31

    @@ -1708,6 +2049,7 @@ To remove a mask, set this property to null.

    The pivot point of the displayObject that it rotates around

    +
    @@ -1741,7 +2083,7 @@ To remove a mask, set this property to null.

    - src/pixi/display/DisplayObject.js:15 + src/pixi/display/DisplayObject.js:15

    @@ -1752,6 +2094,52 @@ To remove a mask, set this property to null.

    The coordinate of the object relative to the local coordinates of the parent.

    + +
    + + + + + + +
    + + +
    +

    renderable

    + Boolean + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/display/DisplayObject.js:80 + +

    + + + + +
    + +
    +

    Can this object be rendered

    +
    @@ -1785,7 +2173,7 @@ To remove a mask, set this property to null.

    - src/pixi/display/DisplayObject.js:36 + src/pixi/display/DisplayObject.js:39

    @@ -1796,6 +2184,7 @@ To remove a mask, set this property to null.

    The rotation of the object in radians.

    +
    @@ -1829,7 +2218,7 @@ To remove a mask, set this property to null.

    - src/pixi/display/DisplayObject.js:22 + src/pixi/display/DisplayObject.js:23

    @@ -1840,6 +2229,7 @@ To remove a mask, set this property to null.

    The scale factor of the object.

    +
    @@ -1873,7 +2263,7 @@ To remove a mask, set this property to null.

    - src/pixi/display/DisplayObject.js:65 + src/pixi/display/DisplayObject.js:97

    @@ -1884,6 +2274,7 @@ To remove a mask, set this property to null.

    [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage.

    +
    @@ -1917,7 +2308,7 @@ To remove a mask, set this property to null.

    - src/pixi/display/DisplayObject.js:50 + src/pixi/display/DisplayObject.js:55

    @@ -1928,6 +2319,99 @@ To remove a mask, set this property to null.

    The visibility of the object.

    + +
    + + + + + + +
    + + +
    +

    worldAlpha

    + Number + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/display/DisplayObject.js:106 + +

    + + + + +
    + +
    +

    [read-only] The multiplied alpha of the displayobject

    + +
    + + + + + + +
    + + +
    +

    worldTransform

    + Mat3 + + + + + private + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/display/DisplayObject.js:125 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object based on world (parent) factors

    +
    @@ -1953,13 +2437,13 @@ To remove a mask, set this property to null.

  • - + - - - - - - + + + + + + diff --git a/docs/classes/DisplayObjectContainer.html b/docs/classes/DisplayObjectContainer.html index aff6af1..10e4c76 100644 --- a/docs/classes/DisplayObjectContainer.html +++ b/docs/classes/DisplayObjectContainer.html @@ -3,11 +3,11 @@ DisplayObjectContainer - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -154,7 +178,7 @@ @@ -170,7 +194,9 @@
    -

    A DisplayObjectContainer represents a collection of display objects. It is the base class of all display objects that act as a container for other objects.

    +

    A DisplayObjectContainer represents a collection of display objects. +It is the base class of all display objects that act as a container for other objects.

    +
    @@ -208,7 +234,7 @@ - src/pixi/display/DisplayObjectContainer.js:6 + src/pixi/display/DisplayObjectContainer.js:6

    @@ -326,14 +352,16 @@ -
  • +
  • setInteractive + deprecated +
  • -
  • +
  • swapChildren @@ -378,6 +406,13 @@ @@ -492,7 +576,7 @@
  • - DisplayObject + child
  • @@ -525,7 +609,7 @@ - src/pixi/display/DisplayObjectContainer.js:42 + src/pixi/display/DisplayObjectContainer.js:32

    @@ -537,6 +621,7 @@

    Adds a child to the container.

    +
    @@ -547,14 +632,15 @@
  • - DisplayObject + child DisplayObject
    - +

    The DisplayObject to add to the container

    +
    @@ -579,7 +665,7 @@
  • - DisplayObject + child
  • @@ -618,7 +704,7 @@ - src/pixi/display/DisplayObjectContainer.js:139 + src/pixi/display/DisplayObjectContainer.js:120

    @@ -630,6 +716,7 @@

    Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown

    +
    @@ -640,14 +727,15 @@
  • - DisplayObject + child DisplayObject
    - +

    The child to add

    +
    @@ -662,7 +750,8 @@
    - +

    The index to place the child in

    +
    @@ -713,11 +802,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:109 + src/pixi/display/DisplayObject.js:174

    @@ -729,6 +818,7 @@

    A callback that is used when the users clicks on the displayObject with their mouse

    +
    @@ -740,7 +830,7 @@
  • interactionData - InteractionData + InteractionData @@ -804,7 +894,7 @@ - src/pixi/display/DisplayObjectContainer.js:274 + src/pixi/display/DisplayObjectContainer.js:256

    @@ -816,6 +906,7 @@

    Returns the Child at the specified index

    +
    @@ -833,7 +924,8 @@
    - +

    The index to get the child from

    +
    @@ -884,11 +976,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:115 + src/pixi/display/DisplayObject.js:180

    @@ -900,6 +992,7 @@

    A callback that is used when the user clicks the mouse down over the sprite

    +
    @@ -911,7 +1004,7 @@
  • interactionData - InteractionData + InteractionData @@ -968,11 +1061,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:141 + src/pixi/display/DisplayObject.js:206

    @@ -984,6 +1077,7 @@

    A callback that is used when the users mouse leaves the displayObject

    +
    @@ -995,7 +1089,7 @@
  • interactionData - InteractionData + InteractionData @@ -1052,11 +1146,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:135 + src/pixi/display/DisplayObject.js:200

    @@ -1068,6 +1162,7 @@

    A callback that is used when the users mouse rolls over the displayObject

    +
    @@ -1079,7 +1174,7 @@
  • interactionData - InteractionData + InteractionData @@ -1136,11 +1231,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:121 + src/pixi/display/DisplayObject.js:186

    @@ -1153,6 +1248,7 @@

    A callback that is used when the user releases the mouse that was over the displayObject for this callback to be fired the mouse must have been pressed down over the displayObject

    +
    @@ -1164,7 +1260,7 @@ for this callback to be fired the mouse must have been pressed down over the dis
  • interactionData - InteractionData + InteractionData @@ -1221,11 +1317,11 @@ for this callback to be fired the mouse must have been pressed down over the dis

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:128 + src/pixi/display/DisplayObject.js:193

    @@ -1238,6 +1334,7 @@ for this callback to be fired the mouse must have been pressed down over the dis

    A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject for this callback to be fired, The touch must have started over the displayObject

    +
    @@ -1249,7 +1346,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • interactionData - InteractionData + InteractionData @@ -1280,7 +1377,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • - DisplayObject + child
  • @@ -1313,7 +1410,7 @@ for this callback to be fired, The touch must have started over the displayObjec - src/pixi/display/DisplayObjectContainer.js:291 + src/pixi/display/DisplayObjectContainer.js:274

    @@ -1325,6 +1422,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    Removes a child from the container.

    +
    @@ -1335,14 +1433,15 @@ for this callback to be fired, The touch must have started over the displayObjec
  • - DisplayObject + child DisplayObject
    - +

    The DisplayObject to remove

    +
    @@ -1358,7 +1457,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • -
    +

    setInteractive

    @@ -1378,6 +1477,8 @@ for this callback to be fired, The touch must have started over the displayObjec + deprecated + @@ -1393,16 +1494,18 @@ for this callback to be fired, The touch must have started over the displayObjec

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:193 + src/pixi/display/DisplayObject.js:247

    +

    Deprecated: Simply set the `interactive` property directly

    +
    @@ -1410,6 +1513,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default Instead of using this function you can now simply set the interactive property to true or false

    +
    @@ -1443,7 +1547,7 @@ Instead of using this function you can now simply set the interactive property t
    -
    +

    swapChildren

    @@ -1452,13 +1556,13 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child
  • - DisplayObject2 + child2
  • @@ -1471,6 +1575,8 @@ Instead of using this function you can now simply set the interactive property t + private + @@ -1491,7 +1597,7 @@ Instead of using this function you can now simply set the interactive property t - src/pixi/display/DisplayObjectContainer.js:227 + src/pixi/display/DisplayObjectContainer.js:207

    @@ -1502,7 +1608,8 @@ Instead of using this function you can now simply set the interactive property t
    -

    Swaps the depth of 2 displayObjects

    +

    [NYI] Swaps the depth of 2 displayObjects

    +
    @@ -1513,7 +1620,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child DisplayObject @@ -1528,7 +1635,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject2 + child2 DisplayObject @@ -1586,11 +1693,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:152 + src/pixi/display/DisplayObject.js:217

    @@ -1603,6 +1710,7 @@ Instead of using this function you can now simply set the interactive property t

    A callback that is used when the users taps on the sprite with their finger basically a touch version of click

    +
    @@ -1614,7 +1722,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -1671,11 +1779,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:165 + src/pixi/display/DisplayObject.js:230

    @@ -1687,6 +1795,7 @@ basically a touch version of click

    A callback that is used when the user releases a touch over the displayObject

    +
    @@ -1698,7 +1807,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -1755,11 +1864,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:171 + src/pixi/display/DisplayObject.js:236

    @@ -1772,6 +1881,7 @@ basically a touch version of click

    A callback that is used when the user releases the touch that was over the displayObject for this callback to be fired, The touch must have started over the sprite

    +
    @@ -1783,7 +1893,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -1840,11 +1950,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:159 + src/pixi/display/DisplayObject.js:224

    @@ -1855,7 +1965,8 @@ for this callback to be fired, The touch must have started over the sprite

  • -

    A callback that is used when the user touch's over the displayObject

    +

    A callback that is used when the user touch's over the displayObject

    +
    @@ -1867,7 +1978,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -1897,6 +2008,50 @@ for this callback to be fired, The touch must have started over the sprite

    Properties

    +
    +

    _interactive

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:115 + +

    + + + + +
    + +
    +

    [read-only] Whether or not the object is interactive, do not toggle directly! use the interactive property

    + +
    + + + + + + +
    + +

    alpha

    Number @@ -1913,11 +2068,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:43 + src/pixi/display/DisplayObject.js:47

    @@ -1928,6 +2083,7 @@ for this callback to be fired, The touch must have started over the sprite

    The opacity of the object.

    +
    @@ -1954,11 +2110,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:98 + src/pixi/display/DisplayObject.js:72

    @@ -1969,6 +2125,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is used to indicate if the displayObject should display a mouse hand cursor on rollover

    +
    @@ -1981,7 +2138,7 @@ for this callback to be fired, The touch must have started over the sprite

    children

    - Array + Array @@ -2002,7 +2159,7 @@ for this callback to be fired, The touch must have started over the sprite

    - src/pixi/display/DisplayObjectContainer.js:16 + src/pixi/display/DisplayObjectContainer.js:18

    @@ -2013,6 +2170,7 @@ for this callback to be fired, The touch must have started over the sprite

    [read-only] The of children of this container.

    +
    @@ -2023,9 +2181,97 @@ for this callback to be fired, The touch must have started over the sprite

    -
    -

    hitArea

    - Rectangle +
    +

    color

    + Array<> + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:145 + +

    + + + + +
    + +
    +

    [NYI] Unkown

    + +
    + + + + + + +
    + + +
    +

    dynamic

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:154 + +

    + + + + +
    + +
    +

    [NYI] Holds whether or not this object is dynamic, for rendering optimization

    + +
    + + + + + + +
    + + +
    +

    filters

    + Array An array of filters @@ -2039,11 +2285,55 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:72 + src/pixi/display/DisplayObject.js:318 + +

    + + + + +
    + +
    +

    Sets the filters for the displayObject. +* IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer. +To remove filters simply set this property to 'null'

    + +
    + + + + + + +
    + + +
    +

    hitArea

    + Rectangle | Circle | Ellipse | Polygon + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:63

    @@ -2055,6 +2345,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is the defined area that will pick up mouse / touch events. It is null by default. Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children)

    +
    @@ -2081,11 +2372,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:204 + src/pixi/display/DisplayObject.js:260

    @@ -2096,6 +2387,53 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Indicates if the sprite will have touch and mouse interactivity. It is false by default

    + +
    + + +

    Default: false

    + + + + + +
    + + +
    +

    localTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:135 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object locally

    +
    @@ -2108,7 +2446,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    mask

    - PIXI.Graphics + Graphics @@ -2122,11 +2460,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:222 + src/pixi/display/DisplayObject.js:280

    @@ -2139,6 +2477,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. To remove a mask, set this property to null.

    +
    @@ -2165,11 +2504,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:58 + src/pixi/display/DisplayObject.js:88

    @@ -2180,6 +2519,7 @@ To remove a mask, set this property to null.

    [read-only] The display object container that contains this display object.

    +
    @@ -2206,11 +2546,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:29 + src/pixi/display/DisplayObject.js:31

    @@ -2221,6 +2561,7 @@ To remove a mask, set this property to null.

    The pivot point of the displayObject that it rotates around

    +
    @@ -2247,11 +2588,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:15 + src/pixi/display/DisplayObject.js:15

    @@ -2262,6 +2603,49 @@ To remove a mask, set this property to null.

    The coordinate of the object relative to the local coordinates of the parent.

    + +
    + + + + + + +
    + + +
    +

    renderable

    + Boolean + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:80 + +

    + + + + +
    + +
    +

    Can this object be rendered

    +
    @@ -2288,11 +2672,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:36 + src/pixi/display/DisplayObject.js:39

    @@ -2303,6 +2687,7 @@ To remove a mask, set this property to null.

    The rotation of the object in radians.

    +
    @@ -2329,11 +2714,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:22 + src/pixi/display/DisplayObject.js:23

    @@ -2344,6 +2729,7 @@ To remove a mask, set this property to null.

    The scale factor of the object.

    +
    @@ -2370,11 +2756,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:65 + src/pixi/display/DisplayObject.js:97

    @@ -2385,6 +2771,7 @@ To remove a mask, set this property to null.

    [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage.

    +
    @@ -2411,11 +2798,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:50 + src/pixi/display/DisplayObject.js:55

    @@ -2426,6 +2813,93 @@ To remove a mask, set this property to null.

    The visibility of the object.

    + +
    + + + + + + +
    + + +
    +

    worldAlpha

    + Number + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:106 + +

    + + + + +
    + +
    +

    [read-only] The multiplied alpha of the displayobject

    + +
    + + + + + + +
    + + +
    +

    worldTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:125 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object based on world (parent) factors

    +
    @@ -2451,13 +2925,13 @@ To remove a mask, set this property to null.

    - + - - - - - - + + + + + + diff --git a/docs/classes/Ellipse.html b/docs/classes/Ellipse.html index c5b5e4e..7fbc4b1 100644 --- a/docs/classes/Ellipse.html +++ b/docs/classes/Ellipse.html @@ -3,11 +3,11 @@ Ellipse - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -150,7 +174,7 @@ @@ -166,7 +190,8 @@
    - +

    The Ellipse object can be used to specify a hit area for displayobjects

    +
    @@ -232,7 +257,7 @@ - src/pixi/core/Ellipse.js:5 + src/pixi/core/Ellipse.js:5

    @@ -261,7 +286,8 @@
    -

    The X coord of the upper-left corner of the framing rectangle of this circle

    +

    The X coord of the upper-left corner of the framing rectangle of this ellipse

    +
    @@ -276,7 +302,8 @@
    -

    The Y coord of the upper-left corner of the framing rectangle of this circle

    +

    The Y coord of the upper-left corner of the framing rectangle of this ellipse

    +
    @@ -291,7 +318,8 @@
    -

    The overall height of this ellipse

    +

    The overall width of this ellipse

    +
    @@ -306,7 +334,8 @@
    -

    The overall width of this ellipse

    +

    The overall height of this ellipse

    +
    @@ -423,7 +452,7 @@ - + Ellipse @@ -450,7 +479,7 @@ - src/pixi/core/Ellipse.js:44 + src/pixi/core/Ellipse.js:46

    @@ -461,7 +490,8 @@
    - +

    Creates a clone of this Ellipse instance

    +
    @@ -473,7 +503,10 @@
    - a copy of the polygon + Ellipse: + +

    a copy of the ellipse

    +
    @@ -508,7 +541,7 @@ - + Boolean @@ -535,7 +568,7 @@ - src/pixi/core/Ellipse.js:53 + src/pixi/core/Ellipse.js:57

    @@ -546,7 +579,8 @@
  • - +

    Checks if the x, and y coords passed to this function are contained within this ellipse

    +
    @@ -565,6 +599,7 @@

    The X coord of the point to test

    +
    @@ -580,6 +615,7 @@

    The Y coord of the point to test

    +
    @@ -596,7 +632,10 @@
    - if the x/y coords are within this polygon + Boolean: + +

    if the x/y coords are within this ellipse

    +
    @@ -637,7 +676,7 @@ - src/pixi/core/Ellipse.js:36 + src/pixi/core/Ellipse.js:38

    @@ -683,7 +722,7 @@ - src/pixi/core/Ellipse.js:29 + src/pixi/core/Ellipse.js:31

    @@ -729,7 +768,7 @@ - src/pixi/core/Ellipse.js:15 + src/pixi/core/Ellipse.js:17

    @@ -775,7 +814,7 @@ - src/pixi/core/Ellipse.js:22 + src/pixi/core/Ellipse.js:24

    @@ -813,13 +852,13 @@ - + - - - - - - + + + + + + diff --git a/docs/classes/EventTarget.html b/docs/classes/EventTarget.html new file mode 100644 index 0000000..a25d62d --- /dev/null +++ b/docs/classes/EventTarget.html @@ -0,0 +1,454 @@ + + + + + EventTarget - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    EventTarget Class

    +
    + + + + + + + + + + + Module: PIXI + + + + +
    + + + +
    +

    Adds event emitter functionality to a class

    + +
    + + + +
    + + +
    +
    +

    Item Index

    + + +
    +

    Methods

    + + +
    + + + + + + + +
    + + +
    +

    Methods

    + + +
    +

    autoDetectRenderer

    + + +
    + (
      + +
    • + + width + +
    • + +
    • + + height + +
    • + +
    • + + view + +
    • + +
    • + + transparent=false + +
    • + +
    • + + antialias=false + +
    • + +
    ) +
    + + + + + + + + + + + + static + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/utils/Detector.js:5 + +

    + + + + + +
    + +
    +

    This helper function will automatically detect which renderer you should be using. +WebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by +the browser then this function will return a canvas renderer

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + width + Number + + + + +
      +

      the width of the renderers view

      + +
      + + +
    • + +
    • + + height + Number + + + + +
      +

      the height of the renderers view

      + +
      + + +
    • + +
    • + + view + Canvas + + + + +
      +

      the canvas to use as a view, optional

      + +
      + + +
    • + +
    • + + transparent=false + Boolean + + + + +
      +

      the transparency of the render view, default false

      + +
      + + +
    • + +
    • + + antialias=false + Boolean + + + + +
      +

      sets antialias (only applicable in webGL chrome at the moment)

      +

      antialias

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    + + + + + + + +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/classes/Graphics.html b/docs/classes/Graphics.html index 99e71fc..5fd3d7c 100644 --- a/docs/classes/Graphics.html +++ b/docs/classes/Graphics.html @@ -3,11 +3,11 @@ Graphics - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -154,7 +178,7 @@ @@ -170,9 +194,10 @@
    -

    The Graphics class contains a set of methods that you can use to create primitive shapes and lines. +

    The Graphics class contains a set of methods that you can use to create primitive shapes and lines. It is important to know that with the webGL renderer only simple polys can be filled at this stage -Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png

    +Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png

    +
    @@ -210,7 +235,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www - src/pixi/primitives/Graphics.js:6 + src/pixi/primitives/Graphics.js:6

    @@ -391,14 +416,16 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www -
  • +
  • setInteractive + deprecated +
  • -
  • +
  • swapChildren @@ -443,6 +470,13 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
      +
    • + _interactive + + + +
    • +
    • alpha @@ -462,6 +496,48 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www +
    • + +
    • + color + + + +
    • + +
    • + currentPath + + + +
    • + +
    • + dynamic + + + +
    • + +
    • + fillAlpha + + + +
    • + +
    • + filters + + + +
    • + +
    • + graphicsData + + +
    • @@ -476,6 +552,27 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www +
    • + +
    • + lineColor + + + +
    • + +
    • + lineWidth + + + +
    • + +
    • + localTransform + + +
    • @@ -504,6 +601,13 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www +
    • + +
    • + renderable + + +
    • @@ -532,6 +636,20 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www +
    • + +
    • + worldAlpha + + + +
    • + +
    • + worldTransform + + +
    @@ -557,7 +675,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
  • - DisplayObject + child
  • @@ -583,11 +701,11 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:42 + src/pixi/display/DisplayObjectContainer.js:32

    @@ -599,6 +717,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Adds a child to the container.

    +
    @@ -609,14 +728,15 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
  • - DisplayObject + child DisplayObject
    - +

    The DisplayObject to add to the container

    +
    @@ -641,7 +761,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
  • - DisplayObject + child
  • @@ -673,11 +793,11 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:139 + src/pixi/display/DisplayObjectContainer.js:120

    @@ -689,6 +809,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown

    +
    @@ -699,14 +820,15 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
  • - DisplayObject + child DisplayObject
    - +

    The child to add

    +
    @@ -721,7 +843,8 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
    - +

    The index to place the child in

    +
    @@ -785,7 +908,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www - src/pixi/primitives/Graphics.js:85 + src/pixi/primitives/Graphics.js:123

    @@ -796,7 +919,9 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
  • -

    Specifies a simple one-color fill that subsequent calls to other Graphics methods (such as lineTo() or drawCircle()) use when drawing.

    +

    Specifies a simple one-color fill that subsequent calls to other Graphics methods +(such as lineTo() or drawCircle()) use when drawing.

    +
    @@ -815,6 +940,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    the color of the fill

    +
    @@ -830,6 +956,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    the alpha

    +
    @@ -877,7 +1004,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www - src/pixi/primitives/Graphics.js:167 + src/pixi/primitives/Graphics.js:211

    @@ -889,6 +1016,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings.

    +
    @@ -934,11 +1062,11 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:109 + src/pixi/display/DisplayObject.js:174

    @@ -950,6 +1078,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    A callback that is used when the users clicks on the displayObject with their mouse

    +
    @@ -961,7 +1090,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
  • interactionData - InteractionData + InteractionData @@ -1037,7 +1166,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www - src/pixi/primitives/Graphics.js:128 + src/pixi/primitives/Graphics.js:170

    @@ -1049,6 +1178,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Draws a circle.

    +
    @@ -1066,7 +1196,8 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
    - +

    The X coord of the center of the circle

    +
    @@ -1081,7 +1212,8 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
    - +

    The Y coord of the center of the circle

    +
    @@ -1096,7 +1228,8 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
    - +

    The radius of the circle

    +
    @@ -1172,7 +1305,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www - src/pixi/primitives/Graphics.js:147 + src/pixi/primitives/Graphics.js:190

    @@ -1184,6 +1317,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Draws an elipse.

    +
    @@ -1322,7 +1456,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www - src/pixi/primitives/Graphics.js:109 + src/pixi/primitives/Graphics.js:150

    @@ -1351,7 +1485,8 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
    - +

    The X coord of the top-left of the rectangle

    +
    @@ -1366,7 +1501,8 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
    - +

    The Y coord of the top-left of the rectangle

    +
    @@ -1381,7 +1517,8 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
    - +

    The width of the rectangle

    +
    @@ -1396,7 +1533,8 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
    - +

    The height of the rectangle

    +
    @@ -1444,7 +1582,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www - src/pixi/primitives/Graphics.js:98 + src/pixi/primitives/Graphics.js:138

    @@ -1456,6 +1594,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Applies a fill to the lines and shapes that were added since the last call to the beginFill() method.

    +
    @@ -1501,11 +1640,11 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:274 + src/pixi/display/DisplayObjectContainer.js:256

    @@ -1517,6 +1656,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Returns the Child at the specified index

    +
    @@ -1534,7 +1674,8 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
    - +

    The index to get the child from

    +
    @@ -1604,7 +1745,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www - src/pixi/primitives/Graphics.js:34 + src/pixi/primitives/Graphics.js:68

    @@ -1616,6 +1757,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Specifies a line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method.

    +
    @@ -1633,7 +1775,8 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
    - +

    width of the line to draw, will update the object's stored style

    +
    @@ -1648,7 +1791,8 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
    - +

    color of the line to draw, will update the object's stored style

    +
    @@ -1663,7 +1807,8 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
    - +

    alpha of the line to draw, will update the object's stored style

    +
    @@ -1727,7 +1872,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www - src/pixi/primitives/Graphics.js:73 + src/pixi/primitives/Graphics.js:109

    @@ -1738,7 +1883,9 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
  • -

    Draws a line using the current line style from the current drawing position to (x, y); the current drawing position is then set to (x, y).

    +

    Draws a line using the current line style from the current drawing position to (x, y); +the current drawing position is then set to (x, y).

    +
    @@ -1756,7 +1903,8 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
    - +

    the X coord to draw to

    +
    @@ -1771,7 +1919,8 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
    - +

    the Y coord to draw to

    +
    @@ -1822,11 +1971,11 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:115 + src/pixi/display/DisplayObject.js:180

    @@ -1838,6 +1987,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    A callback that is used when the user clicks the mouse down over the sprite

    +
    @@ -1849,7 +1999,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
  • interactionData - InteractionData + InteractionData @@ -1906,11 +2056,11 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:141 + src/pixi/display/DisplayObject.js:206

    @@ -1922,6 +2072,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    A callback that is used when the users mouse leaves the displayObject

    +
    @@ -1933,7 +2084,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
  • interactionData - InteractionData + InteractionData @@ -1990,11 +2141,11 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:135 + src/pixi/display/DisplayObject.js:200

    @@ -2006,6 +2157,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    A callback that is used when the users mouse rolls over the displayObject

    +
    @@ -2017,7 +2169,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www
  • interactionData - InteractionData + InteractionData @@ -2074,11 +2226,11 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:121 + src/pixi/display/DisplayObject.js:186

    @@ -2091,6 +2243,7 @@ Complex polys will not be filled. Heres an example of a complex poly: http://www

    A callback that is used when the user releases the mouse that was over the displayObject for this callback to be fired the mouse must have been pressed down over the displayObject

    +
    @@ -2102,7 +2255,7 @@ for this callback to be fired the mouse must have been pressed down over the dis
  • interactionData - InteractionData + InteractionData @@ -2159,11 +2312,11 @@ for this callback to be fired the mouse must have been pressed down over the dis

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:128 + src/pixi/display/DisplayObject.js:193

    @@ -2176,6 +2329,7 @@ for this callback to be fired the mouse must have been pressed down over the dis

    A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject for this callback to be fired, The touch must have started over the displayObject

    +
    @@ -2187,7 +2341,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • interactionData - InteractionData + InteractionData @@ -2257,7 +2411,7 @@ for this callback to be fired, The touch must have started over the displayObjec - src/pixi/primitives/Graphics.js:55 + src/pixi/primitives/Graphics.js:90

    @@ -2269,6 +2423,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    Moves the current drawing position to (x, y).

    +
    @@ -2286,7 +2441,8 @@ for this callback to be fired, The touch must have started over the displayObjec
    - +

    the X coord to move to

    +
    @@ -2301,7 +2457,8 @@ for this callback to be fired, The touch must have started over the displayObjec
    - +

    the Y coord to move to

    +
    @@ -2326,7 +2483,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • - DisplayObject + child
  • @@ -2352,11 +2509,11 @@ for this callback to be fired, The touch must have started over the displayObjec

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:291 + src/pixi/display/DisplayObjectContainer.js:274

    @@ -2368,6 +2525,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    Removes a child from the container.

    +
    @@ -2378,14 +2536,15 @@ for this callback to be fired, The touch must have started over the displayObjec
  • - DisplayObject + child DisplayObject
    - +

    The DisplayObject to remove

    +
    @@ -2401,7 +2560,7 @@ for this callback to be fired, The touch must have started over the displayObjec -
    +

    setInteractive

    @@ -2421,6 +2580,8 @@ for this callback to be fired, The touch must have started over the displayObjec + deprecated + @@ -2436,16 +2597,18 @@ for this callback to be fired, The touch must have started over the displayObjec

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:193 + src/pixi/display/DisplayObject.js:247

    +

    Deprecated: Simply set the `interactive` property directly

    +
    @@ -2453,6 +2616,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default Instead of using this function you can now simply set the interactive property to true or false

    +
    @@ -2486,7 +2650,7 @@ Instead of using this function you can now simply set the interactive property t
    -
    +

    swapChildren

    @@ -2495,13 +2659,13 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child
  • - DisplayObject2 + child2
  • @@ -2514,6 +2678,8 @@ Instead of using this function you can now simply set the interactive property t + private + @@ -2527,11 +2693,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:227 + src/pixi/display/DisplayObjectContainer.js:207

    @@ -2542,7 +2708,8 @@ Instead of using this function you can now simply set the interactive property t
    -

    Swaps the depth of 2 displayObjects

    +

    [NYI] Swaps the depth of 2 displayObjects

    +
    @@ -2553,7 +2720,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child DisplayObject @@ -2568,7 +2735,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject2 + child2 DisplayObject @@ -2626,11 +2793,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:152 + src/pixi/display/DisplayObject.js:217

    @@ -2643,6 +2810,7 @@ Instead of using this function you can now simply set the interactive property t

    A callback that is used when the users taps on the sprite with their finger basically a touch version of click

    +
    @@ -2654,7 +2822,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -2711,11 +2879,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:165 + src/pixi/display/DisplayObject.js:230

    @@ -2727,6 +2895,7 @@ basically a touch version of click

    A callback that is used when the user releases a touch over the displayObject

    +
    @@ -2738,7 +2907,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -2795,11 +2964,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:171 + src/pixi/display/DisplayObject.js:236

    @@ -2812,6 +2981,7 @@ basically a touch version of click

    A callback that is used when the user releases the touch that was over the displayObject for this callback to be fired, The touch must have started over the sprite

    +
    @@ -2823,7 +2993,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -2880,11 +3050,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:159 + src/pixi/display/DisplayObject.js:224

    @@ -2895,7 +3065,8 @@ for this callback to be fired, The touch must have started over the sprite

    -

    A callback that is used when the user touch's over the displayObject

    +

    A callback that is used when the user touch's over the displayObject

    +
    @@ -2907,7 +3078,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -2937,6 +3108,50 @@ for this callback to be fired, The touch must have started over the sprite

    Properties

    +
    +

    _interactive

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:115 + +

    + + + + +
    + +
    +

    [read-only] Whether or not the object is interactive, do not toggle directly! use the interactive property

    + +
    + + + + + + +
    + +

    alpha

    Number @@ -2953,11 +3168,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:43 + src/pixi/display/DisplayObject.js:47

    @@ -2968,6 +3183,7 @@ for this callback to be fired, The touch must have started over the sprite

    The opacity of the object.

    +
    @@ -2994,11 +3210,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:98 + src/pixi/display/DisplayObject.js:72

    @@ -3009,6 +3225,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is used to indicate if the displayObject should display a mouse hand cursor on rollover

    +
    @@ -3021,7 +3238,7 @@ for this callback to be fired, The touch must have started over the sprite

    children

    - Array + Array @@ -3035,11 +3252,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:16 + src/pixi/display/DisplayObjectContainer.js:18

    @@ -3050,6 +3267,278 @@ for this callback to be fired, The touch must have started over the sprite

    [read-only] The of children of this container.

    + +
    + + + + + + +
    + + +
    +

    color

    + Array<> + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:145 + +

    + + + + +
    + +
    +

    [NYI] Unkown

    + +
    + + + + + + +
    + + +
    +

    currentPath

    + Object + + + + + private + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/primitives/Graphics.js:54 + +

    + + + + +
    + +
    +

    Current path

    + +
    + + + + + + +
    + + +
    +

    dynamic

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:154 + +

    + + + + +
    + +
    +

    [NYI] Holds whether or not this object is dynamic, for rendering optimization

    + +
    + + + + + + +
    + + +
    +

    fillAlpha

    + Number + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/primitives/Graphics.js:21 + +

    + + + + +
    + +
    +

    The alpha of the fill of this graphics object

    + +
    + + + + + + +
    + + +
    +

    filters

    + Array An array of filters + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:318 + +

    + + + + +
    + +
    +

    Sets the filters for the displayObject. +* IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer. +To remove filters simply set this property to 'null'

    + +
    + + + + + + +
    + + +
    +

    graphicsData

    + Array + + + + + private + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/primitives/Graphics.js:45 + +

    + + + + +
    + +
    +

    Graphics data

    +
    @@ -3062,7 +3551,7 @@ for this callback to be fired, The touch must have started over the sprite

    hitArea

    - Rectangle + Rectangle | Circle | Ellipse | Polygon @@ -3076,11 +3565,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:72 + src/pixi/display/DisplayObject.js:63

    @@ -3092,6 +3581,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is the defined area that will pick up mouse / touch events. It is null by default. Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children)

    +
    @@ -3118,11 +3608,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:204 + src/pixi/display/DisplayObject.js:260

    @@ -3133,6 +3623,143 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Indicates if the sprite will have touch and mouse interactivity. It is false by default

    + +
    + + +

    Default: false

    + + + + + +
    + + +
    +

    lineColor

    + String + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/primitives/Graphics.js:37 + +

    + + + + +
    + +
    +

    The color of any lines drawn

    + +
    + + + + + + +
    + + +
    +

    lineWidth

    + Number + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/primitives/Graphics.js:29 + +

    + + + + +
    + +
    +

    The width of any lines drawn

    + +
    + + + + + + +
    + + +
    +

    localTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:135 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object locally

    +
    @@ -3145,7 +3772,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    mask

    - PIXI.Graphics + Graphics @@ -3159,11 +3786,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:222 + src/pixi/display/DisplayObject.js:280

    @@ -3176,6 +3803,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. To remove a mask, set this property to null.

    +
    @@ -3202,11 +3830,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:58 + src/pixi/display/DisplayObject.js:88

    @@ -3217,6 +3845,7 @@ To remove a mask, set this property to null.

    [read-only] The display object container that contains this display object.

    +
    @@ -3243,11 +3872,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:29 + src/pixi/display/DisplayObject.js:31

    @@ -3258,6 +3887,7 @@ To remove a mask, set this property to null.

    The pivot point of the displayObject that it rotates around

    +
    @@ -3284,11 +3914,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:15 + src/pixi/display/DisplayObject.js:15

    @@ -3299,6 +3929,49 @@ To remove a mask, set this property to null.

    The coordinate of the object relative to the local coordinates of the parent.

    + +
    + + + + + + +
    + + +
    +

    renderable

    + Boolean + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:80 + +

    + + + + +
    + +
    +

    Can this object be rendered

    +
    @@ -3325,11 +3998,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:36 + src/pixi/display/DisplayObject.js:39

    @@ -3340,6 +4013,7 @@ To remove a mask, set this property to null.

    The rotation of the object in radians.

    +
    @@ -3366,11 +4040,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:22 + src/pixi/display/DisplayObject.js:23

    @@ -3381,6 +4055,7 @@ To remove a mask, set this property to null.

    The scale factor of the object.

    +
    @@ -3407,11 +4082,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:65 + src/pixi/display/DisplayObject.js:97

    @@ -3422,6 +4097,7 @@ To remove a mask, set this property to null.

    [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage.

    +
    @@ -3448,11 +4124,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:50 + src/pixi/display/DisplayObject.js:55

    @@ -3463,6 +4139,93 @@ To remove a mask, set this property to null.

    The visibility of the object.

    + +
    + + + + + + +
    + + +
    +

    worldAlpha

    + Number + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:106 + +

    + + + + +
    + +
    +

    [read-only] The multiplied alpha of the displayobject

    + +
    + + + + + + +
    + + +
    +

    worldTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:125 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object based on world (parent) factors

    +
    @@ -3488,13 +4251,13 @@ To remove a mask, set this property to null.

    - + - - - - - - + + + + + + diff --git a/docs/classes/GreyFilter.html b/docs/classes/GreyFilter.html new file mode 100644 index 0000000..4f47931 --- /dev/null +++ b/docs/classes/GreyFilter.html @@ -0,0 +1,315 @@ + + + + + GreyFilter - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    GreyFilter Class

    +
    + + + + + + + + + + + Module: PIXI + + + + +
    + + + +
    +

    This turns your displayObjects to black and white.

    + +
    + + + +
    + + +
    +
    +

    Item Index

    + + + + +
    +

    Properties

    + +
      + +
    • + grey + + + +
    • + +
    +
    + + + + + +
    + + + + +
    +

    Properties

    + + +
    +

    grey

    + Unknown + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/filters/GreyFilter.js:40 + +

    + + + + +
    + +
    +

    The strength of the grey. 1 will make the object black and white, 0 will make the object its normal color

    + +
    + + + + + + +
    + + +
    + + + + + +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/classes/ImageLoader.html b/docs/classes/ImageLoader.html index 0400bba..d2ef76d 100644 --- a/docs/classes/ImageLoader.html +++ b/docs/classes/ImageLoader.html @@ -3,11 +3,11 @@ ImageLoader - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -145,16 +169,21 @@

    ImageLoader Class

    - - -
    - Extends EventTarget +
    + Uses +
    + + @@ -170,9 +199,10 @@
    -

    The image loader class is responsible for loading images file formats ("jpeg", "jpg", "png" and "gif") +

    The image loader class is responsible for loading images file formats ("jpeg", "jpg", "png" and "gif") Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() -When loaded this class will dispatch a 'loaded' event

    +When loaded this class will dispatch a 'loaded' event

    +
    @@ -226,7 +256,7 @@ When loaded this class will dispatch a 'loaded' event

    - src/pixi/loaders/ImageLoader.js:5 + src/pixi/loaders/ImageLoader.js:5

    @@ -256,6 +286,7 @@ When loaded this class will dispatch a 'loaded' event

    The url of the image

    +
    @@ -270,7 +301,8 @@ When loaded this class will dispatch a 'loaded' event

    - +

    Whether requests should be treated as crossorigin

    +
    @@ -293,6 +325,10 @@ When loaded this class will dispatch a 'loaded' event

  • Index
  • +
  • Methods
  • + + +
  • Properties
  • @@ -303,7 +339,51 @@ When loaded this class will dispatch a 'loaded' event

    Item Index

    +
    +

    Methods

    + +
    + + + +
    +

    Properties

    + + +
    @@ -312,7 +392,309 @@ When loaded this class will dispatch a 'loaded' event

    +
    +

    Methods

    + +
    +

    load

    + + + () + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/ImageLoader.js:39 + +

    + + + + + +
    + +
    +

    Loads image or takes it from cache

    + +
    + + + + + + +
    + + +
    +

    loadFramedSpriteSheet

    + + +
    + (
      + +
    • + + frameWidth + +
    • + +
    • + + frameHeight + +
    • + +
    • + + textureName + +
    • + +
    ) +
    + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/ImageLoader.js:71 + +

    + + + + + +
    + +
    +

    Loads image and split it to uniform sized frames

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + frameWidth + Number + + + + +
      +

      with of each frame

      + +
      + + +
    • + +
    • + + frameHeight + Number + + + + +
      +

      height of each frame

      + +
      + + +
    • + +
    • + + textureName + String + + + + +
      +

      if given, the frames will be cached in - format

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    onLoaded

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/ImageLoader.js:60 + +

    + + + + + +
    + +
    +

    Invoked when image file is loaded or it is already cached and ready to use

    + +
    + + + + + + +
    + + +
    + + + +
    +

    Properties

    + + +
    +

    texture

    + Texture + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/ImageLoader.js:20 + +

    + + + + +
    + +
    +

    The texture being loaded

    + +
    + + + + + + +
    + + +
    @@ -327,13 +709,13 @@ When loaded this class will dispatch a 'loaded' event

    - + - - - - - - + + + + + + diff --git a/docs/classes/InteractionManager.html b/docs/classes/InteractionManager.html deleted file mode 100644 index 54f508b..0000000 --- a/docs/classes/InteractionManager.html +++ /dev/null @@ -1,660 +0,0 @@ - - - - - InteractionManager - Pixi.JS - - - - - - - - -
    -
    -
    - -

    - -
    -
    - API Docs for: 1.3.0 -
    -
    -
    - - -
    -
    - Show: - - - - - - - -
    - - -
    -
    -
    -

    InteractionManager Class

    -
    - - - - - - - - - - - Module: PIXI - - - - -
    - - - -
    -

    The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive -This manager also supports multitouch.

    -
    - - -
    -

    Constructor

    -
    -

    InteractionManager

    - - -
    - (
      - -
    • - - stage - -
    • - -
    ) -
    - - - - - - - - - - - - - - - - -
    - - - -

    - - Defined in - - - - - src/pixi/InteractionManager.js:7 - -

    - - - - - -
    - -
    - -
    - - -
    -

    Parameters:

    - -
      - -
    • - - stage - Stage - - - - -
      - -
      - - -
    • - -
    -
    - - - - - -
    - -
    - - -
    - - -
    -
    -

    Item Index

    - - -
    -

    Methods

    - - -
    - - - -
    -

    Properties

    - - -
    - - - - - -
    - - -
    -

    Methods

    - - -
    -

    autoDetectRenderer

    - - -
    - (
      - -
    • - - width - -
    • - -
    • - - height - -
    • - -
    • - - view - -
    • - -
    • - - transparent - -
    • - -
    ) -
    - - - - - - - - - - - - static - - - - - - -
    - - - -

    - - Defined in - - - - - src/pixi/utils/Detector.js:5 - -

    - - - - - -
    - -
    -

    This helper function will automatically detect which renderer you should be using. -WebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by the browser then this function will return a canvas renderer

    -
    - - -
    -

    Parameters:

    - -
      - -
    • - - width - Number - - - - -
      -

      the width of the renderers view

      -
      - - -
    • - -
    • - - height - Number - - - - -
      -

      the height of the renderers view

      -
      - - -
    • - -
    • - - view - Canvas - - - - -
      -

      the canvas to use as a view, optional

      -
      - - -
    • - -
    • - - transparent - Boolean - - - - -
      -

      the transparency of the render view, default false

      -
      - - -
    • - -
    -
    - - - - - -
    - - -
    - - - -
    -

    Properties

    - - -
    -

    mouse

    - InteractionData - - - - - - - - - -
    - - - -

    - - Defined in - - - - - src/pixi/InteractionManager.js:30 - -

    - - - - -
    - -
    -

    the mouse data

    -
    - - - - - - -
    - - -
    -

    stage

    - Stage - - - - - - - - - -
    - - - -

    - - Defined in - - - - - src/pixi/InteractionManager.js:17 - -

    - - - - -
    - -
    -

    a refference to the stage

    -
    - - - - - - -
    - - -
    -

    touchs

    - Object - - - - - - - - - -
    - - - -

    - - Defined in - - - - - src/pixi/InteractionManager.js:37 - -

    - - - - -
    - -
    -

    an object that stores current touches (InteractionData) by id reference

    -
    - - - - - - -
    - - -
    - - - - - -
    -
    - -
    -
    -
    -
    -
    -
    - - - - - - - - - - diff --git a/docs/classes/InvertFilter.html b/docs/classes/InvertFilter.html new file mode 100644 index 0000000..d2184c7 --- /dev/null +++ b/docs/classes/InvertFilter.html @@ -0,0 +1,315 @@ + + + + + InvertFilter - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    InvertFilter Class

    +
    + + + + + + + + + + + Module: PIXI + + + + +
    + + + +
    +

    This inverts your displayObjects colors.

    + +
    + + + +
    + + +
    +
    +

    Item Index

    + + + + +
    +

    Properties

    + + +
    + + + + + +
    + + + + +
    +

    Properties

    + + +
    +

    invert

    + Unknown + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/filters/InvertFilter.js:41 + +

    + + + + +
    + +
    +

    The strength of the invert. 1 will fully invert the colors, 0 will make the object its normal color

    + +
    + + + + + + +
    + + +
    + + + + + +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/classes/JsonLoader.html b/docs/classes/JsonLoader.html index a7e8161..c5c510b 100644 --- a/docs/classes/JsonLoader.html +++ b/docs/classes/JsonLoader.html @@ -3,11 +3,11 @@ JsonLoader - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -145,16 +169,21 @@

    JsonLoader Class

    - - -
    - Extends EventTarget +
    + Uses +
    + + @@ -171,8 +200,9 @@

    The json file loader is used to load in JSON data and parsing it -When loaded this class will dispatch a "loaded" event -If load failed this class will dispatch a "error" event

    +When loaded this class will dispatch a "loaded" event +If load failed this class will dispatch a "error" event

    +
    @@ -226,7 +256,7 @@ If load failed this class will dispatch a "error" event

    - src/pixi/loaders/JsonLoader.js:5 + src/pixi/loaders/JsonLoader.js:5

    @@ -255,7 +285,8 @@ If load failed this class will dispatch a "error" event

    -

    the url of the JSON file

    +

    The url of the JSON file

    +
    @@ -270,7 +301,8 @@ If load failed this class will dispatch a "error" event

    - +

    Whether requests should be treated as crossorigin

    +
    @@ -293,6 +325,10 @@ If load failed this class will dispatch a "error" event

  • Index
  • +
  • Methods
  • + + +
  • Properties
  • @@ -303,7 +339,79 @@ If load failed this class will dispatch a "error" event

    Item Index

    +
    +

    Methods

    + +
    + + + +
    +

    Properties

    + + +
    @@ -312,7 +420,425 @@ If load failed this class will dispatch a "error" event

    +
    +

    Methods

    + +
    +

    load

    + + + () + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/JsonLoader.js:58 + +

    + + + + + +
    + +
    +

    Loads the JSON data

    + +
    + + + + + + +
    + + +
    +

    onError

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/JsonLoader.js:154 + +

    + + + + + +
    + +
    +

    Invoke when error occured

    + +
    + + + + + + +
    + + +
    +

    onJSONLoaded

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/JsonLoader.js:75 + +

    + + + + + +
    + +
    +

    Invoke when JSON file is loaded

    + +
    + + + + + + +
    + + +
    +

    onLoaded

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/JsonLoader.js:140 + +

    + + + + + +
    + +
    +

    Invoke when json file loaded

    + +
    + + + + + + +
    + + +
    + + + +
    +

    Properties

    + + +
    +

    baseUrl

    + String + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/JsonLoader.js:35 + +

    + + + + +
    + +
    +

    [read-only] The base url of the bitmap font data

    + +
    + + + + + + +
    + + +
    +

    crossorigin

    + Boolean + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/JsonLoader.js:27 + +

    + + + + +
    + +
    +

    Whether the requests should be treated as cross origin

    + +
    + + + + + + +
    + + +
    +

    loaded

    + Boolean + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/JsonLoader.js:44 + +

    + + + + +
    + +
    +

    [read-only] Whether the data has loaded yet

    + +
    + + + + + + +
    + + +
    +

    url

    + String + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/JsonLoader.js:19 + +

    + + + + +
    + +
    +

    The url of the bitmap font data

    + +
    + + + + + + +
    + + +
    @@ -327,13 +853,13 @@ If load failed this class will dispatch a "error" event

    - + - - - - - - + + + + + + diff --git a/docs/classes/MovieClip.html b/docs/classes/MovieClip.html index ecfa688..90a28a9 100644 --- a/docs/classes/MovieClip.html +++ b/docs/classes/MovieClip.html @@ -3,11 +3,11 @@ MovieClip - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -154,7 +178,7 @@ @@ -171,6 +195,7 @@

    A MovieClip is a simple way to display an animation depicted by a list of textures.

    +
    @@ -218,7 +243,7 @@ - src/pixi/display/MovieClip.js:5 + src/pixi/display/MovieClip.js:5

    @@ -241,13 +266,14 @@
  • textures - Array + Array

    an array of {Texture} objects that make up the animation

    +
    @@ -364,6 +390,13 @@ +
  • + +
  • + onTextureUpdate + + +
  • @@ -380,11 +413,13 @@
  • -
  • +
  • setInteractive + deprecated +
  • @@ -401,7 +436,7 @@
  • -
  • +
  • swapChildren @@ -446,6 +481,27 @@ @@ -637,7 +749,7 @@
  • - DisplayObject + child
  • @@ -663,11 +775,11 @@

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:42 + src/pixi/display/DisplayObjectContainer.js:32

    @@ -679,6 +791,7 @@

    Adds a child to the container.

    +
    @@ -689,14 +802,15 @@
  • - DisplayObject + child DisplayObject
    - +

    The DisplayObject to add to the container

    +
    @@ -721,7 +835,7 @@
  • - DisplayObject + child
  • @@ -753,11 +867,11 @@

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:139 + src/pixi/display/DisplayObjectContainer.js:120

    @@ -769,6 +883,7 @@

    Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown

    +
    @@ -779,14 +894,15 @@
  • - DisplayObject + child DisplayObject
    - +

    The child to add

    +
    @@ -801,7 +917,8 @@
    - +

    The index to place the child in

    +
    @@ -852,11 +969,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:109 + src/pixi/display/DisplayObject.js:174

    @@ -868,6 +985,7 @@

    A callback that is used when the users clicks on the displayObject with their mouse

    +
    @@ -879,7 +997,7 @@
  • interactionData - InteractionData + InteractionData @@ -936,11 +1054,11 @@

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:274 + src/pixi/display/DisplayObjectContainer.js:256

    @@ -952,6 +1070,7 @@

    Returns the Child at the specified index

    +
    @@ -969,7 +1088,8 @@
    - +

    The index to get the child from

    +
    @@ -1027,7 +1147,7 @@ - src/pixi/display/MovieClip.js:94 + src/pixi/display/MovieClip.js:126

    @@ -1039,6 +1159,7 @@

    Goes to a specific frame and begins playing the MovieClip

    +
    @@ -1057,6 +1178,7 @@

    frame index to start at

    +
    @@ -1114,7 +1236,7 @@ - src/pixi/display/MovieClip.js:81 + src/pixi/display/MovieClip.js:112

    @@ -1126,6 +1248,7 @@

    Stops the MovieClip and goes to a specific frame

    +
    @@ -1144,6 +1267,7 @@

    frame index to stop at

    +
    @@ -1194,11 +1318,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:115 + src/pixi/display/DisplayObject.js:180

    @@ -1210,6 +1334,7 @@

    A callback that is used when the user clicks the mouse down over the sprite

    +
    @@ -1221,7 +1346,7 @@
  • interactionData - InteractionData + InteractionData @@ -1278,11 +1403,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:141 + src/pixi/display/DisplayObject.js:206

    @@ -1294,6 +1419,7 @@

    A callback that is used when the users mouse leaves the displayObject

    +
    @@ -1305,7 +1431,7 @@
  • interactionData - InteractionData + InteractionData @@ -1362,11 +1488,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:135 + src/pixi/display/DisplayObject.js:200

    @@ -1378,6 +1504,7 @@

    A callback that is used when the users mouse rolls over the displayObject

    +
    @@ -1389,7 +1516,7 @@
  • interactionData - InteractionData + InteractionData @@ -1446,11 +1573,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:121 + src/pixi/display/DisplayObject.js:186

    @@ -1463,6 +1590,7 @@

    A callback that is used when the user releases the mouse that was over the displayObject for this callback to be fired the mouse must have been pressed down over the displayObject

    +
    @@ -1474,7 +1602,7 @@ for this callback to be fired the mouse must have been pressed down over the dis
  • interactionData - InteractionData + InteractionData @@ -1531,11 +1659,11 @@ for this callback to be fired the mouse must have been pressed down over the dis

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:128 + src/pixi/display/DisplayObject.js:193

    @@ -1548,6 +1676,7 @@ for this callback to be fired the mouse must have been pressed down over the dis

    A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject for this callback to be fired, The touch must have started over the displayObject

    +
    @@ -1559,7 +1688,94 @@ for this callback to be fired, The touch must have started over the displayObjec
  • interactionData - InteractionData + InteractionData + + + + +
    + +
    + + +
  • + + +
    + + + + + +
    + + +
    +

    onTextureUpdate

    + + +
    + (
      + +
    • + + event + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + +

    Inherited from + Sprite: + + + + src/pixi/display/Sprite.js:145 + +

    + + + + + +
    + +
    +

    When the texture is updated, this event will fire to update the scale and frame

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + event + Object @@ -1613,7 +1829,7 @@ for this callback to be fired, The touch must have started over the displayObjec - src/pixi/display/MovieClip.js:72 + src/pixi/display/MovieClip.js:102

      @@ -1625,6 +1841,7 @@ for this callback to be fired, The touch must have started over the displayObjec

      Plays the MovieClip

      +
      @@ -1644,7 +1861,7 @@ for this callback to be fired, The touch must have started over the displayObjec
    • - DisplayObject + child
    • @@ -1670,11 +1887,11 @@ for this callback to be fired, The touch must have started over the displayObjec

      Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:291 + src/pixi/display/DisplayObjectContainer.js:274

      @@ -1686,6 +1903,7 @@ for this callback to be fired, The touch must have started over the displayObjec

      Removes a child from the container.

      +
      @@ -1696,14 +1914,15 @@ for this callback to be fired, The touch must have started over the displayObjec
    • - DisplayObject + child DisplayObject
      - +

      The DisplayObject to remove

      +
      @@ -1719,7 +1938,7 @@ for this callback to be fired, The touch must have started over the displayObjec
    -
    +

    setInteractive

    @@ -1739,6 +1958,8 @@ for this callback to be fired, The touch must have started over the displayObjec + deprecated + @@ -1754,16 +1975,18 @@ for this callback to be fired, The touch must have started over the displayObjec

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:193 + src/pixi/display/DisplayObject.js:247

    +

    Deprecated: Simply set the `interactive` property directly

    +
    @@ -1771,6 +1994,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default Instead of using this function you can now simply set the interactive property to true or false

    +
    @@ -1839,11 +2063,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - Sprite: + Sprite: - src/pixi/display/Sprite.js:103 + src/pixi/display/Sprite.js:118

    @@ -1854,7 +2078,8 @@ Instead of using this function you can now simply set the interactive property t
    - +

    Sets the texture of the sprite

    +
    @@ -1873,6 +2098,7 @@ Instead of using this function you can now simply set the interactive property t

    The PIXI texture that is displayed by the sprite

    +
    @@ -1920,7 +2146,7 @@ Instead of using this function you can now simply set the interactive property t - src/pixi/display/MovieClip.js:63 + src/pixi/display/MovieClip.js:92

    @@ -1932,6 +2158,7 @@ Instead of using this function you can now simply set the interactive property t

    Stops the MovieClip

    +
    @@ -1942,7 +2169,7 @@ Instead of using this function you can now simply set the interactive property t
    -
    +

    swapChildren

    @@ -1951,13 +2178,13 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child
  • - DisplayObject2 + child2
  • @@ -1970,6 +2197,8 @@ Instead of using this function you can now simply set the interactive property t + private + @@ -1983,11 +2212,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:227 + src/pixi/display/DisplayObjectContainer.js:207

    @@ -1998,7 +2227,8 @@ Instead of using this function you can now simply set the interactive property t
    -

    Swaps the depth of 2 displayObjects

    +

    [NYI] Swaps the depth of 2 displayObjects

    +
    @@ -2009,7 +2239,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child DisplayObject @@ -2024,7 +2254,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject2 + child2 DisplayObject @@ -2082,11 +2312,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:152 + src/pixi/display/DisplayObject.js:217

    @@ -2099,6 +2329,7 @@ Instead of using this function you can now simply set the interactive property t

    A callback that is used when the users taps on the sprite with their finger basically a touch version of click

    +
    @@ -2110,7 +2341,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -2167,11 +2398,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:165 + src/pixi/display/DisplayObject.js:230

    @@ -2183,6 +2414,7 @@ basically a touch version of click

    A callback that is used when the user releases a touch over the displayObject

    +
    @@ -2194,7 +2426,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -2251,11 +2483,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:171 + src/pixi/display/DisplayObject.js:236

    @@ -2268,6 +2500,7 @@ basically a touch version of click

    A callback that is used when the user releases the touch that was over the displayObject for this callback to be fired, The touch must have started over the sprite

    +
    @@ -2279,7 +2512,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -2336,11 +2569,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:159 + src/pixi/display/DisplayObject.js:224

    @@ -2351,7 +2584,8 @@ for this callback to be fired, The touch must have started over the sprite

  • -

    A callback that is used when the user touch's over the displayObject

    +

    A callback that is used when the user touch's over the displayObject

    +
    @@ -2363,7 +2597,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -2393,6 +2627,138 @@ for this callback to be fired, The touch must have started over the sprite

    Properties

    +
    +

    _height

    + Number + + + + + private + + + + + + +
    + + +

    Inherited from + Sprite: + + + + src/pixi/display/Sprite.js:60 + +

    + + + + +
    + +
    +

    The height of the sprite (this is initially set by the texture)

    + +
    + + + + + + +
    + + +
    +

    _interactive

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:115 + +

    + + + + +
    + +
    +

    [read-only] Whether or not the object is interactive, do not toggle directly! use the interactive property

    + +
    + + + + + + +
    + + +
    +

    _width

    + Number + + + + + private + + + + + + +
    + + +

    Inherited from + Sprite: + + + + src/pixi/display/Sprite.js:51 + +

    + + + + +
    + +
    +

    The width of the sprite (this is initially set by the texture)

    + +
    + + + + + + +
    + +

    alpha

    Number @@ -2409,11 +2775,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:43 + src/pixi/display/DisplayObject.js:47

    @@ -2424,6 +2790,7 @@ for this callback to be fired, The touch must have started over the sprite

    The opacity of the object.

    +
    @@ -2450,11 +2817,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - Sprite: + Sprite: - src/pixi/display/Sprite.js:21 + src/pixi/display/Sprite.js:23

    @@ -2468,6 +2835,7 @@ for this callback to be fired, The touch must have started over the sprite

    The default is 0,0 this means the textures origin is the top left Setting than anchor to 0.5,0.5 means the textures origin is centered Setting the anchor to 1,1 would mean the textures origin points will be the bottom right

    +
    @@ -2501,7 +2869,7 @@ Setting the anchor to 1,1 would mean the textures origin points will be the bott - src/pixi/display/MovieClip.js:30 + src/pixi/display/MovieClip.js:25

    @@ -2512,9 +2880,12 @@ Setting the anchor to 1,1 would mean the textures origin points will be the bott

    The speed that the MovieClip will play at. Higher is faster, lower is slower

    +
    +

    Default: 1

    + @@ -2524,7 +2895,7 @@ Setting the anchor to 1,1 would mean the textures origin points will be the bott

    blendMode

    - Uint + Number @@ -2538,11 +2909,11 @@ Setting the anchor to 1,1 would mean the textures origin points will be the bott

    Inherited from - Sprite: + Sprite: - src/pixi/display/Sprite.js:38 + src/pixi/display/Sprite.js:42

    @@ -2554,6 +2925,7 @@ Setting the anchor to 1,1 would mean the textures origin points will be the bott

    The blend mode of sprite. currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    +
    @@ -2580,11 +2952,11 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:98 + src/pixi/display/DisplayObject.js:72

    @@ -2595,6 +2967,7 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    This is used to indicate if the displayObject should display a mouse hand cursor on rollover

    +
    @@ -2607,7 +2980,7 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    children

    - Array + Array @@ -2621,11 +2994,11 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:16 + src/pixi/display/DisplayObjectContainer.js:18

    @@ -2636,6 +3009,51 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    [read-only] The of children of this container.

    + +
    + + + + + + +
    + + +
    +

    color

    + Array<> + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:145 + +

    + + + + +
    + +
    +

    [NYI] Unkown

    +
    @@ -2669,7 +3087,7 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    - src/pixi/display/MovieClip.js:23 + src/pixi/display/MovieClip.js:51

    @@ -2679,7 +3097,98 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    -

    [read only] The index MovieClips current frame (this may not have to be a whole number)

    +

    [read-only] The index MovieClips current frame (this may not have to be a whole number)

    + +
    + + +

    Default: 0

    + + + + + +
    + + +
    +

    dynamic

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:154 + +

    + + + + +
    + +
    +

    [NYI] Holds whether or not this object is dynamic, for rendering optimization

    + +
    + + + + + + +
    + + +
    +

    filters

    + Array An array of filters + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:318 + +

    + + + + +
    + +
    +

    Sets the filters for the displayObject. +* IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer. +To remove filters simply set this property to 'null'

    +
    @@ -2692,7 +3201,7 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    height

    - #Number + Number @@ -2706,11 +3215,11 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    Inherited from - Sprite: + Sprite: - src/pixi/display/Sprite.js:53 + src/pixi/display/Sprite.js:102

    @@ -2720,7 +3229,8 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    -

    The height of the sprite (this is initially set by the texture)

    +

    The height of the sprite, setting this will actually modify the scale to acheive the value set

    +
    @@ -2733,7 +3243,7 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    hitArea

    - Rectangle + Rectangle | Circle | Ellipse | Polygon @@ -2747,11 +3257,11 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:72 + src/pixi/display/DisplayObject.js:63

    @@ -2763,6 +3273,7 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    This is the defined area that will pick up mouse / touch events. It is null by default. Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children)

    +
    @@ -2789,11 +3300,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:204 + src/pixi/display/DisplayObject.js:260

    @@ -2804,6 +3315,53 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Indicates if the sprite will have touch and mouse interactivity. It is false by default

    + +
    + + +

    Default: false

    + + + + + +
    + + +
    +

    localTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:135 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object locally

    +
    @@ -2837,7 +3395,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction - src/pixi/display/MovieClip.js:37 + src/pixi/display/MovieClip.js:34

    @@ -2848,9 +3406,12 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Whether or not the movie clip repeats after playing.

    +
    +

    Default: true

    + @@ -2860,7 +3421,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    mask

    - PIXI.Graphics + Graphics @@ -2874,11 +3435,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:222 + src/pixi/display/DisplayObject.js:280

    @@ -2891,6 +3452,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. To remove a mask, set this property to null.

    +
    @@ -2924,7 +3486,7 @@ To remove a mask, set this property to null.

    - src/pixi/display/MovieClip.js:44 + src/pixi/display/MovieClip.js:43

    @@ -2935,6 +3497,7 @@ To remove a mask, set this property to null.

    Function to call when a MovieClip finishes playing

    +
    @@ -2961,11 +3524,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:58 + src/pixi/display/DisplayObject.js:88

    @@ -2976,6 +3539,7 @@ To remove a mask, set this property to null.

    [read-only] The display object container that contains this display object.

    +
    @@ -3002,11 +3566,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:29 + src/pixi/display/DisplayObject.js:31

    @@ -3017,6 +3581,7 @@ To remove a mask, set this property to null.

    The pivot point of the displayObject that it rotates around

    +
    @@ -3050,7 +3615,7 @@ To remove a mask, set this property to null.

    - src/pixi/display/MovieClip.js:51 + src/pixi/display/MovieClip.js:61

    @@ -3060,7 +3625,8 @@ To remove a mask, set this property to null.

    -

    [read only] indicates if the MovieClip is currently playing

    +

    [read-only] Indicates if the MovieClip is currently playing

    +
    @@ -3087,11 +3653,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:15 + src/pixi/display/DisplayObject.js:15

    @@ -3102,6 +3668,49 @@ To remove a mask, set this property to null.

    The coordinate of the object relative to the local coordinates of the parent.

    + +
    + + + + + + +
    + + +
    +

    renderable

    + Boolean + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:80 + +

    + + + + +
    + +
    +

    Can this object be rendered

    +
    @@ -3128,11 +3737,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:36 + src/pixi/display/DisplayObject.js:39

    @@ -3143,6 +3752,7 @@ To remove a mask, set this property to null.

    The rotation of the object in radians.

    +
    @@ -3169,11 +3779,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:22 + src/pixi/display/DisplayObject.js:23

    @@ -3184,6 +3794,7 @@ To remove a mask, set this property to null.

    The scale factor of the object.

    +
    @@ -3210,11 +3821,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:65 + src/pixi/display/DisplayObject.js:97

    @@ -3225,6 +3836,7 @@ To remove a mask, set this property to null.

    [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage.

    +
    @@ -3251,11 +3863,11 @@ To remove a mask, set this property to null.

    Inherited from - Sprite: + Sprite: - src/pixi/display/Sprite.js:31 + src/pixi/display/Sprite.js:34

    @@ -3266,6 +3878,7 @@ To remove a mask, set this property to null.

    The texture that the sprite is using

    +
    @@ -3299,7 +3912,7 @@ To remove a mask, set this property to null.

    - src/pixi/display/MovieClip.js:16 + src/pixi/display/MovieClip.js:17

    @@ -3310,6 +3923,7 @@ To remove a mask, set this property to null.

    The array of textures that make up the animation

    +
    @@ -3317,6 +3931,54 @@ To remove a mask, set this property to null.

    +
    + + +
    +

    totalFrames

    + Number + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/display/MovieClip.js:75 + +

    + + + + +
    + +
    +

    [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures +assigned to the MovieClip.

    + +
    + + +

    Default: 0

    + + + + +
    @@ -3336,11 +3998,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:50 + src/pixi/display/DisplayObject.js:55

    @@ -3351,6 +4013,7 @@ To remove a mask, set this property to null.

    The visibility of the object.

    +
    @@ -3363,7 +4026,7 @@ To remove a mask, set this property to null.

    width

    - #Number + Number @@ -3377,11 +4040,11 @@ To remove a mask, set this property to null.

    Inherited from - Sprite: + Sprite: - src/pixi/display/Sprite.js:46 + src/pixi/display/Sprite.js:86

    @@ -3391,7 +4054,94 @@ To remove a mask, set this property to null.

    -

    The width of the sprite (this is initially set by the texture)

    +

    The width of the sprite, setting this will actually modify the scale to acheive the value set

    + +
    + + + + + + + + + +
    +

    worldAlpha

    + Number + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:106 + +

    + + + + +
    + +
    +

    [read-only] The multiplied alpha of the displayobject

    + +
    + + + + + + +
    + + +
    +

    worldTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:125 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object based on world (parent) factors

    +
    @@ -3417,13 +4167,13 @@ To remove a mask, set this property to null.

    - + - - - - - - + + + + + + diff --git a/docs/classes/PixelateFilter.html b/docs/classes/PixelateFilter.html new file mode 100644 index 0000000..ba0d21d --- /dev/null +++ b/docs/classes/PixelateFilter.html @@ -0,0 +1,315 @@ + + + + + PixelateFilter - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    PixelateFilter Class

    +
    + + + + + + + + + + + Module: PIXI + + + + +
    + + + +
    +

    This filter applies a pixlate effect making display objects appear "blocky"

    + +
    + + + +
    + + +
    +
    +

    Item Index

    + + + + +
    +

    Properties

    + +
      + +
    • + size + + + +
    • + +
    +
    + + + + + +
    + + + + +
    +

    Properties

    + + +
    +

    size

    + Point + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/filters/PixelateFilter.js:50 + +

    + + + + +
    + +
    +

    This a point that describes the size of the blocs. x is the width of the block and y is the the height

    + +
    + + + + + + +
    + + +
    + + + + + +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/classes/Point.html b/docs/classes/Point.html index 9cc03ce..21f7d7a 100644 --- a/docs/classes/Point.html +++ b/docs/classes/Point.html @@ -3,11 +3,11 @@ Point - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -150,7 +174,7 @@ @@ -167,6 +191,7 @@

    The Point object represents a location in a two-dimensional coordinate system, where x represents the horizontal axis and y represents the vertical axis.

    +
    @@ -220,7 +245,7 @@ - src/pixi/core/Point.js:5 + src/pixi/core/Point.js:5

    @@ -250,6 +275,7 @@

    position of the point

    +
    @@ -265,6 +291,7 @@

    position of the point

    +
    @@ -360,7 +387,7 @@ - + Point @@ -387,7 +414,7 @@ - src/pixi/core/Point.js:29 + src/pixi/core/Point.js:30

    @@ -398,7 +425,8 @@
    - +

    Creates a clone of this point

    +
    @@ -410,7 +438,10 @@
    - a copy of the point + Point: + +

    a copy of the point

    +
    @@ -451,7 +482,7 @@ - src/pixi/core/Point.js:14 + src/pixi/core/Point.js:15

    @@ -497,7 +528,7 @@ - src/pixi/core/Point.js:21 + src/pixi/core/Point.js:22

    @@ -535,13 +566,13 @@ - + - - - - - - + + + + + + diff --git a/docs/classes/PolyK.AjaxRequest.html b/docs/classes/PolyK.AjaxRequest.html new file mode 100644 index 0000000..508d79f --- /dev/null +++ b/docs/classes/PolyK.AjaxRequest.html @@ -0,0 +1,601 @@ + + + + + PolyK.AjaxRequest - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    PolyK.AjaxRequest Class

    +
    + + + + + +
    + Defined in: src/pixi/utils/Utils.js:81 +
    + + + + + Module: PIXI + + + + +
    + + + +
    +

    A wrapper for ajax requests to be handled cross browser

    + +
    + + +
    +

    Constructor

    +
    +

    PolyK.AjaxRequest

    + + + () + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/utils/Utils.js:81 + +

    + + + + + +
    + +
    + +
    + + + + + + +
    + +
    + + +
    + + +
    +
    +

    Item Index

    + + +
    +

    Methods

    + + +
    + + + + + + + +
    + + +
    +

    Methods

    + + +
    +

    bind

    + + + () + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/utils/Utils.js:53 + +

    + + + + + +
    + +
    +

    A polyfill for Function.prototype.bind

    + +
    + + + + + + +
    + + +
    +

    cancelAnimationFrame

    + + + () + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/utils/Utils.js:13 + +

    + + + + + +
    + +
    +

    A polyfill for cancelAnimationFrame

    + +
    + + + + + + +
    + + +
    +

    HEXtoRGB

    + + +
    + (
      + +
    • + + hex + +
    • + +
    ) +
    + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/utils/Utils.js:43 + +

    + + + + + +
    + +
    +

    Converts a hex color number to an [R, G, B] array

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + hex + Number + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    requestAnimationFrame

    + + + () + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/utils/Utils.js:8 + +

    + + + + + +
    + +
    +

    A polyfill for requestAnimationFrame

    + +
    + + + + + + +
    + + +
    + + + + + + + +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/classes/InteractionData.html b/docs/classes/PolyK.InteractionData.html similarity index 62% rename from docs/classes/InteractionData.html rename to docs/classes/PolyK.InteractionData.html index 56f1b0d..2555156 100644 --- a/docs/classes/InteractionData.html +++ b/docs/classes/PolyK.InteractionData.html @@ -2,12 +2,12 @@ - InteractionData - Pixi.JS - - - - - + PolyK.InteractionData - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,7 +166,7 @@
    -

    InteractionData Class

    +

    PolyK.InteractionData Class

    @@ -150,7 +174,7 @@ @@ -166,14 +190,15 @@
    - +

    Holds all information related to an Interaction event

    +

    Constructor

    -
    -

    InteractionData

    +
    +

    PolyK.InteractionData

    () @@ -204,7 +229,7 @@ - src/pixi/InteractionManager.js:493 + src/pixi/InteractionManager.js:646

    @@ -350,7 +375,7 @@ - src/pixi/InteractionManager.js:524 + src/pixi/InteractionManager.js:682

    @@ -362,6 +387,7 @@

    This will return the local coords of the specified displayObject for this InteractionData

    +
    @@ -380,6 +406,7 @@

    The DisplayObject that you would like the local coords off

    +
    @@ -398,7 +425,8 @@ Point: - A point containing the coords of the InteractionData position relative to the DisplayObject +

    A point containing the coords of the InteractionData position relative to the DisplayObject

    +
    @@ -439,7 +467,7 @@ - src/pixi/InteractionManager.js:499 + src/pixi/InteractionManager.js:654

    @@ -450,6 +478,7 @@

    This point stores the global coords of where the touch/mouse event happened

    +
    @@ -483,7 +512,7 @@ - src/pixi/InteractionManager.js:516 + src/pixi/InteractionManager.js:673

    @@ -494,6 +523,7 @@

    When passed to an event handler, this will be the original DOM Event that was captured

    +
    @@ -527,7 +557,7 @@ - src/pixi/InteractionManager.js:509 + src/pixi/InteractionManager.js:665

    @@ -538,6 +568,7 @@

    The target Sprite that was interacted with

    +
    @@ -563,13 +594,13 @@
    - + - - - - - - + + + + + + diff --git a/docs/classes/PolyK.InteractionManager.html b/docs/classes/PolyK.InteractionManager.html new file mode 100644 index 0000000..d24b54e --- /dev/null +++ b/docs/classes/PolyK.InteractionManager.html @@ -0,0 +1,1616 @@ + + + + + PolyK.InteractionManager - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    PolyK.InteractionManager Class

    +
    + + + + + + + + + + + Module: PIXI + + + + +
    + + + +
    +

    The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive +This manager also supports multitouch.

    + +
    + + +
    +

    Constructor

    +
    +

    PolyK.InteractionManager

    + + +
    + (
      + +
    • + + stage + +
    • + +
    ) +
    + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/InteractionManager.js:5 + +

    + + + + + +
    + +
    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + stage + Stage + + + + +
      +

      The stage to handle interactions

      + +
      + + +
    • + +
    +
    + + + + + +
    + +
    + + +
    + + +
    +
    +

    Item Index

    + + +
    +

    Methods

    + + +
    + + + +
    +

    Properties

    + + +
    + + + + + +
    + + +
    +

    Methods

    + + +
    +

    collectInteractiveSprite

    + + +
    + (
      + +
    • + + displayObject + +
    • + +
    • + + iParent + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/InteractionManager.js:70 + +

    + + + + + +
    + +
    +

    Collects an interactive sprite recursively to have their interactions managed

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + displayObject + DisplayObject + + + + +
      +

      the displayObject to collect

      + +
      + + +
    • + +
    • + + iParent + DisplayObject + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    hitTest

    + + +
    + (
      + +
    • + + item + +
    • + +
    • + + interactionData + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/InteractionManager.js:422 + +

    + + + + + +
    + +
    +

    Tests if the current mouse coords hit a sprite

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + item + DisplayObject + + + + +
      +

      The displayObject to test for a hit

      + +
      + + +
    • + +
    • + + interactionData + InteractionData + + + + +
      +

      The interactiondata object to update in the case of a hit

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    onMouseDown

    + + +
    + (
      + +
    • + + event + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/InteractionManager.js:305 + +

    + + + + + +
    + +
    +

    Is called when the mouse button is pressed down on the renderer element

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + event + Event + + + + +
      +

      The DOM event of a mouse button being pressed down

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    onMouseMove

    + + +
    + (
      + +
    • + + event + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/InteractionManager.js:273 + +

    + + + + + +
    + +
    +

    Is called when the mouse moves accross the renderer element

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + event + Event + + + + +
      +

      The DOM event of the mouse moving

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    onMouseUp

    + + +
    + (
      + +
    • + + event + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/InteractionManager.js:370 + +

    + + + + + +
    + +
    +

    Is called when the mouse button is released on the renderer element

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + event + Event + + + + +
      +

      The DOM event of a mouse button being released

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    onTouchEnd

    + + +
    + (
      + +
    • + + event + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/InteractionManager.js:575 + +

    + + + + + +
    + +
    +

    Is called when a touch is ended on the renderer element

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + event + Event + + + + +
      +

      The DOM event of a touch ending on the renderer view

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    onTouchMove

    + + +
    + (
      + +
    • + + event + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/InteractionManager.js:495 + +

    + + + + + +
    + +
    +

    Is called when a touch is moved accross the renderer element

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + event + Event + + + + +
      +

      The DOM event of a touch moving accross the renderer view

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    onTouchStart

    + + +
    + (
      + +
    • + + event + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/InteractionManager.js:526 + +

    + + + + + +
    + +
    +

    Is called when a touch is started on the renderer element

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + event + Event + + + + +
      +

      The DOM event of a touch starting on the renderer view

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    setTarget

    + + +
    + (
      + +
    • + + target + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/InteractionManager.js:114 + +

    + + + + + +
    + +
    +

    Sets the target for event delegation

    + +
    + + +
    +

    Parameters:

    + + +
    + + + + + +
    + + +
    +

    setTargetDomElement

    + + +
    + (
      + +
    • + + domElement + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/InteractionManager.js:135 + +

    + + + + + +
    + +
    +

    Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM +elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element +to receive those events

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + domElement + DOMElement + + + + +
      +

      the dom element which will receive mouse and touch events

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    update

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/InteractionManager.js:185 + +

    + + + + + +
    + +
    +

    updates the state of interactive objects

    + +
    + + + + + + +
    + + +
    + + + +
    +

    Properties

    + + +
    +

    mouse

    + InteractionData + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/InteractionManager.js:23 + +

    + + + + +
    + +
    +

    the mouse data

    + +
    + + + + + + +
    + + +
    +

    stage

    + Stage + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/InteractionManager.js:15 + +

    + + + + +
    + +
    +

    a refference to the stage

    + +
    + + + + + + +
    + + +
    +

    touchs

    + Object + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/InteractionManager.js:31 + +

    + + + + +
    + +
    +

    an object that stores current touches (InteractionData) by id reference

    + +
    + + + + + + +
    + + +
    + + + + + +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/classes/PolyK._PointInTriangle.html b/docs/classes/PolyK._PointInTriangle.html new file mode 100644 index 0000000..3ea0a55 --- /dev/null +++ b/docs/classes/PolyK._PointInTriangle.html @@ -0,0 +1,325 @@ + + + + + PolyK._PointInTriangle - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    PolyK._PointInTriangle Class

    +
    + + + + + +
    + Defined in: src/pixi/utils/Polyk.js:109 +
    + + + + + Module: PIXI + + + + +
    + + + +
    +

    Checks if a point is within a triangle

    + +
    + + + +
    + + +
    +
    +

    Item Index

    + + +
    +

    Methods

    + + +
    + + + + + + + +
    + + +
    +

    Methods

    + + +
    +

    Triangulate

    + + + () + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/utils/Polyk.js:36 + +

    + + + + + +
    + +
    +

    Triangulates shapes for webGL graphic fills

    + +
    + + + + + + +
    + + +
    + + + + + + + +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/classes/PolyK._convex.html b/docs/classes/PolyK._convex.html new file mode 100644 index 0000000..4a91a69 --- /dev/null +++ b/docs/classes/PolyK._convex.html @@ -0,0 +1,247 @@ + + + + + PolyK._convex - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    PolyK._convex Class

    +
    + + + + + +
    + Defined in: src/pixi/utils/Polyk.js:139 +
    + + + + + Module: PIXI + + + + +
    + + + +
    +

    Checks if a shape is convex

    + +
    + + + +
    + + +
    +
    +

    Item Index

    + + + + + + + + +
    + + + + + + + + +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/classes/Polygon.html b/docs/classes/Polygon.html index 587eb48..6dcfee8 100644 --- a/docs/classes/Polygon.html +++ b/docs/classes/Polygon.html @@ -3,11 +3,11 @@ Polygon - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
  • points - Array | Array + Array | Array | Point... | Number... + multiple +
    -

    This cna be an array of Points or a flat array of numbers - that will be interpreted as [x,y, x,y, ...]

    +

    This can be an array of Points that form the polygon, + a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be + all the points of the polygon e.g. new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...), or the + arguments passed can be flat x,y values e.g. new PIXI.Polygon(x,y, x,y, x,y, ...) where x and y are + Numbers.

    +
    @@ -323,7 +353,7 @@ - + Polygon @@ -350,7 +380,7 @@ - src/pixi/core/Polygon.js:28 + src/pixi/core/Polygon.js:35

    @@ -361,7 +391,8 @@
    - +

    Creates a clone of this polygon

    +
    @@ -373,7 +404,10 @@
    - a copy of the polygon + Polygon: + +

    a copy of the polygon

    +
    @@ -408,7 +442,7 @@ - + Boolean @@ -435,7 +469,7 @@ - src/pixi/core/Polygon.js:42 + src/pixi/core/Polygon.js:51

    @@ -446,7 +480,8 @@
    - +

    Checks if the x, and y coords passed to this function are contained within this polygon

    +
    @@ -465,6 +500,7 @@

    The X coord of the point to test

    +
    @@ -480,6 +516,7 @@

    The Y coord of the point to test

    +
    @@ -496,7 +533,10 @@
    - if the x/y coords are within this polygon + Boolean: + +

    if the x/y coords are within this polygon

    +
    @@ -523,13 +563,13 @@ - + - - - - - - + + + + + + diff --git a/docs/classes/Rectangle.html b/docs/classes/Rectangle.html index bbf3d67..142297c 100644 --- a/docs/classes/Rectangle.html +++ b/docs/classes/Rectangle.html @@ -3,11 +3,11 @@ Rectangle - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -150,7 +174,7 @@ @@ -167,6 +191,7 @@

    the Rectangle object is an area defined by its position, as indicated by its top-left corner point (x, y) and by its width and its height.

    +
    @@ -232,7 +257,7 @@ - src/pixi/core/Rectangle.js:5 + src/pixi/core/Rectangle.js:5

    @@ -261,7 +286,8 @@
    -

    position of the rectangle

    +

    The X coord of the upper-left corner of the rectangle

    +
    @@ -276,7 +302,8 @@
    -

    position of the rectangle

    +

    The Y coord of the upper-left corner of the rectangle

    +
    @@ -291,7 +318,8 @@
    -

    of the rectangle

    +

    The overall width of this rectangle

    +
    @@ -306,7 +334,8 @@
    -

    of the rectangle

    +

    The overall height of this rectangle

    +
    @@ -423,7 +452,7 @@ - + Rectangle @@ -450,7 +479,7 @@ - src/pixi/core/Rectangle.js:45 + src/pixi/core/Rectangle.js:46

    @@ -461,7 +490,8 @@
    - +

    Creates a clone of this Rectangle

    +
    @@ -473,7 +503,10 @@
    - a copy of the rectangle + Rectangle: + +

    a copy of the rectangle

    +
    @@ -508,7 +541,7 @@ - + Boolean @@ -535,7 +568,7 @@ - src/pixi/core/Rectangle.js:54 + src/pixi/core/Rectangle.js:57

    @@ -546,7 +579,8 @@
    - +

    Checks if the x, and y coords passed to this function are contained within this Rectangle

    +
    @@ -565,6 +599,7 @@

    The X coord of the point to test

    +
    @@ -580,6 +615,7 @@

    The Y coord of the point to test

    +
    @@ -596,7 +632,10 @@
    - if the x/y coords are within this polygon + Boolean: + +

    if the x/y coords are within this Rectangle

    +
    @@ -637,7 +676,7 @@ - src/pixi/core/Rectangle.js:37 + src/pixi/core/Rectangle.js:38

    @@ -683,7 +722,7 @@ - src/pixi/core/Rectangle.js:30 + src/pixi/core/Rectangle.js:31

    @@ -729,7 +768,7 @@ - src/pixi/core/Rectangle.js:16 + src/pixi/core/Rectangle.js:17

    @@ -775,7 +814,7 @@ - src/pixi/core/Rectangle.js:23 + src/pixi/core/Rectangle.js:24

    @@ -813,13 +852,13 @@ - + - - - - - - + + + + + + diff --git a/docs/classes/RenderTexture.html b/docs/classes/RenderTexture.html index e274141..3e617dc 100644 --- a/docs/classes/RenderTexture.html +++ b/docs/classes/RenderTexture.html @@ -3,11 +3,11 @@ RenderTexture - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -154,7 +178,7 @@ @@ -171,27 +195,21 @@

    A RenderTexture is a special texture that allows any pixi displayObject to be rendered to it.

    -

    Hint: All DisplayObjects (exmpl. Sprites) that renders on RenderTexture should be preloaded. Otherwise black rectangles will be drawn instead.

    -

    RenderTexture takes snapshot of DisplayObject passed to render method. If DisplayObject is passed to render method, position and rotation of it will be ignored. For example:

    -
    var renderTexture = new PIXI.RenderTexture(800, 600);
    -var sprite = PIXI.Sprite.fromImage("spinObj_01.png");
    +var sprite = PIXI.Sprite.fromImage("spinObj_01.png");
     sprite.position.x = 800/2;
     sprite.position.y = 600/2;
     sprite.anchor.x = 0.5;
     sprite.anchor.y = 0.5;
    -renderTexture.render(sprite);
    -
    - +renderTexture.render(sprite);

    Sprite in this case will be rendered to 0,0 position. To render this sprite at center DisplayObjectContainer should be used:

    -
    var doc = new PIXI.DisplayObjectContainer();
     doc.addChild(sprite);
    -renderTexture.render(doc);  // Renders to center of renderTexture
    -
    +renderTexture.render(doc); // Renders to center of renderTexture +
    @@ -245,7 +263,7 @@ renderTexture.render(doc); // Renders to center of renderTexture - src/pixi/textures/RenderTexture.js:5 + src/pixi/textures/RenderTexture.js:5

    @@ -274,7 +292,8 @@ renderTexture.render(doc); // Renders to center of renderTexture
    - +

    The width of the render texture

    +
    @@ -289,7 +308,8 @@ renderTexture.render(doc); // Renders to center of renderTexture
    - +

    The height of the render texture

    +
    @@ -332,14 +352,42 @@ renderTexture.render(doc); // Renders to center of renderTexture @@ -390,8 +445,8 @@ renderTexture.render(doc); // Renders to center of renderTexture

    Methods

    -
    -

    fromFrame

    +
    +

    destroy

    @@ -399,7 +454,7 @@ renderTexture.render(doc); // Renders to center of renderTexture
  • - frameId + destroyBase
  • @@ -408,10 +463,6 @@ renderTexture.render(doc); // Renders to center of renderTexture - - - - @@ -429,11 +480,11 @@ renderTexture.render(doc); // Renders to center of renderTexture

    Inherited from - Texture: + Texture: - src/pixi/textures/Texture.js:127 + src/pixi/textures/Texture.js:93

    @@ -444,8 +495,8 @@ renderTexture.render(doc); // Renders to center of renderTexture
    -

    Helper function that returns a texture based on a frame id - If the frame id is not in the texture cache an error will be thrown

    +

    Destroys this texture

    +
    @@ -456,14 +507,15 @@ renderTexture.render(doc); // Renders to center of renderTexture
  • - frameId - String + destroyBase + Boolean
    -

    The frame id of the texture

    +

    Whether to destroy the base texture as well

    +
    @@ -474,24 +526,214 @@ renderTexture.render(doc); // Renders to center of renderTexture -
    -

    Returns:

    -
    + +
    + - - Texture +
    +

    initCanvas

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + -
    -
    +

    + + Defined in + + + + + src/pixi/textures/RenderTexture.js:125 + +

    + + + + + +
    + +
    +

    Initializes the canvas data for this texture

    + +
    + + + -
    -

    render

    +
    +

    initWebGL

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/textures/RenderTexture.js:57 + +

    + + + + + +
    + +
    +

    Initializes the webgl data for this texture

    + +
    + + + + + + +
    + + +
    +

    onBaseTextureLoaded

    + + +
    + (
      + +
    • + + event + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + +

    Inherited from + Texture: + + + + src/pixi/textures/Texture.js:73 + +

    + + + + + +
    + +
    +

    Called when the base texture is loaded

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + event + Object + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    renderCanvas

    @@ -518,6 +760,8 @@ renderTexture.render(doc); // Renders to center of renderTexture + private + @@ -538,7 +782,7 @@ renderTexture.render(doc); // Renders to center of renderTexture - src/pixi/textures/RenderTexture.js:112 + src/pixi/textures/RenderTexture.js:214

    @@ -550,6 +794,7 @@ renderTexture.render(doc); // Renders to center of renderTexture

    This function will draw the display object to the texture.

    +
    @@ -567,7 +812,8 @@ renderTexture.render(doc); // Renders to center of renderTexture
    - +

    The display object to render this texture on

    +
    @@ -583,6 +829,120 @@ renderTexture.render(doc); // Renders to center of renderTexture

    If true the texture will be cleared before the displayObject is drawn

    + +
    + + +
  • + + + + + + + + + + + +
    +

    renderWebGL

    + + +
    + (
      + +
    • + + displayObject + +
    • + +
    • + + clear + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/textures/RenderTexture.js:141 + +

    + + + + + +
    + +
    +

    This function will draw the display object to the texture.

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + displayObject + DisplayObject + + + + +
      +

      The display object to render this texture on

      + +
      + + +
    • + +
    • + + clear + Boolean + + + + +
      +

      If true the texture will be cleared before the displayObject is drawn

      +
      @@ -633,11 +993,11 @@ renderTexture.render(doc); // Renders to center of renderTexture

      Inherited from - Texture: + Texture: - src/pixi/textures/Texture.js:83 + src/pixi/textures/Texture.js:104

      @@ -649,6 +1009,7 @@ renderTexture.render(doc); // Renders to center of renderTexture

      Specifies the rectangle region of the baseTexture

      +
      @@ -666,7 +1027,8 @@ renderTexture.render(doc); // Renders to center of renderTexture
      - +

      The frame of the texture to set it to

      +
      @@ -706,11 +1068,11 @@ renderTexture.render(doc); // Renders to center of renderTexture

      Inherited from - Texture: + Texture: - src/pixi/textures/Texture.js:31 + src/pixi/textures/Texture.js:31

      @@ -721,6 +1083,7 @@ renderTexture.render(doc); // Renders to center of renderTexture

      The base texture of this texture

      +
      @@ -733,7 +1096,7 @@ renderTexture.render(doc); // Renders to center of renderTexture

      frame

      - #Rectangle + Rectangle @@ -747,11 +1110,11 @@ renderTexture.render(doc); // Renders to center of renderTexture

      Inherited from - Texture: + Texture: - src/pixi/textures/Texture.js:40 + src/pixi/textures/Texture.js:39

      @@ -762,6 +1125,49 @@ renderTexture.render(doc); // Renders to center of renderTexture

      The frame specifies the region of the base texture that this texture uses

      + +
      + + + + + + +
      + + +
      +

      trim

      + Point + + + + + + + + + +
      + + +

      Inherited from + Texture: + + + + src/pixi/textures/Texture.js:47 + +

      + + + + +
      + +
      +

      The trim point

      +
      @@ -787,13 +1193,13 @@ renderTexture.render(doc); // Renders to center of renderTexture
    - + - - - - - - + + + + + + diff --git a/docs/classes/SepiaFilter.html b/docs/classes/SepiaFilter.html new file mode 100644 index 0000000..7911051 --- /dev/null +++ b/docs/classes/SepiaFilter.html @@ -0,0 +1,315 @@ + + + + + SepiaFilter - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    SepiaFilter Class

    +
    + + + + + + + + + + + Module: PIXI + + + + +
    + + + +
    +

    This applies a sepia effect to your displayObjects.

    + +
    + + + +
    + + +
    +
    +

    Item Index

    + + + + +
    +

    Properties

    + +
      + +
    • + sepia + + + +
    • + +
    +
    + + + + + +
    + + + + +
    +

    Properties

    + + +
    +

    sepia

    + Unknown + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/filters/SepiaFilter.js:44 + +

    + + + + +
    + +
    +

    The strength of the sepia. 1 will apply the full sepia effect, 0 will make the object its normal color

    + +
    + + + + + + +
    + + +
    + + + + + +
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/classes/Spine.html b/docs/classes/Spine.html index 07fba75..2152e64 100644 --- a/docs/classes/Spine.html +++ b/docs/classes/Spine.html @@ -3,11 +3,11 @@ Spine - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -145,6 +169,15 @@

    Spine Class

    +
    + Uses + +
    +
    @@ -154,7 +187,7 @@ @@ -171,11 +204,12 @@

    The Spine loader is used to load in JSON spine data -To generate the data you need to use http://esotericsoftware.com/ and export the "JSON" format -Due to a clash of names You will need to change the extension of the spine file from *.json to *.anim for it to load -See example 12 (http://www.goodboydigital.com/pixijs/examples/12/) to see a working example and check out the source -You will need to generate a sprite sheet to accompany the spine data -When loaded this class will dispatch a "loaded" event

    +To generate the data you need to use http://esotericsoftware.com/ and export the "JSON" format +Due to a clash of names You will need to change the extension of the spine file from .json to .anim for it to load +See example 12 (http://www.goodboydigital.com/pixijs/examples/12/) to see a working example and check out the source +You will need to generate a sprite sheet to accompany the spine data +When loaded this class will dispatch a "loaded" event

    +
    @@ -223,7 +257,7 @@ When loaded this class will dispatch a "loaded" event

    - src/pixi/loaders/SpineLoader.js:10 + src/pixi/loaders/SpineLoader.js:10

    @@ -252,7 +286,8 @@ When loaded this class will dispatch a "loaded" event

    -

    the url of the spine anim file to be used

    +

    The url of the spine anim file to be used

    +
    @@ -320,6 +355,13 @@ When loaded this class will dispatch a "loaded" event

    + + +
  • + load + + +
  • @@ -355,6 +397,20 @@ When loaded this class will dispatch a "loaded" event

    +
  • + +
  • + onJSONLoaded + + + +
  • + +
  • + onLoaded + + +
  • @@ -364,14 +420,16 @@ When loaded this class will dispatch a "loaded" event

  • -
  • +
  • setInteractive + deprecated +
  • -
  • +
  • swapChildren @@ -416,6 +474,13 @@ When loaded this class will dispatch a "loaded" event

      +
    • + _interactive + + + +
    • +
    • alpha @@ -435,6 +500,34 @@ When loaded this class will dispatch a "loaded" event

      +
    • + +
    • + color + + + +
    • + +
    • + crossorigin + + + +
    • + +
    • + dynamic + + + +
    • + +
    • + filters + + +
    • @@ -449,6 +542,20 @@ When loaded this class will dispatch a "loaded" event

      +
    • + +
    • + loaded + + + +
    • + +
    • + localTransform + + +
    • @@ -477,6 +584,13 @@ When loaded this class will dispatch a "loaded" event

      +
    • + +
    • + renderable + + +
    • @@ -498,6 +612,13 @@ When loaded this class will dispatch a "loaded" event

      +
    • + +
    • + url + + +
    • @@ -505,6 +626,20 @@ When loaded this class will dispatch a "loaded" event

      +
    • + +
    • + worldAlpha + + + +
    • + +
    • + worldTransform + + +
    @@ -530,7 +665,7 @@ When loaded this class will dispatch a "loaded" event

  • - DisplayObject + child
  • @@ -556,11 +691,11 @@ When loaded this class will dispatch a "loaded" event

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:42 + src/pixi/display/DisplayObjectContainer.js:32

    @@ -572,6 +707,7 @@ When loaded this class will dispatch a "loaded" event

    Adds a child to the container.

    +
    @@ -582,14 +718,15 @@ When loaded this class will dispatch a "loaded" event

  • - DisplayObject + child DisplayObject
    - +

    The DisplayObject to add to the container

    +
    @@ -614,7 +751,7 @@ When loaded this class will dispatch a "loaded" event

  • - DisplayObject + child
  • @@ -646,11 +783,11 @@ When loaded this class will dispatch a "loaded" event

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:139 + src/pixi/display/DisplayObjectContainer.js:120

    @@ -662,6 +799,7 @@ When loaded this class will dispatch a "loaded" event

    Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown

    +
    @@ -672,14 +810,15 @@ When loaded this class will dispatch a "loaded" event

  • - DisplayObject + child DisplayObject
    - +

    The child to add

    +
    @@ -694,7 +833,8 @@ When loaded this class will dispatch a "loaded" event

    - +

    The index to place the child in

    +
    @@ -745,11 +885,11 @@ When loaded this class will dispatch a "loaded" event

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:109 + src/pixi/display/DisplayObject.js:174

    @@ -761,6 +901,7 @@ When loaded this class will dispatch a "loaded" event

    A callback that is used when the users clicks on the displayObject with their mouse

    +
    @@ -772,7 +913,7 @@ When loaded this class will dispatch a "loaded" event

  • interactionData - InteractionData + InteractionData @@ -829,11 +970,11 @@ When loaded this class will dispatch a "loaded" event

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:274 + src/pixi/display/DisplayObjectContainer.js:256

    @@ -845,6 +986,7 @@ When loaded this class will dispatch a "loaded" event

    Returns the Child at the specified index

    +
    @@ -862,7 +1004,8 @@ When loaded this class will dispatch a "loaded" event

    - +

    The index to get the child from

    +
    @@ -875,6 +1018,61 @@ When loaded this class will dispatch a "loaded" event

    +
  • + + +
    +

    load

    + + + () + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/SpineLoader.js:56 + +

    + + + + + +
    + +
    +

    Loads the JSON data

    + +
    + + + + + +
    @@ -913,11 +1111,11 @@ When loaded this class will dispatch a "loaded" event

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:115 + src/pixi/display/DisplayObject.js:180

    @@ -929,6 +1127,7 @@ When loaded this class will dispatch a "loaded" event

    A callback that is used when the user clicks the mouse down over the sprite

    +
    @@ -940,7 +1139,7 @@ When loaded this class will dispatch a "loaded" event

  • interactionData - InteractionData + InteractionData @@ -997,11 +1196,11 @@ When loaded this class will dispatch a "loaded" event

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:141 + src/pixi/display/DisplayObject.js:206

    @@ -1013,6 +1212,7 @@ When loaded this class will dispatch a "loaded" event

    A callback that is used when the users mouse leaves the displayObject

    +
    @@ -1024,7 +1224,7 @@ When loaded this class will dispatch a "loaded" event

  • interactionData - InteractionData + InteractionData @@ -1081,11 +1281,11 @@ When loaded this class will dispatch a "loaded" event

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:135 + src/pixi/display/DisplayObject.js:200

    @@ -1097,6 +1297,7 @@ When loaded this class will dispatch a "loaded" event

    A callback that is used when the users mouse rolls over the displayObject

    +
    @@ -1108,7 +1309,7 @@ When loaded this class will dispatch a "loaded" event

  • interactionData - InteractionData + InteractionData @@ -1165,11 +1366,11 @@ When loaded this class will dispatch a "loaded" event

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:121 + src/pixi/display/DisplayObject.js:186

    @@ -1182,6 +1383,7 @@ When loaded this class will dispatch a "loaded" event

    A callback that is used when the user releases the mouse that was over the displayObject for this callback to be fired the mouse must have been pressed down over the displayObject

    +
    @@ -1193,7 +1395,7 @@ for this callback to be fired the mouse must have been pressed down over the dis
  • interactionData - InteractionData + InteractionData @@ -1250,11 +1452,11 @@ for this callback to be fired the mouse must have been pressed down over the dis

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:128 + src/pixi/display/DisplayObject.js:193

    @@ -1267,6 +1469,7 @@ for this callback to be fired the mouse must have been pressed down over the dis

    A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject for this callback to be fired, The touch must have started over the displayObject

    +
    @@ -1278,7 +1481,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • interactionData - InteractionData + InteractionData @@ -1297,6 +1500,120 @@ for this callback to be fired, The touch must have started over the displayObjec +
  • + + +
    +

    onJSONLoaded

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/SpineLoader.js:72 + +

    + + + + + +
    + +
    +

    Invoke when JSON file is loaded

    + +
    + + + + + + +
    + + +
    +

    onLoaded

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/SpineLoader.js:87 + +

    + + + + + +
    + +
    +

    Invoke when JSON file is loaded

    + +
    + + + + + +
    @@ -1309,7 +1626,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • - DisplayObject + child
  • @@ -1335,11 +1652,11 @@ for this callback to be fired, The touch must have started over the displayObjec

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:291 + src/pixi/display/DisplayObjectContainer.js:274

    @@ -1351,6 +1668,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    Removes a child from the container.

    +
    @@ -1361,14 +1679,15 @@ for this callback to be fired, The touch must have started over the displayObjec
  • - DisplayObject + child DisplayObject
    - +

    The DisplayObject to remove

    +
    @@ -1384,7 +1703,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • -
    +

    setInteractive

    @@ -1404,6 +1723,8 @@ for this callback to be fired, The touch must have started over the displayObjec + deprecated + @@ -1419,16 +1740,18 @@ for this callback to be fired, The touch must have started over the displayObjec

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:193 + src/pixi/display/DisplayObject.js:247

    +

    Deprecated: Simply set the `interactive` property directly

    +
    @@ -1436,6 +1759,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default Instead of using this function you can now simply set the interactive property to true or false

    +
    @@ -1469,7 +1793,7 @@ Instead of using this function you can now simply set the interactive property t
    -
    +

    swapChildren

    @@ -1478,13 +1802,13 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child
  • - DisplayObject2 + child2
  • @@ -1497,6 +1821,8 @@ Instead of using this function you can now simply set the interactive property t + private + @@ -1510,11 +1836,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:227 + src/pixi/display/DisplayObjectContainer.js:207

    @@ -1525,7 +1851,8 @@ Instead of using this function you can now simply set the interactive property t
    -

    Swaps the depth of 2 displayObjects

    +

    [NYI] Swaps the depth of 2 displayObjects

    +
    @@ -1536,7 +1863,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child DisplayObject @@ -1551,7 +1878,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject2 + child2 DisplayObject @@ -1609,11 +1936,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:152 + src/pixi/display/DisplayObject.js:217

    @@ -1626,6 +1953,7 @@ Instead of using this function you can now simply set the interactive property t

    A callback that is used when the users taps on the sprite with their finger basically a touch version of click

    +
    @@ -1637,7 +1965,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -1694,11 +2022,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:165 + src/pixi/display/DisplayObject.js:230

    @@ -1710,6 +2038,7 @@ basically a touch version of click

    A callback that is used when the user releases a touch over the displayObject

    +
    @@ -1721,7 +2050,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -1778,11 +2107,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:171 + src/pixi/display/DisplayObject.js:236

    @@ -1795,6 +2124,7 @@ basically a touch version of click

    A callback that is used when the user releases the touch that was over the displayObject for this callback to be fired, The touch must have started over the sprite

    +
    @@ -1806,7 +2136,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -1863,11 +2193,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:159 + src/pixi/display/DisplayObject.js:224

    @@ -1878,7 +2208,8 @@ for this callback to be fired, The touch must have started over the sprite

  • -

    A callback that is used when the user touch's over the displayObject

    +

    A callback that is used when the user touch's over the displayObject

    +
    @@ -1890,7 +2221,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -1920,6 +2251,50 @@ for this callback to be fired, The touch must have started over the sprite

    Properties

    +
    +

    _interactive

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:115 + +

    + + + + +
    + +
    +

    [read-only] Whether or not the object is interactive, do not toggle directly! use the interactive property

    + +
    + + + + + + +
    + +

    alpha

    Number @@ -1936,11 +2311,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:43 + src/pixi/display/DisplayObject.js:47

    @@ -1951,6 +2326,7 @@ for this callback to be fired, The touch must have started over the sprite

    The opacity of the object.

    +
    @@ -1977,11 +2353,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:98 + src/pixi/display/DisplayObject.js:72

    @@ -1992,6 +2368,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is used to indicate if the displayObject should display a mouse hand cursor on rollover

    +
    @@ -2004,7 +2381,7 @@ for this callback to be fired, The touch must have started over the sprite

    children

    - Array + Array @@ -2018,11 +2395,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:16 + src/pixi/display/DisplayObjectContainer.js:18

    @@ -2033,6 +2410,184 @@ for this callback to be fired, The touch must have started over the sprite

    [read-only] The of children of this container.

    + +
    + + + + + + +
    + + +
    +

    color

    + Array<> + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:145 + +

    + + + + +
    + +
    +

    [NYI] Unkown

    + +
    + + + + + + +
    + + +
    +

    crossorigin

    + Boolean + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/SpineLoader.js:36 + +

    + + + + +
    + +
    +

    Whether the requests should be treated as cross origin

    + +
    + + + + + + +
    + + +
    +

    dynamic

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:154 + +

    + + + + +
    + +
    +

    [NYI] Holds whether or not this object is dynamic, for rendering optimization

    + +
    + + + + + + +
    + + +
    +

    filters

    + Array An array of filters + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:318 + +

    + + + + +
    + +
    +

    Sets the filters for the displayObject. +* IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer. +To remove filters simply set this property to 'null'

    +
    @@ -2045,7 +2600,7 @@ for this callback to be fired, The touch must have started over the sprite

    hitArea

    - Rectangle + Rectangle | Circle | Ellipse | Polygon @@ -2059,11 +2614,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:72 + src/pixi/display/DisplayObject.js:63

    @@ -2075,6 +2630,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is the defined area that will pick up mouse / touch events. It is null by default. Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children)

    +
    @@ -2101,11 +2657,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:204 + src/pixi/display/DisplayObject.js:260

    @@ -2116,6 +2672,98 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Indicates if the sprite will have touch and mouse interactivity. It is false by default

    + +
    + + +

    Default: false

    + + + + + +
    + + +
    +

    loaded

    + Boolean + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/SpineLoader.js:44 + +

    + + + + +
    + +
    +

    [read-only] Whether the data has loaded yet

    + +
    + + + + + + +
    + + +
    +

    localTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:135 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object locally

    +
    @@ -2128,7 +2776,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    mask

    - PIXI.Graphics + Graphics @@ -2142,11 +2790,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:222 + src/pixi/display/DisplayObject.js:280

    @@ -2159,6 +2807,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. To remove a mask, set this property to null.

    +
    @@ -2185,11 +2834,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:58 + src/pixi/display/DisplayObject.js:88

    @@ -2200,6 +2849,7 @@ To remove a mask, set this property to null.

    [read-only] The display object container that contains this display object.

    +
    @@ -2226,11 +2876,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:29 + src/pixi/display/DisplayObject.js:31

    @@ -2241,6 +2891,7 @@ To remove a mask, set this property to null.

    The pivot point of the displayObject that it rotates around

    +
    @@ -2267,11 +2918,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:15 + src/pixi/display/DisplayObject.js:15

    @@ -2282,6 +2933,49 @@ To remove a mask, set this property to null.

    The coordinate of the object relative to the local coordinates of the parent.

    + +
    + + + + + + +
    + + +
    +

    renderable

    + Boolean + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:80 + +

    + + + + +
    + +
    +

    Can this object be rendered

    +
    @@ -2308,11 +3002,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:36 + src/pixi/display/DisplayObject.js:39

    @@ -2323,6 +3017,7 @@ To remove a mask, set this property to null.

    The rotation of the object in radians.

    +
    @@ -2349,11 +3044,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:22 + src/pixi/display/DisplayObject.js:23

    @@ -2364,6 +3059,7 @@ To remove a mask, set this property to null.

    The scale factor of the object.

    +
    @@ -2390,11 +3086,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:65 + src/pixi/display/DisplayObject.js:97

    @@ -2405,6 +3101,52 @@ To remove a mask, set this property to null.

    [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage.

    + +
    + + + + + + +
    + + +
    +

    url

    + String + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/SpineLoader.js:28 + +

    + + + + +
    + +
    +

    The url of the bitmap font data

    +
    @@ -2431,11 +3173,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:50 + src/pixi/display/DisplayObject.js:55

    @@ -2446,6 +3188,93 @@ To remove a mask, set this property to null.

    The visibility of the object.

    + +
    + + + + + + +
    + + +
    +

    worldAlpha

    + Number + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:106 + +

    + + + + +
    + +
    +

    [read-only] The multiplied alpha of the displayobject

    + +
    + + + + + + +
    + + +
    +

    worldTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:125 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object based on world (parent) factors

    +
    @@ -2471,13 +3300,13 @@ To remove a mask, set this property to null.

    - + - - - - - - + + + + + + diff --git a/docs/classes/Sprite.html b/docs/classes/Sprite.html index aea92ff..2916b16 100644 --- a/docs/classes/Sprite.html +++ b/docs/classes/Sprite.html @@ -3,11 +3,11 @@ Sprite - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
  • + +
  • + onTextureUpdate + + +
  • @@ -377,11 +410,13 @@
  • -
  • +
  • setInteractive + deprecated +
  • @@ -391,7 +426,7 @@
  • -
  • +
  • swapChildren @@ -436,6 +471,27 @@ @@ -585,7 +690,7 @@
  • - DisplayObject + child
  • @@ -611,11 +716,11 @@

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:42 + src/pixi/display/DisplayObjectContainer.js:32

    @@ -627,6 +732,7 @@

    Adds a child to the container.

    +
    @@ -637,14 +743,15 @@
  • - DisplayObject + child DisplayObject
    - +

    The DisplayObject to add to the container

    +
    @@ -669,7 +776,7 @@
  • - DisplayObject + child
  • @@ -701,11 +808,11 @@

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:139 + src/pixi/display/DisplayObjectContainer.js:120

    @@ -717,6 +824,7 @@

    Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown

    +
    @@ -727,14 +835,15 @@
  • - DisplayObject + child DisplayObject
    - +

    The child to add

    +
    @@ -749,7 +858,8 @@
    - +

    The index to place the child in

    +
    @@ -800,11 +910,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:109 + src/pixi/display/DisplayObject.js:174

    @@ -816,6 +926,7 @@

    A callback that is used when the users clicks on the displayObject with their mouse

    +
    @@ -827,7 +938,7 @@
  • interactionData - InteractionData + InteractionData @@ -897,7 +1008,7 @@ - src/pixi/display/Sprite.js:135 + src/pixi/display/Sprite.js:165

    @@ -910,6 +1021,7 @@

    Helper function that creates a sprite that will contain a texture from the TextureCache based on the frameId The frame ids are created when a Texture packer file has been loaded

    +
    @@ -928,6 +1040,7 @@

    The frame Id of the texture in the cache

    +
    @@ -946,7 +1059,8 @@ Sprite: - A new Sprite using a texture from the texture cache matching the frameId +

    A new Sprite using a texture from the texture cache matching the frameId

    +
  • @@ -965,7 +1079,7 @@
  • - The + imageId
  • @@ -1004,7 +1118,7 @@ - src/pixi/display/Sprite.js:151 + src/pixi/display/Sprite.js:182

    @@ -1017,6 +1131,7 @@

    Helper function that creates a sprite that will contain a texture based on an image url If the image is not in the texture cache it will be loaded

    +
    @@ -1027,14 +1142,15 @@
  • - The - Object + imageId + String
    -

    image url of the texture

    +

    The image url of the texture

    +
    @@ -1053,7 +1169,8 @@ Sprite: - A new Sprite using a texture from the texture cache matching the image id +

    A new Sprite using a texture from the texture cache matching the image id

    + @@ -1098,11 +1215,11 @@

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:274 + src/pixi/display/DisplayObjectContainer.js:256

    @@ -1114,6 +1231,7 @@

    Returns the Child at the specified index

    +
    @@ -1131,7 +1249,8 @@
    - +

    The index to get the child from

    +
    @@ -1182,11 +1301,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:115 + src/pixi/display/DisplayObject.js:180

    @@ -1198,6 +1317,7 @@

    A callback that is used when the user clicks the mouse down over the sprite

    +
    @@ -1209,7 +1329,7 @@
  • interactionData - InteractionData + InteractionData @@ -1266,11 +1386,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:141 + src/pixi/display/DisplayObject.js:206

    @@ -1282,6 +1402,7 @@

    A callback that is used when the users mouse leaves the displayObject

    +
    @@ -1293,7 +1414,7 @@
  • interactionData - InteractionData + InteractionData @@ -1350,11 +1471,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:135 + src/pixi/display/DisplayObject.js:200

    @@ -1366,6 +1487,7 @@

    A callback that is used when the users mouse rolls over the displayObject

    +
    @@ -1377,7 +1499,7 @@
  • interactionData - InteractionData + InteractionData @@ -1434,11 +1556,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:121 + src/pixi/display/DisplayObject.js:186

    @@ -1451,6 +1573,7 @@

    A callback that is used when the user releases the mouse that was over the displayObject for this callback to be fired the mouse must have been pressed down over the displayObject

    +
    @@ -1462,7 +1585,7 @@ for this callback to be fired the mouse must have been pressed down over the dis
  • interactionData - InteractionData + InteractionData @@ -1519,11 +1642,11 @@ for this callback to be fired the mouse must have been pressed down over the dis

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:128 + src/pixi/display/DisplayObject.js:193

    @@ -1536,6 +1659,7 @@ for this callback to be fired the mouse must have been pressed down over the dis

    A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject for this callback to be fired, The touch must have started over the displayObject

    +
    @@ -1547,7 +1671,97 @@ for this callback to be fired, The touch must have started over the displayObjec
  • interactionData - InteractionData + InteractionData + + + + +
    + +
    + + +
  • + + + + + + + + + + + +
    +

    onTextureUpdate

    + + +
    + (
      + +
    • + + event + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/display/Sprite.js:145 + +

    + + + + + +
    + +
    +

    When the texture is updated, this event will fire to update the scale and frame

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + event + Object @@ -1578,7 +1792,7 @@ for this callback to be fired, The touch must have started over the displayObjec
    • - DisplayObject + child
    • @@ -1604,11 +1818,11 @@ for this callback to be fired, The touch must have started over the displayObjec

      Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:291 + src/pixi/display/DisplayObjectContainer.js:274

      @@ -1620,6 +1834,7 @@ for this callback to be fired, The touch must have started over the displayObjec

      Removes a child from the container.

      +
      @@ -1630,14 +1845,15 @@ for this callback to be fired, The touch must have started over the displayObjec
    • - DisplayObject + child DisplayObject
      - +

      The DisplayObject to remove

      +
      @@ -1653,7 +1869,7 @@ for this callback to be fired, The touch must have started over the displayObjec
    -
    +

    setInteractive

    @@ -1673,6 +1889,8 @@ for this callback to be fired, The touch must have started over the displayObjec + deprecated + @@ -1688,16 +1906,18 @@ for this callback to be fired, The touch must have started over the displayObjec

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:193 + src/pixi/display/DisplayObject.js:247

    +

    Deprecated: Simply set the `interactive` property directly

    +
    @@ -1705,6 +1925,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default Instead of using this function you can now simply set the interactive property to true or false

    +
    @@ -1780,7 +2001,7 @@ Instead of using this function you can now simply set the interactive property t - src/pixi/display/Sprite.js:103 + src/pixi/display/Sprite.js:118

    @@ -1791,7 +2012,8 @@ Instead of using this function you can now simply set the interactive property t
    - +

    Sets the texture of the sprite

    +
    @@ -1810,6 +2032,7 @@ Instead of using this function you can now simply set the interactive property t

    The PIXI texture that is displayed by the sprite

    +
    @@ -1825,7 +2048,7 @@ Instead of using this function you can now simply set the interactive property t
    -
    +

    swapChildren

    @@ -1834,13 +2057,13 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child
  • - DisplayObject2 + child2
  • @@ -1853,6 +2076,8 @@ Instead of using this function you can now simply set the interactive property t + private + @@ -1866,11 +2091,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:227 + src/pixi/display/DisplayObjectContainer.js:207

    @@ -1881,7 +2106,8 @@ Instead of using this function you can now simply set the interactive property t
    -

    Swaps the depth of 2 displayObjects

    +

    [NYI] Swaps the depth of 2 displayObjects

    +
    @@ -1892,7 +2118,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child DisplayObject @@ -1907,7 +2133,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject2 + child2 DisplayObject @@ -1965,11 +2191,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:152 + src/pixi/display/DisplayObject.js:217

    @@ -1982,6 +2208,7 @@ Instead of using this function you can now simply set the interactive property t

    A callback that is used when the users taps on the sprite with their finger basically a touch version of click

    +
    @@ -1993,7 +2220,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -2050,11 +2277,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:165 + src/pixi/display/DisplayObject.js:230

    @@ -2066,6 +2293,7 @@ basically a touch version of click

    A callback that is used when the user releases a touch over the displayObject

    +
    @@ -2077,7 +2305,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -2134,11 +2362,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:171 + src/pixi/display/DisplayObject.js:236

    @@ -2151,6 +2379,7 @@ basically a touch version of click

    A callback that is used when the user releases the touch that was over the displayObject for this callback to be fired, The touch must have started over the sprite

    +
    @@ -2162,7 +2391,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -2219,11 +2448,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:159 + src/pixi/display/DisplayObject.js:224

    @@ -2234,7 +2463,8 @@ for this callback to be fired, The touch must have started over the sprite

  • -

    A callback that is used when the user touch's over the displayObject

    +

    A callback that is used when the user touch's over the displayObject

    +
    @@ -2246,7 +2476,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -2276,6 +2506,144 @@ for this callback to be fired, The touch must have started over the sprite

    Properties

    +
    +

    _height

    + Number + + + + + private + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/display/Sprite.js:60 + +

    + + + + +
    + +
    +

    The height of the sprite (this is initially set by the texture)

    + +
    + + + + + + +
    + + +
    +

    _interactive

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:115 + +

    + + + + +
    + +
    +

    [read-only] Whether or not the object is interactive, do not toggle directly! use the interactive property

    + +
    + + + + + + +
    + + +
    +

    _width

    + Number + + + + + private + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/display/Sprite.js:51 + +

    + + + + +
    + +
    +

    The width of the sprite (this is initially set by the texture)

    + +
    + + + + + + +
    + +

    alpha

    Number @@ -2292,11 +2660,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:43 + src/pixi/display/DisplayObject.js:47

    @@ -2307,6 +2675,7 @@ for this callback to be fired, The touch must have started over the sprite

    The opacity of the object.

    +
    @@ -2340,7 +2709,7 @@ for this callback to be fired, The touch must have started over the sprite

    - src/pixi/display/Sprite.js:21 + src/pixi/display/Sprite.js:23

    @@ -2354,6 +2723,7 @@ for this callback to be fired, The touch must have started over the sprite

    The default is 0,0 this means the textures origin is the top left Setting than anchor to 0.5,0.5 means the textures origin is centered Setting the anchor to 1,1 would mean the textures origin points will be the bottom right

    +
    @@ -2366,7 +2736,7 @@ Setting the anchor to 1,1 would mean the textures origin points will be the bott

    blendMode

    - Uint + Number @@ -2387,7 +2757,7 @@ Setting the anchor to 1,1 would mean the textures origin points will be the bott - src/pixi/display/Sprite.js:38 + src/pixi/display/Sprite.js:42

    @@ -2399,6 +2769,7 @@ Setting the anchor to 1,1 would mean the textures origin points will be the bott

    The blend mode of sprite. currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    +
    @@ -2425,11 +2796,11 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:98 + src/pixi/display/DisplayObject.js:72

    @@ -2440,6 +2811,7 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    This is used to indicate if the displayObject should display a mouse hand cursor on rollover

    +
    @@ -2452,7 +2824,7 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    children

    - Array + Array @@ -2466,11 +2838,11 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:16 + src/pixi/display/DisplayObjectContainer.js:18

    @@ -2481,6 +2853,139 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    [read-only] The of children of this container.

    + +
    + + + + + + +
    + + +
    +

    color

    + Array<> + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:145 + +

    + + + + +
    + +
    +

    [NYI] Unkown

    + +
    + + + + + + +
    + + +
    +

    dynamic

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:154 + +

    + + + + +
    + +
    +

    [NYI] Holds whether or not this object is dynamic, for rendering optimization

    + +
    + + + + + + +
    + + +
    +

    filters

    + Array An array of filters + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:318 + +

    + + + + +
    + +
    +

    Sets the filters for the displayObject. +* IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer. +To remove filters simply set this property to 'null'

    +
    @@ -2493,7 +2998,7 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    height

    - #Number + Number @@ -2514,7 +3019,7 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    - src/pixi/display/Sprite.js:53 + src/pixi/display/Sprite.js:102

    @@ -2524,7 +3029,8 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    -

    The height of the sprite (this is initially set by the texture)

    +

    The height of the sprite, setting this will actually modify the scale to acheive the value set

    +
    @@ -2537,7 +3043,7 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    hitArea

    - Rectangle + Rectangle | Circle | Ellipse | Polygon @@ -2551,11 +3057,11 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:72 + src/pixi/display/DisplayObject.js:63

    @@ -2567,6 +3073,7 @@ currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN

    This is the defined area that will pick up mouse / touch events. It is null by default. Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children)

    +
    @@ -2593,11 +3100,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:204 + src/pixi/display/DisplayObject.js:260

    @@ -2608,6 +3115,53 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Indicates if the sprite will have touch and mouse interactivity. It is false by default

    + +
    + + +

    Default: false

    + + + + + +
    + + +
    +

    localTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:135 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object locally

    +
    @@ -2620,7 +3174,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    mask

    - PIXI.Graphics + Graphics @@ -2634,11 +3188,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:222 + src/pixi/display/DisplayObject.js:280

    @@ -2651,6 +3205,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. To remove a mask, set this property to null.

    +
    @@ -2677,11 +3232,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:58 + src/pixi/display/DisplayObject.js:88

    @@ -2692,6 +3247,7 @@ To remove a mask, set this property to null.

    [read-only] The display object container that contains this display object.

    +
    @@ -2718,11 +3274,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:29 + src/pixi/display/DisplayObject.js:31

    @@ -2733,6 +3289,7 @@ To remove a mask, set this property to null.

    The pivot point of the displayObject that it rotates around

    +
    @@ -2759,11 +3316,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:15 + src/pixi/display/DisplayObject.js:15

    @@ -2774,6 +3331,49 @@ To remove a mask, set this property to null.

    The coordinate of the object relative to the local coordinates of the parent.

    + +
    + + + + + + +
    + + +
    +

    renderable

    + Boolean + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:80 + +

    + + + + +
    + +
    +

    Can this object be rendered

    +
    @@ -2800,11 +3400,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:36 + src/pixi/display/DisplayObject.js:39

    @@ -2815,6 +3415,7 @@ To remove a mask, set this property to null.

    The rotation of the object in radians.

    +
    @@ -2841,11 +3442,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:22 + src/pixi/display/DisplayObject.js:23

    @@ -2856,6 +3457,7 @@ To remove a mask, set this property to null.

    The scale factor of the object.

    +
    @@ -2882,11 +3484,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:65 + src/pixi/display/DisplayObject.js:97

    @@ -2897,6 +3499,7 @@ To remove a mask, set this property to null.

    [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage.

    +
    @@ -2930,7 +3533,7 @@ To remove a mask, set this property to null.

    - src/pixi/display/Sprite.js:31 + src/pixi/display/Sprite.js:34

    @@ -2941,6 +3544,7 @@ To remove a mask, set this property to null.

    The texture that the sprite is using

    +
    @@ -2967,11 +3571,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:50 + src/pixi/display/DisplayObject.js:55

    @@ -2982,6 +3586,7 @@ To remove a mask, set this property to null.

    The visibility of the object.

    +
    @@ -2994,7 +3599,7 @@ To remove a mask, set this property to null.

    width

    - #Number + Number @@ -3015,7 +3620,7 @@ To remove a mask, set this property to null.

    - src/pixi/display/Sprite.js:46 + src/pixi/display/Sprite.js:86

    @@ -3025,7 +3630,94 @@ To remove a mask, set this property to null.

    -

    The width of the sprite (this is initially set by the texture)

    +

    The width of the sprite, setting this will actually modify the scale to acheive the value set

    + +
    + + + + + + +
    + + +
    +

    worldAlpha

    + Number + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:106 + +

    + + + + +
    + +
    +

    [read-only] The multiplied alpha of the displayobject

    + +
    + + + + + + +
    + + +
    +

    worldTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:125 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object based on world (parent) factors

    +
    @@ -3051,13 +3743,13 @@ To remove a mask, set this property to null.

    - + - - - - - - + + + + + + diff --git a/docs/classes/SpriteSheetLoader.html b/docs/classes/SpriteSheetLoader.html index f1091f0..824e84c 100644 --- a/docs/classes/SpriteSheetLoader.html +++ b/docs/classes/SpriteSheetLoader.html @@ -3,11 +3,11 @@ SpriteSheetLoader - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -145,16 +169,21 @@

    SpriteSheetLoader Class

    - - -
    - Extends EventTarget +
    + Uses +
    + + @@ -171,12 +200,13 @@

    The sprite sheet loader is used to load in JSON sprite sheet data -To generate the data you can use http://www.codeandweb.com/texturepacker and publish the "JSON" format +To generate the data you can use http://www.codeandweb.com/texturepacker and publish the "JSON" format There is a free version so thats nice, although the paid version is great value for money. -It is highly recommended to use Sprite sheets (also know as texture atlas") as it means sprite"s can be batched and drawn together for highly increased rendering speed. +It is highly recommended to use Sprite sheets (also know as texture atlas") as it means sprite"s can be batched and drawn together for highly increased rendering speed. Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId() This loader will also load the image file that the Spritesheet points to as well as the data. -When loaded this class will dispatch a "loaded" event

    +When loaded this class will dispatch a "loaded" event

    +
    @@ -230,7 +260,7 @@ When loaded this class will dispatch a "loaded" event

    - src/pixi/loaders/SpriteSheetLoader.js:5 + src/pixi/loaders/SpriteSheetLoader.js:5

    @@ -259,7 +289,8 @@ When loaded this class will dispatch a "loaded" event

    -

    the url of the sprite sheet JSON file

    +

    The url of the sprite sheet JSON file

    +
    @@ -274,7 +305,8 @@ When loaded this class will dispatch a "loaded" event

    - +

    Whether requests should be treated as crossorigin

    +
    @@ -297,6 +329,10 @@ When loaded this class will dispatch a "loaded" event

  • Index
  • +
  • Methods
  • + + +
  • Properties
  • @@ -307,7 +343,79 @@ When loaded this class will dispatch a "loaded" event

    Item Index

    +
    +

    Methods

    + +
    + + + +
    +

    Properties

    + + +
    @@ -316,7 +424,413 @@ When loaded this class will dispatch a "loaded" event

    +
    +

    Methods

    + +
    +

    load

    + + + () + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/SpriteSheetLoader.js:74 + +

    + + + + + +
    + +
    +

    This will begin loading the JSON file

    + +
    + + + + + + +
    + + +
    +

    onJSONLoaded

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/SpriteSheetLoader.js:89 + +

    + + + + + +
    + +
    +

    Invoke when JSON file is loaded

    + +
    + + + + + + +
    + + +
    +

    onLoaded

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/SpriteSheetLoader.js:126 + +

    + + + + + +
    + +
    +

    Invoke when all files are loaded (json and texture)

    + +
    + + + + + + +
    + + +
    + + + +
    +

    Properties

    + + +
    +

    baseUrl

    + String + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/SpriteSheetLoader.js:45 + +

    + + + + +
    + +
    +

    [read-only] The base url of the bitmap font data

    + +
    + + + + + + +
    + + +
    +

    crossorigin

    + Boolean + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/SpriteSheetLoader.js:37 + +

    + + + + +
    + +
    +

    Whether the requests should be treated as cross origin

    + +
    + + + + + + +
    + + +
    +

    frames

    + Object + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/SpriteSheetLoader.js:62 + +

    + + + + +
    + +
    +

    The frames of the sprite sheet

    + +
    + + + + + + +
    + + +
    +

    texture

    + Texture + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/SpriteSheetLoader.js:54 + +

    + + + + +
    + +
    +

    The texture being loaded

    + +
    + + + + + + +
    + + +
    +

    url

    + String + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/loaders/SpriteSheetLoader.js:29 + +

    + + + + +
    + +
    +

    The url of the bitmap font data

    + +
    + + + + + + +
    + + +
    @@ -331,13 +845,13 @@ When loaded this class will dispatch a "loaded" event

    - + - - - - - - + + + + + + diff --git a/docs/classes/Stage.html b/docs/classes/Stage.html index e145e0c..84ad082 100644 --- a/docs/classes/Stage.html +++ b/docs/classes/Stage.html @@ -3,11 +3,11 @@ Stage - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -224,7 +243,7 @@ - src/pixi/display/Stage.js:5 + src/pixi/display/Stage.js:5

    @@ -253,22 +272,9 @@
    -

    the background color of the stage

    -
    +

    the background color of the stage, easiest way to pass this in is in hex format + like: 0xFFFFFF for white

    - - - -
  • - - interactive - Boolean - - - - -
    -

    enable / disable interaction (default is false)

    @@ -394,14 +400,23 @@
  • -
  • - setInteractive +
  • + setInteractionDelegate
  • -
  • +
  • + setInteractive + + + + deprecated + +
  • + +
  • swapChildren @@ -434,13 +449,6 @@ -
  • - -
  • - updateTransform - - -
  • @@ -453,6 +461,13 @@ @@ -567,7 +645,7 @@
  • - DisplayObject + child
  • @@ -593,11 +671,11 @@

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:42 + src/pixi/display/DisplayObjectContainer.js:32

    @@ -609,6 +687,7 @@

    Adds a child to the container.

    +
    @@ -619,14 +698,15 @@
  • - DisplayObject + child DisplayObject
    - +

    The DisplayObject to add to the container

    +
    @@ -651,7 +731,7 @@
  • - DisplayObject + child
  • @@ -683,11 +763,11 @@

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:139 + src/pixi/display/DisplayObjectContainer.js:120

    @@ -699,6 +779,7 @@

    Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown

    +
    @@ -709,14 +790,15 @@
  • - DisplayObject + child DisplayObject
    - +

    The child to add

    +
    @@ -731,7 +813,8 @@
    - +

    The index to place the child in

    +
    @@ -782,11 +865,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:109 + src/pixi/display/DisplayObject.js:174

    @@ -798,6 +881,7 @@

    A callback that is used when the users clicks on the displayObject with their mouse

    +
    @@ -809,7 +893,7 @@
  • interactionData - InteractionData + InteractionData @@ -866,11 +950,11 @@

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:274 + src/pixi/display/DisplayObjectContainer.js:256

    @@ -882,6 +966,7 @@

    Returns the Child at the specified index

    +
    @@ -899,7 +984,8 @@
    - +

    The index to get the child from

    +
    @@ -951,7 +1037,7 @@ - src/pixi/display/Stage.js:78 + src/pixi/display/Stage.js:125

    @@ -963,6 +1049,7 @@

    This will return the point containing global coords of the mouse.

    +
    @@ -976,7 +1063,8 @@ Point: - The point containing the coords of the global InteractionData position. +

    The point containing the coords of the global InteractionData position.

    +
  • @@ -1021,11 +1109,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:115 + src/pixi/display/DisplayObject.js:180

    @@ -1037,6 +1125,7 @@

    A callback that is used when the user clicks the mouse down over the sprite

    +
    @@ -1048,7 +1137,7 @@
  • interactionData - InteractionData + InteractionData @@ -1105,11 +1194,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:141 + src/pixi/display/DisplayObject.js:206

    @@ -1121,6 +1210,7 @@

    A callback that is used when the users mouse leaves the displayObject

    +
    @@ -1132,7 +1222,7 @@
  • interactionData - InteractionData + InteractionData @@ -1189,11 +1279,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:135 + src/pixi/display/DisplayObject.js:200

    @@ -1205,6 +1295,7 @@

    A callback that is used when the users mouse rolls over the displayObject

    +
    @@ -1216,7 +1307,7 @@
  • interactionData - InteractionData + InteractionData @@ -1273,11 +1364,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:121 + src/pixi/display/DisplayObject.js:186

    @@ -1290,6 +1381,7 @@

    A callback that is used when the user releases the mouse that was over the displayObject for this callback to be fired the mouse must have been pressed down over the displayObject

    +
    @@ -1301,7 +1393,7 @@ for this callback to be fired the mouse must have been pressed down over the dis
  • interactionData - InteractionData + InteractionData @@ -1358,11 +1450,11 @@ for this callback to be fired the mouse must have been pressed down over the dis

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:128 + src/pixi/display/DisplayObject.js:193

    @@ -1375,6 +1467,7 @@ for this callback to be fired the mouse must have been pressed down over the dis

    A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject for this callback to be fired, The touch must have started over the displayObject

    +
    @@ -1386,7 +1479,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • interactionData - InteractionData + InteractionData @@ -1417,7 +1510,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • - DisplayObject + child
  • @@ -1443,11 +1536,11 @@ for this callback to be fired, The touch must have started over the displayObjec

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:291 + src/pixi/display/DisplayObjectContainer.js:274

    @@ -1459,6 +1552,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    Removes a child from the container.

    +
    @@ -1469,14 +1563,15 @@ for this callback to be fired, The touch must have started over the displayObjec
  • - DisplayObject + child DisplayObject
    - +

    The DisplayObject to remove

    +
    @@ -1534,7 +1629,7 @@ for this callback to be fired, The touch must have started over the displayObjec - src/pixi/display/Stage.js:65 + src/pixi/display/Stage.js:109

    @@ -1545,7 +1640,8 @@ for this callback to be fired, The touch must have started over the displayObjec
    - +

    Sets the background color for the stage

    +
    @@ -1563,7 +1659,9 @@ for this callback to be fired, The touch must have started over the displayObjec
    - +

    the color of the background, easiest way to pass this in is in hex format + like: 0xFFFFFF for white

    +
    @@ -1579,8 +1677,8 @@ for this callback to be fired, The touch must have started over the displayObjec -
    -

    setInteractive

    +
    +

    setInteractionDelegate

    @@ -1588,7 +1686,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • - interactive + domElement
  • @@ -1613,12 +1711,15 @@ for this callback to be fired, The touch must have started over the displayObjec
    -

    Inherited from - DisplayObject: + +

    + + Defined in + - src/pixi/display/DisplayObject.js:193 + src/pixi/display/Stage.js:70

    @@ -1626,11 +1727,103 @@ for this callback to be fired, The touch must have started over the displayObjec +
    + +
    +

    Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element. +This is useful for when you have other DOM elements ontop of the Canvas element.

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + domElement + DOMElement + + + + +
      +

      This new domElement which will receive mouse/touch events

      + +
      + + +
    • + +
    +
    + + + + + + + + +
    +

    setInteractive

    + + +
    + (
      + +
    • + + interactive + +
    • + +
    ) +
    + + + + + + deprecated + + + + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:247 + +

    + + + +

    Deprecated: Simply set the `interactive` property directly

    + + +

    [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default Instead of using this function you can now simply set the interactive property to true or false

    +
    @@ -1664,7 +1857,7 @@ Instead of using this function you can now simply set the interactive property t
    -
    +

    swapChildren

    @@ -1673,13 +1866,13 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child
  • - DisplayObject2 + child2
  • @@ -1692,6 +1885,8 @@ Instead of using this function you can now simply set the interactive property t + private + @@ -1705,11 +1900,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:227 + src/pixi/display/DisplayObjectContainer.js:207

    @@ -1720,7 +1915,8 @@ Instead of using this function you can now simply set the interactive property t
    -

    Swaps the depth of 2 displayObjects

    +

    [NYI] Swaps the depth of 2 displayObjects

    +
    @@ -1731,7 +1927,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child DisplayObject @@ -1746,7 +1942,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject2 + child2 DisplayObject @@ -1804,11 +2000,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:152 + src/pixi/display/DisplayObject.js:217

    @@ -1821,6 +2017,7 @@ Instead of using this function you can now simply set the interactive property t

    A callback that is used when the users taps on the sprite with their finger basically a touch version of click

    +
    @@ -1832,7 +2029,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -1889,11 +2086,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:165 + src/pixi/display/DisplayObject.js:230

    @@ -1905,6 +2102,7 @@ basically a touch version of click

    A callback that is used when the user releases a touch over the displayObject

    +
    @@ -1916,7 +2114,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -1973,11 +2171,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:171 + src/pixi/display/DisplayObject.js:236

    @@ -1990,6 +2188,7 @@ basically a touch version of click

    A callback that is used when the user releases the touch that was over the displayObject for this callback to be fired, The touch must have started over the sprite

    +
    @@ -2001,7 +2200,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -2058,11 +2257,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:159 + src/pixi/display/DisplayObject.js:224

    @@ -2073,7 +2272,8 @@ for this callback to be fired, The touch must have started over the sprite

  • -

    A callback that is used when the user touch's over the displayObject

    +

    A callback that is used when the user touch's over the displayObject

    +
    @@ -2085,7 +2285,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -2107,21 +2307,22 @@ for this callback to be fired, The touch must have started over the sprite

    -
    -

    updateTransform

    +
    + - - () - + +
    +

    Properties

    + + +
    +

    _interactive

    + Boolean - - - - - + private @@ -2131,26 +2332,23 @@ for this callback to be fired, The touch must have started over the sprite

    - +

    [read-only] Whether or not the object is interactive, do not toggle directly! use the interactive property

    +
    @@ -2161,14 +2359,6 @@ for this callback to be fired, The touch must have started over the sprite

    -
    - - - -
    -

    Properties

    - -

    alpha

    Number @@ -2185,11 +2375,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:43 + src/pixi/display/DisplayObject.js:47

    @@ -2200,6 +2390,7 @@ for this callback to be fired, The touch must have started over the sprite

    The opacity of the object.

    +
    @@ -2226,11 +2417,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:98 + src/pixi/display/DisplayObject.js:72

    @@ -2241,6 +2432,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is used to indicate if the displayObject should display a mouse hand cursor on rollover

    +
    @@ -2253,7 +2445,7 @@ for this callback to be fired, The touch must have started over the sprite

    children

    - Array + Array @@ -2267,11 +2459,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:16 + src/pixi/display/DisplayObjectContainer.js:18

    @@ -2282,6 +2474,186 @@ for this callback to be fired, The touch must have started over the sprite

    [read-only] The of children of this container.

    + +
    + + + + + + +
    + + +
    +

    color

    + Array<> + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:145 + +

    + + + + +
    + +
    +

    [NYI] Unkown

    + +
    + + + + + + +
    + + +
    +

    dirty

    + Boolean + + + + + private + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/display/Stage.js:44 + +

    + + + + +
    + +
    +

    Whether the stage is dirty and needs to have interactions updated

    + +
    + + + + + + +
    + + +
    +

    dynamic

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:154 + +

    + + + + +
    + +
    +

    [NYI] Holds whether or not this object is dynamic, for rendering optimization

    + +
    + + + + + + +
    + + +
    +

    filters

    + Array An array of filters + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:318 + +

    + + + + +
    + +
    +

    Sets the filters for the displayObject. +* IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer. +To remove filters simply set this property to 'null'

    +
    @@ -2294,7 +2666,7 @@ for this callback to be fired, The touch must have started over the sprite

    hitArea

    - Rectangle + Rectangle | Circle | Ellipse | Polygon @@ -2308,11 +2680,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:72 + src/pixi/display/DisplayObject.js:63

    @@ -2324,6 +2696,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is the defined area that will pick up mouse / touch events. It is null by default. Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children)

    +
    @@ -2334,7 +2707,52 @@ Setting it is a neat way of optimising the hitTest function that the interaction
    -
    +
    +

    interactive

    + InteractionManager + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/display/Stage.js:36 + +

    + + + + +
    + +
    +

    The interaction manage for this stage, manages all interactive activity on the stage

    + +
    + + + + + + +
    + + +

    interactive

    Boolean @@ -2348,13 +2766,16 @@ Setting it is a neat way of optimising the hitTest function that the interaction
    +

    Inherited from + + DisplayObject + -

    Inherited from - DisplayObject: + but overwritten in - src/pixi/display/DisplayObject.js:204 + src/pixi/display/Stage.js:28

    @@ -2364,7 +2785,52 @@ Setting it is a neat way of optimising the hitTest function that the interaction
    -

    Indicates if the sprite will have touch and mouse interactivity. It is false by default

    +

    Whether or not the stage is interactive

    + +
    + + + + + + +
    + + +
    +

    localTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:135 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object locally

    +
    @@ -2377,7 +2843,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    mask

    - PIXI.Graphics + Graphics @@ -2391,11 +2857,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:222 + src/pixi/display/DisplayObject.js:280

    @@ -2408,6 +2874,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. To remove a mask, set this property to null.

    +
    @@ -2434,11 +2901,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:58 + src/pixi/display/DisplayObject.js:88

    @@ -2449,6 +2916,7 @@ To remove a mask, set this property to null.

    [read-only] The display object container that contains this display object.

    +
    @@ -2475,11 +2943,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:29 + src/pixi/display/DisplayObject.js:31

    @@ -2490,6 +2958,7 @@ To remove a mask, set this property to null.

    The pivot point of the displayObject that it rotates around

    +
    @@ -2516,11 +2985,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:15 + src/pixi/display/DisplayObject.js:15

    @@ -2531,6 +3000,49 @@ To remove a mask, set this property to null.

    The coordinate of the object relative to the local coordinates of the parent.

    + +
    + + + + + + +
    + + +
    +

    renderable

    + Boolean + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:80 + +

    + + + + +
    + +
    +

    Can this object be rendered

    +
    @@ -2557,11 +3069,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:36 + src/pixi/display/DisplayObject.js:39

    @@ -2572,6 +3084,7 @@ To remove a mask, set this property to null.

    The rotation of the object in radians.

    +
    @@ -2598,11 +3111,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:22 + src/pixi/display/DisplayObject.js:23

    @@ -2613,6 +3126,7 @@ To remove a mask, set this property to null.

    The scale factor of the object.

    +
    @@ -2639,11 +3153,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:65 + src/pixi/display/DisplayObject.js:97

    @@ -2654,6 +3168,7 @@ To remove a mask, set this property to null.

    [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage.

    +
    @@ -2680,11 +3195,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:50 + src/pixi/display/DisplayObject.js:55

    @@ -2695,6 +3210,96 @@ To remove a mask, set this property to null.

    The visibility of the object.

    + +
    + + + + + + +
    + + +
    +

    worldAlpha

    + Number + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:106 + +

    + + + + +
    + +
    +

    [read-only] The multiplied alpha of the displayobject

    + +
    + + + + + + +
    + + +
    +

    worldTransform

    + Mat3 + + + + + private + + + + + + +
    + +

    Inherited from + + DisplayObject + + + but overwritten in + + + + src/pixi/display/Stage.js:18 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object based on world (parent) factors

    +
    @@ -2720,13 +3325,13 @@ To remove a mask, set this property to null.

    - + - - - - - - + + + + + + diff --git a/docs/classes/Text.html b/docs/classes/Text.html index db91c58..e9d556b 100644 --- a/docs/classes/Text.html +++ b/docs/classes/Text.html @@ -3,11 +3,11 @@ Text - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -154,7 +178,7 @@
    - Defined in: src/pixi/text/Text.js:5 + Defined in: src/pixi/text/Text.js:5
    @@ -170,7 +194,8 @@
    -

    A Text Object will create a line(s) of text to split a line you can use "\n"

    +

    A Text Object will create a line(s) of text to split a line you can use "\n"

    +
    @@ -224,7 +249,7 @@ - src/pixi/text/Text.js:5 + src/pixi/text/Text.js:5

    @@ -254,6 +279,7 @@

    The copy that you would like the text to display

    +
    @@ -270,6 +296,7 @@

    The style parameters

    +
    @@ -283,7 +310,8 @@
    -

    default "bold 20pt Arial" The style and size of the font

    +

    default "bold 20pt Arial" The style and size of the font

    +
    @@ -297,7 +325,8 @@
    -

    A canvas fillstyle that will be used on the text eg "red", "#00FF00"

    +

    A canvas fillstyle that will be used on the text eg "red", "#00FF00"

    +
    @@ -311,7 +340,8 @@
    -

    An alignment of the multiline text ("left", "center" or "right")

    +

    An alignment of the multiline text ("left", "center" or "right")

    +
    @@ -325,7 +355,8 @@
    -

    A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00"

    +

    A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00"

    +
    @@ -340,6 +371,7 @@

    A number that represents the thickness of the stroke. Default is 0 (no stroke)

    +
    @@ -354,6 +386,7 @@

    Indicates if word wrap should be used

    +
    @@ -368,6 +401,7 @@

    The width at which text will wrap

    +
    @@ -432,6 +466,13 @@ +
  • + +
  • + destroy + + +
  • @@ -474,6 +515,13 @@ +
  • + +
  • + onTextureUpdate + + +
  • @@ -483,11 +531,13 @@
  • -
  • +
  • setInteractive + deprecated +
  • @@ -504,7 +554,7 @@
  • -
  • +
  • swapChildren @@ -537,6 +587,34 @@ +
  • + +
  • + updateText + + + +
  • + +
  • + updateTexture + + + +
  • + +
  • + updateTransform + + + +
  • + +
  • + wordWrap + + +
  • @@ -549,6 +627,27 @@ @@ -698,7 +846,7 @@
  • - DisplayObject + child
  • @@ -724,11 +872,11 @@

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:42 + src/pixi/display/DisplayObjectContainer.js:32

    @@ -740,6 +888,7 @@

    Adds a child to the container.

    +
    @@ -750,14 +899,15 @@
  • - DisplayObject + child DisplayObject
    - +

    The DisplayObject to add to the container

    +
    @@ -782,7 +932,7 @@
  • - DisplayObject + child
  • @@ -814,11 +964,11 @@

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:139 + src/pixi/display/DisplayObjectContainer.js:120

    @@ -830,6 +980,7 @@

    Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown

    +
    @@ -840,14 +991,15 @@
  • - DisplayObject + child DisplayObject
    - +

    The child to add

    +
    @@ -862,7 +1014,8 @@
    - +

    The index to place the child in

    +
    @@ -913,11 +1066,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:109 + src/pixi/display/DisplayObject.js:174

    @@ -929,6 +1082,7 @@

    A callback that is used when the users clicks on the displayObject with their mouse

    +
    @@ -940,7 +1094,95 @@
  • interactionData - InteractionData + InteractionData + + + + +
    + +
    + + +
  • + + + + + + + + + + + +
    +

    destroy

    + + +
    + (
      + +
    • + + destroyTexture + +
    • + +
    ) +
    + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/text/Text.js:270 + +

    + + + + + +
    + +
    +

    Destroys this text object

    + +
    + + +
    +

    Parameters:

    + + +
    + + + + + +
    + + +
    +

    onTextureUpdate

    + + +
    + (
      + +
    • + + event + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + +

    Inherited from + Sprite: + + + + src/pixi/display/Sprite.js:145 + +

    + + + + + +
    + +
    +

    When the texture is updated, this event will fire to update the scale and frame

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + event + Object @@ -1477,7 +1813,7 @@ for this callback to be fired, The touch must have started over the displayObjec
    • - DisplayObject + child
    • @@ -1503,11 +1839,11 @@ for this callback to be fired, The touch must have started over the displayObjec

      Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:291 + src/pixi/display/DisplayObjectContainer.js:274

      @@ -1519,6 +1855,7 @@ for this callback to be fired, The touch must have started over the displayObjec

      Removes a child from the container.

      +
      @@ -1529,14 +1866,15 @@ for this callback to be fired, The touch must have started over the displayObjec
    • - DisplayObject + child DisplayObject
      - +

      The DisplayObject to remove

      +
      @@ -1552,7 +1890,7 @@ for this callback to be fired, The touch must have started over the displayObjec
    -
    +

    setInteractive

    @@ -1572,6 +1910,8 @@ for this callback to be fired, The touch must have started over the displayObjec + deprecated + @@ -1587,16 +1927,18 @@ for this callback to be fired, The touch must have started over the displayObjec

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:193 + src/pixi/display/DisplayObject.js:247

    +

    Deprecated: Simply set the `interactive` property directly

    +
    @@ -1604,6 +1946,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default Instead of using this function you can now simply set the interactive property to true or false

    +
    @@ -1685,7 +2028,7 @@ Instead of using this function you can now simply set the interactive property t - src/pixi/text/Text.js:37 + src/pixi/text/Text.js:38

    @@ -1697,6 +2040,7 @@ Instead of using this function you can now simply set the interactive property t

    Set the style of the text

    +
    @@ -1716,6 +2060,7 @@ Instead of using this function you can now simply set the interactive property t

    The style parameters

    +
    @@ -1729,7 +2074,8 @@ Instead of using this function you can now simply set the interactive property t
    -

    A canvas fillstyle that will be used on the text eg "red", "#00FF00"

    +

    A canvas fillstyle that will be used on the text eg "red", "#00FF00"

    +
    @@ -1743,7 +2089,8 @@ Instead of using this function you can now simply set the interactive property t
    -

    An alignment of the multiline text ("left", "center" or "right")

    +

    An alignment of the multiline text ("left", "center" or "right")

    +
    @@ -1757,7 +2104,8 @@ Instead of using this function you can now simply set the interactive property t
    -

    A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00"

    +

    A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00"

    +
    @@ -1772,6 +2120,7 @@ Instead of using this function you can now simply set the interactive property t

    A number that represents the thickness of the stroke. Default is 0 (no stroke)

    +
    @@ -1786,6 +2135,7 @@ Instead of using this function you can now simply set the interactive property t

    Indicates if word wrap should be used

    +
    @@ -1800,6 +2150,7 @@ Instead of using this function you can now simply set the interactive property t

    The width at which text will wrap

    +
    @@ -1818,7 +2169,8 @@ Instead of using this function you can now simply set the interactive property t
    -

    20pt Arial"] The style and size of the font

    +

    20pt Arial"] The style and size of the font

    +
    @@ -1869,11 +2221,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - Sprite: + Sprite: - src/pixi/display/Sprite.js:103 + src/pixi/display/Sprite.js:118

    @@ -1884,7 +2236,8 @@ Instead of using this function you can now simply set the interactive property t
    - +

    Sets the texture of the sprite

    +
    @@ -1903,6 +2256,7 @@ Instead of using this function you can now simply set the interactive property t

    The PIXI texture that is displayed by the sprite

    +
    @@ -1918,7 +2272,7 @@ Instead of using this function you can now simply set the interactive property t
    -
    +

    swapChildren

    @@ -1927,13 +2281,13 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child
  • - DisplayObject2 + child2
  • @@ -1946,6 +2300,8 @@ Instead of using this function you can now simply set the interactive property t + private + @@ -1959,11 +2315,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:227 + src/pixi/display/DisplayObjectContainer.js:207

    @@ -1974,7 +2330,8 @@ Instead of using this function you can now simply set the interactive property t
    -

    Swaps the depth of 2 displayObjects

    +

    [NYI] Swaps the depth of 2 displayObjects

    +
    @@ -1985,7 +2342,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + child DisplayObject @@ -2000,7 +2357,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject2 + child2 DisplayObject @@ -2058,11 +2415,11 @@ Instead of using this function you can now simply set the interactive property t

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:152 + src/pixi/display/DisplayObject.js:217

    @@ -2075,6 +2432,7 @@ Instead of using this function you can now simply set the interactive property t

    A callback that is used when the users taps on the sprite with their finger basically a touch version of click

    +
    @@ -2086,7 +2444,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -2143,11 +2501,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:165 + src/pixi/display/DisplayObject.js:230

    @@ -2159,6 +2517,7 @@ basically a touch version of click

    A callback that is used when the user releases a touch over the displayObject

    +
    @@ -2170,7 +2529,7 @@ basically a touch version of click

  • interactionData - InteractionData + InteractionData @@ -2227,11 +2586,11 @@ basically a touch version of click

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:171 + src/pixi/display/DisplayObject.js:236

    @@ -2244,6 +2603,7 @@ basically a touch version of click

    A callback that is used when the user releases the touch that was over the displayObject for this callback to be fired, The touch must have started over the sprite

    +
    @@ -2255,7 +2615,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -2312,11 +2672,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:159 + src/pixi/display/DisplayObject.js:224

    @@ -2327,7 +2687,8 @@ for this callback to be fired, The touch must have started over the sprite

  • -

    A callback that is used when the user touch's over the displayObject

    +

    A callback that is used when the user touch's over the displayObject

    +
    @@ -2339,7 +2700,268 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData + + + + +
    + +
    + + +
  • + + + + + + + + + + + +
    +

    updateText

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/text/Text.js:77 + +

    + + + + + +
    + +
    +

    Renders text

    + +
    + + + + + + +
    + + +
    +

    updateTexture

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/text/Text.js:148 + +

    + + + + + +
    + +
    +

    Updates texture size based on canvas size

    + +
    + + + + + + +
    + + +
    +

    updateTransform

    + + + () + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/text/Text.js:167 + +

    + + + + + +
    + +
    +

    Updates the transfor of this object

    + +
    + + + + + + +
    + + +
    +

    wordWrap

    + + +
    + (
      + +
    • + + text + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/text/Text.js:216 + +

    + + + + + +
    + +
    +

    A Text Object will apply wordwrap

    + +
    + + +
    +

    Parameters:

    + + )
    @@ -764,7 +925,7 @@ - src/pixi/textures/Texture.js:105 + src/pixi/textures/Texture.js:127

    @@ -776,7 +937,8 @@

    Helper function that returns a texture based on an image url - If the image is not in the texture cache it will be created and loaded

    +If the image is not in the texture cache it will be created and loaded

    +
    @@ -795,6 +957,23 @@

    The image url of the texture

    + +
    + + + + +
  • + + crossorigin + Boolean + + + + +
    +

    Whether requests should be treated as crossorigin

    +
    @@ -811,13 +990,104 @@
    - Texture +

    Texture

    +
  • + + + +
    +

    onBaseTextureLoaded

    + + +
    + (
      + +
    • + + event + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/textures/Texture.js:73 + +

    + + + + + +
    + +
    +

    Called when the base texture is loaded

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + event + Object + + + + +
      + +
      + + +
    • + +
    +
    + + + + +
    @@ -869,7 +1139,7 @@ - src/pixi/textures/Texture.js:171 + src/pixi/textures/Texture.js:195

    @@ -881,6 +1151,7 @@

    Remove a texture from the textureCache.

    +
    @@ -899,6 +1170,7 @@

    the id of the texture to be removed

    +
    @@ -917,7 +1189,8 @@ Texture: - the texture that was removed +

    the texture that was removed

    + @@ -969,7 +1242,7 @@ - src/pixi/textures/Texture.js:83 + src/pixi/textures/Texture.js:104

    @@ -981,6 +1254,7 @@

    Specifies the rectangle region of the baseTexture

    +
    @@ -998,7 +1272,8 @@
    - +

    The frame of the texture to set it to

    +
    @@ -1045,7 +1320,7 @@ - src/pixi/textures/Texture.js:31 + src/pixi/textures/Texture.js:31

    @@ -1056,6 +1331,7 @@

    The base texture of this texture

    +
    @@ -1068,7 +1344,7 @@

    frame

    - #Rectangle + Rectangle @@ -1089,7 +1365,7 @@ - src/pixi/textures/Texture.js:40 + src/pixi/textures/Texture.js:39

    @@ -1100,6 +1376,52 @@

    The frame specifies the region of the base texture that this texture uses

    + +
    + + + + + + +
    + + +
    +

    trim

    + Point + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/textures/Texture.js:47 + +

    + + + + +
    + +
    +

    The trim point

    +
    @@ -1125,13 +1447,13 @@
    - + - - - - - - + + + + + + diff --git a/docs/classes/TilingSprite.html b/docs/classes/TilingSprite.html index 663486b..9ed2238 100644 --- a/docs/classes/TilingSprite.html +++ b/docs/classes/TilingSprite.html @@ -3,11 +3,11 @@ TilingSprite - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -154,7 +178,7 @@ @@ -171,6 +195,7 @@

    A tiling sprite is a fast way of rendering a tiling image

    +
    @@ -230,7 +255,7 @@ - src/pixi/extras/TilingSprite.js:5 + src/pixi/extras/TilingSprite.js:5

    @@ -260,6 +285,7 @@

    the texture of the tiling sprite

    +
    @@ -275,6 +301,7 @@

    the width of the tiling sprite

    +
    @@ -290,6 +317,7 @@

    the height of the tiling sprite

    +
    @@ -392,6 +420,13 @@ + + +
  • + onTextureUpdate + + +
  • @@ -401,14 +436,23 @@
  • -
  • +
  • setInteractive + deprecated + +
  • + +
  • + setTexture + + +
  • -
  • +
  • swapChildren @@ -453,6 +497,13 @@ @@ -581,7 +702,7 @@
  • - DisplayObject + child
  • @@ -607,11 +728,11 @@

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:42 + src/pixi/display/DisplayObjectContainer.js:32

    @@ -623,6 +744,7 @@

    Adds a child to the container.

    +
    @@ -633,14 +755,15 @@
  • - DisplayObject + child DisplayObject
    - +

    The DisplayObject to add to the container

    +
    @@ -665,7 +788,7 @@
  • - DisplayObject + child
  • @@ -697,11 +820,11 @@

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:139 + src/pixi/display/DisplayObjectContainer.js:120

    @@ -713,6 +836,7 @@

    Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown

    +
    @@ -723,14 +847,15 @@
  • - DisplayObject + child DisplayObject
    - +

    The child to add

    +
    @@ -745,7 +870,8 @@
    - +

    The index to place the child in

    +
    @@ -796,11 +922,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:109 + src/pixi/display/DisplayObject.js:174

    @@ -812,6 +938,7 @@

    A callback that is used when the users clicks on the displayObject with their mouse

    +
    @@ -823,7 +950,7 @@
  • interactionData - InteractionData + InteractionData @@ -880,11 +1007,11 @@

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:274 + src/pixi/display/DisplayObjectContainer.js:256

    @@ -896,6 +1023,7 @@

    Returns the Child at the specified index

    +
    @@ -913,7 +1041,8 @@
    - +

    The index to get the child from

    +
    @@ -964,11 +1093,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:115 + src/pixi/display/DisplayObject.js:180

    @@ -980,6 +1109,7 @@

    A callback that is used when the user clicks the mouse down over the sprite

    +
    @@ -991,7 +1121,7 @@
  • interactionData - InteractionData + InteractionData @@ -1048,11 +1178,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:141 + src/pixi/display/DisplayObject.js:206

    @@ -1064,6 +1194,7 @@

    A callback that is used when the users mouse leaves the displayObject

    +
    @@ -1075,7 +1206,7 @@
  • interactionData - InteractionData + InteractionData @@ -1132,11 +1263,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:135 + src/pixi/display/DisplayObject.js:200

    @@ -1148,6 +1279,7 @@

    A callback that is used when the users mouse rolls over the displayObject

    +
    @@ -1159,7 +1291,7 @@
  • interactionData - InteractionData + InteractionData @@ -1216,11 +1348,11 @@

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:121 + src/pixi/display/DisplayObject.js:186

    @@ -1233,6 +1365,7 @@

    A callback that is used when the user releases the mouse that was over the displayObject for this callback to be fired the mouse must have been pressed down over the displayObject

    +
    @@ -1244,7 +1377,7 @@ for this callback to be fired the mouse must have been pressed down over the dis
  • interactionData - InteractionData + InteractionData @@ -1301,11 +1434,11 @@ for this callback to be fired the mouse must have been pressed down over the dis

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:128 + src/pixi/display/DisplayObject.js:193

    @@ -1318,6 +1451,7 @@ for this callback to be fired the mouse must have been pressed down over the dis

    A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject for this callback to be fired, The touch must have started over the displayObject

    +
    @@ -1329,7 +1463,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • interactionData - InteractionData + InteractionData @@ -1348,6 +1482,96 @@ for this callback to be fired, The touch must have started over the displayObjec +
  • + + +
    +

    onTextureUpdate

    + + +
    + (
      + +
    • + + event + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/extras/TilingSprite.js:84 + +

    + + + + + +
    + +
    +

    When the texture is updated, this event will fire to update the frame

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + event + Object + + + + +
      + +
      + + +
    • + +
    +
    + + + + +
    @@ -1360,7 +1584,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • - DisplayObject + child
  • @@ -1386,11 +1610,11 @@ for this callback to be fired, The touch must have started over the displayObjec

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:291 + src/pixi/display/DisplayObjectContainer.js:274

    @@ -1402,6 +1626,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    Removes a child from the container.

    +
    @@ -1412,14 +1637,15 @@ for this callback to be fired, The touch must have started over the displayObjec
  • - DisplayObject + child DisplayObject
    - +

    The DisplayObject to remove

    +
    @@ -1435,7 +1661,7 @@ for this callback to be fired, The touch must have started over the displayObjec
  • -
    +

    setInteractive

    @@ -1455,6 +1681,8 @@ for this callback to be fired, The touch must have started over the displayObjec + deprecated + @@ -1470,16 +1698,18 @@ for this callback to be fired, The touch must have started over the displayObjec

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:193 + src/pixi/display/DisplayObject.js:247

    +

    Deprecated: Simply set the `interactive` property directly

    +
    @@ -1487,6 +1717,7 @@ for this callback to be fired, The touch must have started over the displayObjec

    [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default Instead of using this function you can now simply set the interactive property to true or false

    +
    @@ -1520,8 +1751,8 @@ Instead of using this function you can now simply set the interactive property t
    -
    -

    swapChildren

    +
    +

    setTexture

    @@ -1529,13 +1760,7 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject - -
  • - -
  • - - DisplayObject2 + texture
  • @@ -1560,12 +1785,15 @@ Instead of using this function you can now simply set the interactive property t
    -

    Inherited from - DisplayObjectContainer: + +

    + + Defined in + - src/pixi/display/DisplayObjectContainer.js:227 + src/pixi/extras/TilingSprite.js:68

    @@ -1576,7 +1804,8 @@ Instead of using this function you can now simply set the interactive property t
    -

    Swaps the depth of 2 displayObjects

    +

    Sets the texture of the tiling sprite

    +
    @@ -1587,7 +1816,101 @@ Instead of using this function you can now simply set the interactive property t
  • - DisplayObject + texture + Texture + + + + +
    +

    The PIXI texture that is displayed by the sprite

    + +
    + + +
  • + + +
    + + + + + +
    + + +
    +

    swapChildren

    + + +
    + (
      + +
    • + + child + +
    • + +
    • + + child2 + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + +

    Inherited from + DisplayObjectContainer: + + + + src/pixi/display/DisplayObjectContainer.js:207 + +

    + + + + + +
    + +
    +

    [NYI] Swaps the depth of 2 displayObjects

    + +
    + + +
    +

    Parameters:

    + +
    -

    A callback that is used when the user touch's over the displayObject

    +

    A callback that is used when the user touch's over the displayObject

    +
    @@ -1941,7 +2268,7 @@ for this callback to be fired, The touch must have started over the sprite

  • interactionData - InteractionData + InteractionData @@ -1971,6 +2298,50 @@ for this callback to be fired, The touch must have started over the sprite

    Properties

    +
    +

    _interactive

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:115 + +

    + + + + +
    + +
    +

    [read-only] Whether or not the object is interactive, do not toggle directly! use the interactive property

    + +
    + + + + + + +
    + +

    alpha

    Number @@ -1987,11 +2358,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:43 + src/pixi/display/DisplayObject.js:47

    @@ -2002,6 +2373,7 @@ for this callback to be fired, The touch must have started over the sprite

    The opacity of the object.

    +
    @@ -2028,11 +2400,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:98 + src/pixi/display/DisplayObject.js:72

    @@ -2043,6 +2415,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is used to indicate if the displayObject should display a mouse hand cursor on rollover

    +
    @@ -2055,7 +2428,7 @@ for this callback to be fired, The touch must have started over the sprite

    children

    - Array + Array @@ -2069,11 +2442,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObjectContainer: + DisplayObjectContainer: - src/pixi/display/DisplayObjectContainer.js:16 + src/pixi/display/DisplayObjectContainer.js:18

    @@ -2084,6 +2457,184 @@ for this callback to be fired, The touch must have started over the sprite

    [read-only] The of children of this container.

    + +
    + + + + + + +
    + + +
    +

    color

    + Array<> + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:145 + +

    + + + + +
    + +
    +

    [NYI] Unkown

    + +
    + + + + + + +
    + + +
    +

    dynamic

    + Boolean + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:154 + +

    + + + + +
    + +
    +

    [NYI] Holds whether or not this object is dynamic, for rendering optimization

    + +
    + + + + + + +
    + + +
    +

    filters

    + Array An array of filters + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:318 + +

    + + + + +
    + +
    +

    Sets the filters for the displayObject. +* IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer. +To remove filters simply set this property to 'null'

    + +
    + + + + + + +
    + + +
    +

    height

    + Number + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/extras/TilingSprite.js:35 + +

    + + + + +
    + +
    +

    The height of the tiling sprite

    +
    @@ -2096,7 +2647,7 @@ for this callback to be fired, The touch must have started over the sprite

    hitArea

    - Rectangle + Rectangle | Circle | Ellipse | Polygon @@ -2110,11 +2661,11 @@ for this callback to be fired, The touch must have started over the sprite

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:72 + src/pixi/display/DisplayObject.js:63

    @@ -2126,6 +2677,7 @@ for this callback to be fired, The touch must have started over the sprite

    This is the defined area that will pick up mouse / touch events. It is null by default. Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children)

    +
    @@ -2152,11 +2704,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:204 + src/pixi/display/DisplayObject.js:260

    @@ -2167,6 +2719,53 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Indicates if the sprite will have touch and mouse interactivity. It is false by default

    + +
    + + +

    Default: false

    + + + + + +
    + + +
    +

    localTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:135 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object locally

    +
    @@ -2179,7 +2778,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    mask

    - PIXI.Graphics + Graphics @@ -2193,11 +2792,11 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:222 + src/pixi/display/DisplayObject.js:280

    @@ -2210,6 +2809,7 @@ Setting it is a neat way of optimising the hitTest function that the interaction

    Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it. In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping. To remove a mask, set this property to null.

    +
    @@ -2236,11 +2836,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:58 + src/pixi/display/DisplayObject.js:88

    @@ -2251,6 +2851,7 @@ To remove a mask, set this property to null.

    [read-only] The display object container that contains this display object.

    +
    @@ -2277,11 +2878,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:29 + src/pixi/display/DisplayObject.js:31

    @@ -2292,6 +2893,7 @@ To remove a mask, set this property to null.

    The pivot point of the displayObject that it rotates around

    +
    @@ -2318,11 +2920,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:15 + src/pixi/display/DisplayObject.js:15

    @@ -2333,6 +2935,49 @@ To remove a mask, set this property to null.

    The coordinate of the object relative to the local coordinates of the parent.

    + +
    + + + + + + +
    + + +
    +

    renderable

    + Boolean + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:80 + +

    + + + + +
    + +
    +

    Can this object be rendered

    +
    @@ -2359,11 +3004,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:36 + src/pixi/display/DisplayObject.js:39

    @@ -2374,6 +3019,7 @@ To remove a mask, set this property to null.

    The rotation of the object in radians.

    +
    @@ -2400,11 +3046,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:22 + src/pixi/display/DisplayObject.js:23

    @@ -2415,6 +3061,7 @@ To remove a mask, set this property to null.

    The scale factor of the object.

    +
    @@ -2441,11 +3088,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:65 + src/pixi/display/DisplayObject.js:97

    @@ -2456,6 +3103,52 @@ To remove a mask, set this property to null.

    [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage.

    + +
    + + + + + + +
    + + +
    +

    texture

    + Texture + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/extras/TilingSprite.js:19 + +

    + + + + +
    + +
    +

    The texture that the sprite is using

    +
    @@ -2489,7 +3182,7 @@ To remove a mask, set this property to null.

    - src/pixi/extras/TilingSprite.js:28 + src/pixi/extras/TilingSprite.js:51

    @@ -2500,6 +3193,7 @@ To remove a mask, set this property to null.

    The offset position of the image that is being tiled

    +
    @@ -2533,7 +3227,7 @@ To remove a mask, set this property to null.

    - src/pixi/extras/TilingSprite.js:22 + src/pixi/extras/TilingSprite.js:43

    @@ -2544,6 +3238,7 @@ To remove a mask, set this property to null.

    The scaling of the image that is being tiled

    +
    @@ -2570,11 +3265,11 @@ To remove a mask, set this property to null.

    Inherited from - DisplayObject: + DisplayObject: - src/pixi/display/DisplayObject.js:50 + src/pixi/display/DisplayObject.js:55

    @@ -2585,6 +3280,138 @@ To remove a mask, set this property to null.

    The visibility of the object.

    + +
    + + + + + + +
    + + +
    +

    width

    + Number + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/extras/TilingSprite.js:27 + +

    + + + + +
    + +
    +

    The width of the tiling sprite

    + +
    + + + + + + +
    + + +
    +

    worldAlpha

    + Number + + + + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:106 + +

    + + + + +
    + +
    +

    [read-only] The multiplied alpha of the displayobject

    + +
    + + + + + + +
    + + +
    +

    worldTransform

    + Mat3 + + + + + private + + + + + + +
    + + +

    Inherited from + DisplayObject: + + + + src/pixi/display/DisplayObject.js:125 + +

    + + + + +
    + +
    +

    [read-only] Current transform of the object based on world (parent) factors

    +
    @@ -2610,13 +3437,13 @@ To remove a mask, set this property to null.

    - + - - - - - - + + + + + + diff --git a/docs/classes/WebGLBatch.html b/docs/classes/WebGLBatch.html index 39646be..28c727b 100644 --- a/docs/classes/WebGLBatch.html +++ b/docs/classes/WebGLBatch.html @@ -3,11 +3,11 @@ WebGLBatch - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -150,7 +174,7 @@ @@ -167,10 +191,107 @@

    A WebGLBatch Enables a group of sprites to be drawn using the same settings. -if a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch. All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster the webGL renderer will run.

    +if a group of sprites all have the same baseTexture and blendMode then they can be +grouped into a batch. All the sprites in a batch can then be drawn in one go by the +GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch +even if the batch only contains one sprite. Batching is handled automatically by the +webGL renderer. A good tip is: the smaller the number of batchs there are, the faster +the webGL renderer will run.

    +
    +
    +

    Constructor

    +
    +

    WebGLBatch

    + + +
    + (
      + +
    • + + gl + +
    • + +
    ) +
    + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:5 + +

    + + + + + +
    + +
    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + gl + WebGLContext + + + + +
      +

      an instance of the webGL context

      + +
      + + +
    • + +
    +
    + + + + + +
    + +
    +
      @@ -194,11 +315,60 @@ if a group of sprites all have the same baseTexture and blendMode then they can @@ -273,6 +527,319 @@ if a group of sprites all have the same baseTexture and blendMode then they can

      Methods

      +
      +

      addDisplayObjectAndChildren

      + + +
      + (
        + +
      • + + displayObject + +
      • + +
      ) +
      + + + + + + + + private + + + + + + + + + + +
      + + + +

      + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:430 + +

      + + + + + +
      + +
      +

      Adds a display object and children to the webgl context

      + +
      + + +
      +

      Parameters:

      + + +
      + + + + + +
      + + +
      +

      addFilterBlocks

      + + +
      + (
        + +
      • + + start + +
      • + +
      • + + end + +
      • + +
      ) +
      + + + + + + + + private + + + + + + + + + + +
      + + + +

      + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:376 + +

      + + + + + +
      + +
      +

      Adds filter blocks

      + +
      + + +
      +

      Parameters:

      + +
        + +
      • + + start + FilterBlock + + + + +
        + +
        + + +
      • + +
      • + + end + FilterBlock + + + + +
        + +
        + + +
      • + +
      +
      + + + + + +
      + + +
      +

      clean

      + + + () + + + + + + + + + + + + + + + + +
      + + + +

      + + Defined in + + + + + src/pixi/renderers/webgl/WebGLBatch.js:71 + +

      + + + + + +
      + +
      +

      Cleans the batch so that is can be returned to an object pool and reused

      + +
      + + + + + + +
      + + +
      +

      growBatch

      + + + () + + + + + + + + + + + + + + + + +
      + + + +

      + + Defined in + + + + + src/pixi/renderers/webgl/WebGLBatch.js:292 + +

      + + + + + +
      + +
      +

      Grows the size of the batch. As the elements in the batch cannot have a dynamic size this +function is used to increase the size of the batch. It also creates a little extra room so +that the batch does not need to be resized every time a sprite is added

      + +
      + + + + + + +
      + +

      init

      @@ -315,7 +882,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can - src/pixi/renderers/webgl/WebGLBatch.js:98 + src/pixi/renderers/webgl/WebGLBatch.js:105

      @@ -326,7 +893,8 @@ if a group of sprites all have the same baseTexture and blendMode then they can
      -

      inits the batch's texture and blend mode based if the supplied sprite

      +

      inits the batch's texture and blend mode based if the supplied sprite

      +
      @@ -344,7 +912,303 @@ if a group of sprites all have the same baseTexture and blendMode then they can
      -

      the first sprite to be added to the batch. Only sprites with the same base texture and blend mode will be allowed to be added to this batch

      +

      the first sprite to be added to the batch. Only sprites with + the same base texture and blend mode will be allowed to be added to this batch

      + +
      + + + + +
    +
    + + + + + +
    + + +
    +

    initStrip

    + + +
    + (
      + +
    • + + strip + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:974 + +

    + + + + + +
    + +
    +

    Initializes a strip to be rendered

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + strip + Strip + + + + +
      +

      The strip to initialize

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    initTilingSprite

    + + +
    + (
      + +
    • + + sprite + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:781 + +

    + + + + + +
    + +
    +

    Initializes a tiling sprite

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + sprite + TilingSprite + + + + +
      +

      The tiling sprite to initialize

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    insertAfter

    + + +
    + (
      + +
    • + + item + +
    • + +
    • + + displayObject + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:647 + +

    + + + + + +
    + +
    +

    Inserts a displayObject into the linked list

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + item + DisplayObject + + + + +
      + +
      + + +
    • + +
    • + + displayObject + DisplayObject + + + + +
      +

      The object to insert

      +
      @@ -408,7 +1272,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can - src/pixi/renderers/webgl/WebGLBatch.js:145 + src/pixi/renderers/webgl/WebGLBatch.js:153

      @@ -420,6 +1284,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can

      inserts a sprite after the specified sprite

      +
      @@ -438,6 +1303,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can

      the sprite to be added

      +
      @@ -453,6 +1319,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can

      the first sprite will be inserted after this sprite

      +
      @@ -516,7 +1383,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can - src/pixi/renderers/webgl/WebGLBatch.js:117 + src/pixi/renderers/webgl/WebGLBatch.js:125

      @@ -528,6 +1395,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can

      inserts a sprite before the specified sprite

      +
      @@ -546,6 +1414,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can

      the sprite to be added

      +
      @@ -561,6 +1430,139 @@ if a group of sprites all have the same baseTexture and blendMode then they can

      the first sprite will be inserted before this sprite

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    insertObject

    + + +
    + (
      + +
    • + + displayObject + +
    • + +
    • + + previousObject + +
    • + +
    • + + nextObject + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:509 + +

    + + + + + +
    + +
    +

    Inserts a displayObject into the linked list

    + +
    + + +
    +

    Parameters:

    + +
    -

    Refresh's all the data in the batch and sync's it with the webGL buffers

    +

    Refresh's all the data in the batch and sync's it with the webGL buffers

    +
    @@ -759,7 +1764,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can - src/pixi/renderers/webgl/WebGLBatch.js:175 + src/pixi/renderers/webgl/WebGLBatch.js:182

    @@ -771,6 +1776,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can

    removes a sprite from the batch

    +
    @@ -789,6 +1795,299 @@ if a group of sprites all have the same baseTexture and blendMode then they can

    the sprite to be removed

    + +
    + + +
  • + + +
    + + + + + +
    + + +
    +

    removeDisplayObjectAndChildren

    + + +
    + (
      + +
    • + + displayObject + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:487 + +

    + + + + + +
    + +
    +

    Removes a display object and children to the webgl context

    + +
    + + +
    +

    Parameters:

    + + +
    + + + + + +
    + + +
    +

    removeFilterBlocks

    + + +
    + (
      + +
    • + + start + +
    • + +
    • + + end + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:416 + +

    + + + + + +
    + +
    +

    Remove filter blocks

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + start + FilterBlock + + + + +
      + +
      + + +
    • + +
    • + + end + FilterBlock + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    removeObject

    + + +
    + (
      + +
    • + + displayObject + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:702 + +

    + + + + + +
    + +
    +

    Removes a displayObject from the linked list

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + displayObject + DisplayObject + + + + +
      +

      The object to remove

      +
      @@ -836,7 +2135,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can - src/pixi/renderers/webgl/WebGLBatch.js:513 + src/pixi/renderers/webgl/WebGLBatch.js:508

      @@ -848,6 +2147,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can

      Draws the batch to the frame buffer

      +
      @@ -855,6 +2155,718 @@ if a group of sprites all have the same baseTexture and blendMode then they can +
    + + +
    +

    render

    + + +
    + (
      + +
    • + + projection + +
    • + +
    ) +
    + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:55 + +

    + + + + + +
    + +
    +

    Renders the stage to its webgl view

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + projection + Object + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    renderSpecial

    + + +
    + (
      + +
    • + + renderable + +
    • + +
    • + + projection + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:251 + +

    + + + + + +
    + +
    +

    Renders a specific renderable

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + renderable + DisplayObject + + + + +
      + +
      + + +
    • + +
    • + + projection + Object + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    renderSpecific

    + + +
    + (
      + +
    • + + displayObject + +
    • + +
    • + + projection + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:91 + +

    + + + + + +
    + +
    +

    Renders a specific displayObject

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + displayObject + DisplayObject + + + + +
      + +
      + + +
    • + +
    • + + projection + Object + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    renderStrip

    + + +
    + (
      + +
    • + + strip + +
    • + +
    • + + projection + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:840 + +

    + + + + + +
    + +
    +

    Renders a Strip

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + strip + Strip + + + + +
      +

      The strip to render

      + +
      + + +
    • + +
    • + + projection + Object + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    renderTilingSprite

    + + +
    + (
      + +
    • + + sprite + +
    • + +
    • + + projectionMatrix + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:932 + +

    + + + + + +
    + +
    +

    Renders a TilingSprite

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + sprite + TilingSprite + + + + +
      +

      The tiling sprite to render

      + +
      + + +
    • + +
    • + + projectionMatrix + Object + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    restoreLostContext

    + + +
    + (
      + +
    • + + gl + +
    • + +
    ) +
    + + + + + + + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLBatch.js:90 + +

    + + + + + +
    + +
    +

    Recreates the buffers in the event of a context loss

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + gl + WebGLContext + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    setRenderable

    + + +
    + (
      + +
    • + + displayObject + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:33 + +

    + + + + + +
    + +
    +

    Add a display object to the webgl renderer

    + +
    + + +
    +

    Parameters:

    + + +
    + + + + +
    @@ -904,7 +2916,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can - src/pixi/renderers/webgl/WebGLBatch.js:218 + src/pixi/renderers/webgl/WebGLBatch.js:226

    @@ -916,6 +2928,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can

    Splits the batch into two with the specified sprite being the start of the new batch.

    +
    @@ -934,6 +2947,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can

    the sprite that indicates where the batch should be split

    +
    @@ -952,7 +2966,8 @@ if a group of sprites all have the same baseTexture and blendMode then they can WebGLBatch: - the new batch +

    the new batch

    +
    @@ -994,7 +3009,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can - src/pixi/renderers/webgl/WebGLBatch.js:401 + src/pixi/renderers/webgl/WebGLBatch.js:403

    @@ -1006,6 +3021,7 @@ if a group of sprites all have the same baseTexture and blendMode then they can

    Updates all the relevant geometry and uploads the data to the GPU

    +
    @@ -1013,6 +3029,96 @@ if a group of sprites all have the same baseTexture and blendMode then they can + + + +
    +

    updateTexture

    + + +
    + (
      + +
    • + + displayObject + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderGroup.js:334 + +

    + + + + + +
    + +
    +

    Updates a webgl texture

    + +
    + + +
    +

    Parameters:

    + + +
    + + + + +
    @@ -1033,13 +3139,13 @@ if a group of sprites all have the same baseTexture and blendMode then they can - + - - - - - - + + + + + + diff --git a/docs/classes/WebGLRenderer.html b/docs/classes/WebGLRenderer.html index 4b5ffef..c0a37b3 100644 --- a/docs/classes/WebGLRenderer.html +++ b/docs/classes/WebGLRenderer.html @@ -3,11 +3,11 @@ WebGLRenderer - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -150,7 +174,7 @@ @@ -166,8 +190,11 @@
    -

    the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer should be used for browsers support webGL. This Render works by automatically managing webGLBatchs. So no need for Sprite Batch's or Sprite Cloud's +

    the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer +should be used for browsers support webGL. This Render works by automatically managing webGLBatchs. +So no need for Sprite Batch's or Sprite Cloud's Dont forget to add the view to your DOM or you will not see anything :)

    +
    @@ -182,13 +209,13 @@ Dont forget to add the view to your DOM or you will not see anything :)

  • - width + width=0
  • - height + height=0
  • @@ -200,7 +227,13 @@ Dont forget to add the view to your DOM or you will not see anything :)

  • - transparent + transparent=false + +
  • + +
  • + + antialias=false
  • @@ -233,7 +266,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    - src/pixi/renderers/webgl/WebGLRenderer.js:11 + src/pixi/renderers/webgl/WebGLRenderer.js:11

    @@ -255,7 +288,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

  • - width + width=0 Number @@ -263,6 +296,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    the width of the canvas view

    +
    @@ -270,7 +304,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

  • - height + height=0 Number @@ -278,6 +312,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    the height of the canvas view

    +
    @@ -293,6 +328,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    the canvas to use as a view, optional

    +
    @@ -300,7 +336,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

  • - transparent + transparent=false Boolean @@ -308,6 +344,23 @@ Dont forget to add the view to your DOM or you will not see anything :)

    the transparency of the render view, default false

    + +
    + + +
  • + +
  • + + antialias=false + Boolean + + + + +
    +

    sets antialias (only applicable in chrome at the moment)

    +
    @@ -347,6 +400,36 @@ Dont forget to add the view to your DOM or you will not see anything :)

    @@ -377,6 +487,352 @@ Dont forget to add the view to your DOM or you will not see anything :)

    Methods

    +
    +

    destroyTexture

    + + +
    + (
      + +
    • + + texture + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderer.js:269 + +

    + + + + + +
    + +
    +

    Destroys a loaded webgl texture

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + texture + Texture + + + + +
      +

      The texture to update

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    getBatch

    + + + () + + + + + WebGLBatch + + + + + + + private + + + + + + static + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderer.js:104 + +

    + + + + + +
    + +
    +

    Gets a new WebGLBatch from the pool

    + +
    + + + + +
    +

    Returns:

    + +
    + + + WebGLBatch: + + +
    +
    + + + +
    + + +
    +

    handleContextLost

    + + +
    + (
      + +
    • + + event + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderer.js:319 + +

    + + + + + +
    + +
    +

    Handles a lost webgl context

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + event + Event + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    handleContextRestored

    + + +
    + (
      + +
    • + + event + +
    • + +
    ) +
    + + + + + + + + private + + + + + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderer.js:332 + +

    + + + + + +
    + +
    +

    Handles a restored webgl context

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + event + Event + + + + +
      + +
      + + +
    • + +
    +
    + + + + + +
    + +

    render

    @@ -419,7 +875,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    - src/pixi/renderers/webgl/WebGLRenderer.js:121 + src/pixi/renderers/webgl/WebGLRenderer.js:138

    @@ -431,6 +887,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    Renders the stage to its webGL view

    +
    @@ -448,7 +905,8 @@ Dont forget to add the view to your DOM or you will not see anything :)

    -

    the PIXI.Stage element to be rendered

    +

    the Stage element to be rendered

    +
    @@ -512,7 +970,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    - src/pixi/renderers/webgl/WebGLRenderer.js:263 + src/pixi/renderers/webgl/WebGLRenderer.js:288

    @@ -524,6 +982,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    resizes the webGL view to the specified width and height

    +
    @@ -542,6 +1001,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    the new width of the webGL view

    +
    @@ -557,6 +1017,7 @@ Dont forget to add the view to your DOM or you will not see anything :)

    the new height of the webGL view

    +
    @@ -569,6 +1030,251 @@ Dont forget to add the view to your DOM or you will not see anything :)

    +
    + + +
    +

    returnBatch

    + + +
    + (
      + +
    • + + batch + +
    • + +
    ) +
    + + + + + + + + private + + + + + + static + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderer.js:124 + +

    + + + + + +
    + +
    +

    Puts a batch back into the pool

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + batch + WebGLBatch + + + + +
      +

      The batch to return

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    updateTexture

    + + +
    + (
      + +
    • + + texture + +
    • + +
    ) +
    + + + + + + + + private + + + + + + static + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderer.js:225 + +

    + + + + + +
    + +
    +

    Updates a loaded webgl texture

    + +
    + + +
    +

    Parameters:

    + +
      + +
    • + + texture + Texture + + + + +
      +

      The texture to update

      + +
      + + +
    • + +
    +
    + + + + + +
    + + +
    +

    updateTextures

    + + + () + + + + + + + + private + + + + + + static + + + + + + +
    + + + +

    + + Defined in + + + + + src/pixi/renderers/webgl/WebGLRenderer.js:209 + +

    + + + + + +
    + +
    +

    Updates the textures loaded into this webgl renderer

    + +
    + + + + + +
    @@ -589,13 +1295,13 @@ Dont forget to add the view to your DOM or you will not see anything :)

  • - + - - - - - - + + + + + + diff --git a/docs/data.json b/docs/data.json index d450277..7f424e1 100644 --- a/docs/data.json +++ b/docs/data.json @@ -136,6 +136,56 @@ "fors": {}, "namespaces": {} }, + "src/pixi/filters/AbstractFilter.js": { + "name": "src/pixi/filters/AbstractFilter.js", + "modules": {}, + "classes": { + "AbstractFilter": 1 + }, + "fors": {}, + "namespaces": {} + }, + "src/pixi/filters/BlurFilter.js": { + "name": "src/pixi/filters/BlurFilter.js", + "modules": {}, + "classes": { + "BlurFilter": 1 + }, + "fors": {}, + "namespaces": {} + }, + "src/pixi/filters/BlurXFilter.js": { + "name": "src/pixi/filters/BlurXFilter.js", + "modules": {}, + "classes": {}, + "fors": {}, + "namespaces": {} + }, + "src/pixi/filters/BlurYFilter.js": { + "name": "src/pixi/filters/BlurYFilter.js", + "modules": {}, + "classes": {}, + "fors": {}, + "namespaces": {} + }, + "src/pixi/filters/ColorMatrixFilter.js": { + "name": "src/pixi/filters/ColorMatrixFilter.js", + "modules": {}, + "classes": { + "ColorMatrixFilter": 1 + }, + "fors": {}, + "namespaces": {} + }, + "src/pixi/filters/DisplacementFilter.js": { + "name": "src/pixi/filters/DisplacementFilter.js", + "modules": {}, + "classes": { + "DisplacementFilter": 1 + }, + "fors": {}, + "namespaces": {} + }, "src/pixi/filters/FilterBlock.js": { "name": "src/pixi/filters/FilterBlock.js", "modules": {}, @@ -143,8 +193,44 @@ "fors": {}, "namespaces": {} }, - "src/pixi/filters/MaskFilter.js": { - "name": "src/pixi/filters/MaskFilter.js", + "src/pixi/filters/GreyFilter.js": { + "name": "src/pixi/filters/GreyFilter.js", + "modules": {}, + "classes": { + "GreyFilter": 1 + }, + "fors": {}, + "namespaces": {} + }, + "src/pixi/filters/InvertFilter.js": { + "name": "src/pixi/filters/InvertFilter.js", + "modules": {}, + "classes": { + "InvertFilter": 1 + }, + "fors": {}, + "namespaces": {} + }, + "src/pixi/filters/PixelateFilter.js": { + "name": "src/pixi/filters/PixelateFilter.js", + "modules": {}, + "classes": { + "PixelateFilter": 1 + }, + "fors": {}, + "namespaces": {} + }, + "src/pixi/filters/SepiaFilter.js": { + "name": "src/pixi/filters/SepiaFilter.js", + "modules": {}, + "classes": { + "SepiaFilter": 1 + }, + "fors": {}, + "namespaces": {} + }, + "src/pixi/filters/SmartBlurFilter.js": { + "name": "src/pixi/filters/SmartBlurFilter.js", "modules": {}, "classes": {}, "fors": {}, @@ -229,6 +315,27 @@ "fors": {}, "namespaces": {} }, + "src/pixi/renderers/webgl/PixiShader.js": { + "name": "src/pixi/renderers/webgl/PixiShader.js", + "modules": {}, + "classes": {}, + "fors": {}, + "namespaces": {} + }, + "src/pixi/renderers/webgl/PrimitiveShader.js": { + "name": "src/pixi/renderers/webgl/PrimitiveShader.js", + "modules": {}, + "classes": {}, + "fors": {}, + "namespaces": {} + }, + "src/pixi/renderers/webgl/StripShader.js": { + "name": "src/pixi/renderers/webgl/StripShader.js", + "modules": {}, + "classes": {}, + "fors": {}, + "namespaces": {} + }, "src/pixi/renderers/webgl/WebGLBatch.js": { "name": "src/pixi/renderers/webgl/WebGLBatch.js", "modules": {}, @@ -236,6 +343,13 @@ "fors": {}, "namespaces": {} }, + "src/pixi/renderers/webgl/WebGLFilterManager.js": { + "name": "src/pixi/renderers/webgl/WebGLFilterManager.js", + "modules": {}, + "classes": {}, + "fors": {}, + "namespaces": {} + }, "src/pixi/renderers/webgl/WebGLGraphics.js": { "name": "src/pixi/renderers/webgl/WebGLGraphics.js", "modules": {}, @@ -325,14 +439,30 @@ "src/pixi/utils/EventTarget.js": { "name": "src/pixi/utils/EventTarget.js", "modules": {}, - "classes": {}, + "classes": { + "EventTarget": 1 + }, "fors": {}, "namespaces": {} }, + "src/pixi/utils/Polyk.js": { + "name": "src/pixi/utils/Polyk.js", + "modules": {}, + "classes": { + "PolyK._PointInTriangle": 1, + "PolyK._convex": 1 + }, + "fors": {}, + "namespaces": { + "PolyK": 1 + } + }, "src/pixi/utils/Utils.js": { "name": "src/pixi/utils/Utils.js", "modules": {}, - "classes": {}, + "classes": { + "PolyK.AjaxRequest": 1 + }, "fors": {}, "namespaces": {} }, @@ -340,8 +470,8 @@ "name": "src/pixi/InteractionManager.js", "modules": {}, "classes": { - "InteractionManager": 1, - "InteractionData": 1 + "PolyK.InteractionManager": 1, + "PolyK.InteractionData": 1 }, "fors": {}, "namespaces": {} @@ -388,6 +518,14 @@ "CustomRenderable": 1, "Spine": 1, "TilingSprite": 1, + "AbstractFilter": 1, + "BlurFilter": 1, + "ColorMatrixFilter": 1, + "DisplacementFilter": 1, + "GreyFilter": 1, + "InvertFilter": 1, + "PixelateFilter": 1, + "SepiaFilter": 1, "AssetLoader": 1, "BitmapFontLoader": 1, "ImageLoader": 1, @@ -403,14 +541,18 @@ "BaseTexture": 1, "RenderTexture": 1, "Texture": 1, - "InteractionManager": 1, - "InteractionData": 1 + "EventTarget": 1, + "PolyK._PointInTriangle": 1, + "PolyK._convex": 1, + "PolyK.AjaxRequest": 1, + "PolyK.InteractionManager": 1, + "PolyK.InteractionData": 1 }, "fors": {}, "namespaces": {}, "tag": "module", "file": "src/pixi/InteractionManager.js", - "line": 493 + "line": 646 } }, "classes": { @@ -425,6 +567,7 @@ "module": "PIXI", "file": "src/pixi/core/Circle.js", "line": 5, + "description": "The Circle object can be used to specify a hit area for displayobjects", "is_constructor": 1, "params": [ { @@ -455,26 +598,27 @@ "module": "PIXI", "file": "src/pixi/core/Ellipse.js", "line": 5, + "description": "The Ellipse object can be used to specify a hit area for displayobjects", "is_constructor": 1, "params": [ { "name": "x", - "description": "The X coord of the upper-left corner of the framing rectangle of this circle", + "description": "The X coord of the upper-left corner of the framing rectangle of this ellipse", "type": "Number" }, { "name": "y", - "description": "The Y coord of the upper-left corner of the framing rectangle of this circle", + "description": "The Y coord of the upper-left corner of the framing rectangle of this ellipse", "type": "Number" }, { "name": "width", - "description": "The overall height of this ellipse", + "description": "The overall width of this ellipse", "type": "Number" }, { "name": "height", - "description": "The overall width of this ellipse", + "description": "The overall height of this ellipse", "type": "Number" } ] @@ -520,8 +664,9 @@ "params": [ { "name": "points", - "description": "This cna be an array of Points or a flat array of numbers\n that will be interpreted as [x,y, x,y, ...]", - "type": "Array|Array" + "description": "This can be an array of Points that form the polygon,\n a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be\n all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the\n arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are\n Numbers.", + "type": "Array|Array|Point...|Number...", + "multiple": true } ] }, @@ -541,22 +686,22 @@ "params": [ { "name": "x", - "description": "position of the rectangle", + "description": "The X coord of the upper-left corner of the rectangle", "type": "Number" }, { "name": "y", - "description": "position of the rectangle", + "description": "The Y coord of the upper-left corner of the rectangle", "type": "Number" }, { "name": "width", - "description": "of the rectangle", + "description": "The overall width of this rectangle", "type": "Number" }, { "name": "height", - "description": "of the rectangle", + "description": "The overall height of this rectangle", "type": "Number" } ] @@ -572,7 +717,7 @@ "module": "PIXI", "file": "src/pixi/display/DisplayObject.js", "line": 5, - "description": "this is the base class for all objects that are rendered on the screen.", + "description": "The base class for all objects that are rendered on the screen.", "is_constructor": 1 }, "DisplayObjectContainer": { @@ -586,7 +731,7 @@ "module": "PIXI", "file": "src/pixi/display/DisplayObjectContainer.js", "line": 6, - "description": "A DisplayObjectContainer represents a collection of display objects. It is the base class of all display objects that act as a container for other objects.", + "description": "A DisplayObjectContainer represents a collection of display objects.\nIt is the base class of all display objects that act as a container for other objects.", "extends": "DisplayObject", "is_constructor": 1 }, @@ -608,7 +753,7 @@ { "name": "textures", "description": "an array of {Texture} objects that make up the animation", - "type": "Array" + "type": "Array" } ] }, @@ -623,12 +768,13 @@ "module": "PIXI", "file": "src/pixi/display/Sprite.js", "line": 10, + "description": "The SPrite object is the base for all textured objects that are rendered to the screen", "extends": "DisplayObjectContainer", "is_constructor": 1, "params": [ { "name": "texture", - "description": "", + "description": "The texture for this sprite", "type": "Texture" } ], @@ -651,13 +797,8 @@ "params": [ { "name": "backgroundColor", - "description": "the background color of the stage", + "description": "the background color of the stage, easiest way to pass this in is in hex format\n\t\tlike: 0xFFFFFF for white", "type": "Number" - }, - { - "name": "interactive", - "description": "enable / disable interaction (default is false)", - "type": "Boolean" } ] }, @@ -672,7 +813,7 @@ "module": "PIXI", "file": "src/pixi/extras/CustomRenderable.js", "line": 6, - "description": "Need to finalize this a bit more but works! Its in but will be working on this feature properly next..:)", + "description": "This object is one that will allow you to specify custom rendering functions based on render type", "extends": "DisplayObject", "is_constructor": 1 }, @@ -687,15 +828,18 @@ "module": "PIXI", "file": "src/pixi/loaders/SpineLoader.js", "line": 10, - "description": "The Spine loader is used to load in JSON spine data\nTo generate the data you need to use http://esotericsoftware.com/ and export the \"JSON\" format\nDue to a clash of names You will need to change the extension of the spine file from *.json to *.anim for it to load\nSee example 12 (http://www.goodboydigital.com/pixijs/examples/12/) to see a working example and check out the source\nYou will need to generate a sprite sheet to accompany the spine data \nWhen loaded this class will dispatch a \"loaded\" event", - "is_constructor": 1, + "description": "The Spine loader is used to load in JSON spine data\nTo generate the data you need to use http://esotericsoftware.com/ and export the \"JSON\" format\nDue to a clash of names You will need to change the extension of the spine file from *.json to *.anim for it to load\nSee example 12 (http://www.goodboydigital.com/pixijs/examples/12/) to see a working example and check out the source\nYou will need to generate a sprite sheet to accompany the spine data\nWhen loaded this class will dispatch a \"loaded\" event", "extends": "DisplayObjectContainer", + "is_constructor": 1, "params": [ { "name": "url", - "description": "the url of the spine anim file to be used", + "description": "The url of the spine anim file to be used", "type": "String" } + ], + "uses": [ + "EventTarget" ] }, "TilingSprite": { @@ -730,6 +874,135 @@ } ] }, + "AbstractFilter": { + "name": "AbstractFilter", + "shortname": "AbstractFilter", + "classitems": [], + "plugins": [], + "extensions": [], + "plugin_for": [], + "extension_for": [], + "module": "PIXI", + "file": "src/pixi/filters/AbstractFilter.js", + "line": 6, + "description": "This is the base class for creating a pixi.js filter. Currently only webGL supports filters.\nIf you want to make a custom filter this should be your base class.", + "is_constructor": 1, + "params": [ + { + "name": "fragmentSrc", + "description": "" + }, + { + "name": "unifroms", + "description": "" + } + ] + }, + "BlurFilter": { + "name": "BlurFilter", + "shortname": "BlurFilter", + "classitems": [], + "plugins": [], + "extensions": [], + "plugin_for": [], + "extension_for": [], + "module": "PIXI", + "file": "src/pixi/filters/BlurFilter.js", + "line": 6, + "description": "The BlurFilter applies a Gaussian blur to an object. \n The strength of the blur can be set for x- and y-axis separately (always relative to the stage).", + "contructor": "" + }, + "ColorMatrixFilter": { + "name": "ColorMatrixFilter", + "shortname": "ColorMatrixFilter", + "classitems": [], + "plugins": [], + "extensions": [], + "plugin_for": [], + "extension_for": [], + "module": "PIXI", + "file": "src/pixi/filters/ColorMatrixFilter.js", + "line": 5, + "description": "The ColorMatrixFilter class lets you apply a 4x4 matrix transformation on the RGBA \n color and alpha values of every pixel on your displayObject to produce a result \n with a new set of RGBA color and alpha values. Its pretty powerful!", + "contructor": "" + }, + "DisplacementFilter": { + "name": "DisplacementFilter", + "shortname": "DisplacementFilter", + "classitems": [], + "plugins": [], + "extensions": [], + "plugin_for": [], + "extension_for": [], + "module": "PIXI", + "file": "src/pixi/filters/DisplacementFilter.js", + "line": 6, + "description": "The DisplacementFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object. \n You can use this filter to apply all manor of crazy warping effects\n Currently the r property of the texture is used offset the x and the g propery of the texture is used to offset the y.", + "contructor": "", + "params": [ + { + "name": "texture", + "description": "The texture used for the displacemtent map * must be power of 2 texture at the moment", + "type": "Texture" + } + ] + }, + "GreyFilter": { + "name": "GreyFilter", + "shortname": "GreyFilter", + "classitems": [], + "plugins": [], + "extensions": [], + "plugin_for": [], + "extension_for": [], + "module": "PIXI", + "file": "src/pixi/filters/GreyFilter.js", + "line": 6, + "description": "This turns your displayObjects to black and white.", + "contructor": "" + }, + "InvertFilter": { + "name": "InvertFilter", + "shortname": "InvertFilter", + "classitems": [], + "plugins": [], + "extensions": [], + "plugin_for": [], + "extension_for": [], + "module": "PIXI", + "file": "src/pixi/filters/InvertFilter.js", + "line": 5, + "description": "This inverts your displayObjects colors.", + "contructor": "" + }, + "PixelateFilter": { + "name": "PixelateFilter", + "shortname": "PixelateFilter", + "classitems": [], + "plugins": [], + "extensions": [], + "plugin_for": [], + "extension_for": [], + "module": "PIXI", + "file": "src/pixi/filters/PixelateFilter.js", + "line": 5, + "description": "This filter applies a pixlate effect making display objects appear \"blocky\"", + "contructor": "" + }, + "SepiaFilter": { + "name": "SepiaFilter", + "shortname": "SepiaFilter", + "classitems": [], + "plugins": [], + "extensions": [], + "plugin_for": [], + "extension_for": [], + "module": "PIXI", + "file": "src/pixi/filters/SepiaFilter.js", + "line": 7, + "description": "This applies a sepia effect to your displayObjects.", + "contructor": "" + }, "AssetLoader": { "name": "AssetLoader", "shortname": "AssetLoader", @@ -741,14 +1014,21 @@ "module": "PIXI", "file": "src/pixi/loaders/AssetLoader.js", "line": 5, - "description": "A Class that loads a bunch of images / sprite sheet / bitmap font files. Once the assets have been loaded they are added to the PIXI Texture cache and can be accessed easily through PIXI.Texture.fromImage() and PIXI.Sprite.fromImage()\nWhen all items have been loaded this class will dispatch a \"onLoaded\" event\nAs each individual item is loaded this class will dispatch a \"onProgress\" event", + "description": "A Class that loads a bunch of images / sprite sheet / bitmap font files. Once the\nassets have been loaded they are added to the PIXI Texture cache and can be accessed\neasily through PIXI.Texture.fromImage() and PIXI.Sprite.fromImage()\nWhen all items have been loaded this class will dispatch a \"onLoaded\" event\nAs each individual item is loaded this class will dispatch a \"onProgress\" event", "is_constructor": 1, - "extends": "EventTarget", + "uses": [ + "EventTarget" + ], "params": [ { "name": "assetURLs", - "description": "an array of image/sprite sheet urls that you would like loaded supported. Supported image formats include \"jpeg\", \"jpg\", \"png\", \"gif\". Supported sprite sheet data formats only include \"JSON\" at this time. Supported bitmap font data formats include \"xml\" and \"fnt\".", - "type": "Array" + "description": "an array of image/sprite sheet urls that you would like loaded\n supported. Supported image formats include \"jpeg\", \"jpg\", \"png\", \"gif\". Supported\n sprite sheet data formats only include \"JSON\" at this time. Supported bitmap font\n data formats include \"xml\" and \"fnt\".", + "type": "Array" + }, + { + "name": "crossorigin", + "description": "Whether requests should be treated as crossorigin", + "type": "Boolean" } ] }, @@ -764,17 +1044,19 @@ "file": "src/pixi/loaders/BitmapFontLoader.js", "line": 5, "description": "The xml loader is used to load in XML bitmap font data (\"xml\" or \"fnt\")\nTo generate the data you can use http://www.angelcode.com/products/bmfont/\nThis loader will also load the image file as the data.\nWhen loaded this class will dispatch a \"loaded\" event", - "extends": "EventTarget", + "uses": [ + "EventTarget" + ], "is_constructor": 1, "params": [ { "name": "url", - "description": "the url of the sprite sheet JSON file", + "description": "The url of the sprite sheet JSON file", "type": "String" }, { "name": "crossorigin", - "description": "", + "description": "Whether requests should be treated as crossorigin", "type": "Boolean" } ] @@ -791,7 +1073,9 @@ "file": "src/pixi/loaders/ImageLoader.js", "line": 5, "description": "The image loader class is responsible for loading images file formats (\"jpeg\", \"jpg\", \"png\" and \"gif\")\nOnce the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId()\nWhen loaded this class will dispatch a 'loaded' event", - "extends": "EventTarget", + "uses": [ + "EventTarget" + ], "is_constructor": 1, "params": [ { @@ -801,7 +1085,7 @@ }, { "name": "crossorigin", - "description": "", + "description": "Whether requests should be treated as crossorigin", "type": "Boolean" } ] @@ -818,17 +1102,19 @@ "file": "src/pixi/loaders/JsonLoader.js", "line": 5, "description": "The json file loader is used to load in JSON data and parsing it\nWhen loaded this class will dispatch a \"loaded\" event\nIf load failed this class will dispatch a \"error\" event", - "extends": "EventTarget", + "uses": [ + "EventTarget" + ], "is_constructor": 1, "params": [ { "name": "url", - "description": "the url of the JSON file", + "description": "The url of the JSON file", "type": "String" }, { "name": "crossorigin", - "description": "", + "description": "Whether requests should be treated as crossorigin", "type": "Boolean" } ] @@ -845,17 +1131,19 @@ "file": "src/pixi/loaders/SpriteSheetLoader.js", "line": 5, "description": "The sprite sheet loader is used to load in JSON sprite sheet data\nTo generate the data you can use http://www.codeandweb.com/texturepacker and publish the \"JSON\" format\nThere is a free version so thats nice, although the paid version is great value for money.\nIt is highly recommended to use Sprite sheets (also know as texture atlas\") as it means sprite\"s can be batched and drawn together for highly increased rendering speed.\nOnce the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId()\nThis loader will also load the image file that the Spritesheet points to as well as the data.\nWhen loaded this class will dispatch a \"loaded\" event", - "extends": "EventTarget", + "uses": [ + "EventTarget" + ], "is_constructor": 1, "params": [ { "name": "url", - "description": "the url of the sprite sheet JSON file", + "description": "The url of the sprite sheet JSON file", "type": "String" }, { "name": "crossorigin", - "description": "", + "description": "Whether requests should be treated as crossorigin", "type": "Boolean" } ] @@ -871,7 +1159,7 @@ "module": "PIXI", "file": "src/pixi/primitives/Graphics.js", "line": 6, - "description": "The Graphics class contains a set of methods that you can use to create primitive shapes and lines. \nIt is important to know that with the webGL renderer only simple polys can be filled at this stage\nComplex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png", + "description": "The Graphics class contains a set of methods that you can use to create primitive shapes and lines.\nIt is important to know that with the webGL renderer only simple polys can be filled at this stage\nComplex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png", "extends": "DisplayObjectContainer", "is_constructor": 1 }, @@ -885,7 +1173,7 @@ "extension_for": [], "module": "PIXI", "file": "src/pixi/renderers/webgl/WebGLGraphics.js", - "line": 7, + "line": 5, "description": "A set of functions used by the webGL renderer to draw the primitive graphics data" }, "CanvasRenderer": { @@ -903,12 +1191,12 @@ "is_constructor": 1, "params": [ { - "name": "width", + "name": "width=0", "description": "the width of the canvas view", "type": "Number" }, { - "name": "height", + "name": "height=0", "description": "the height of the canvas view", "type": "Number" }, @@ -918,12 +1206,11 @@ "type": "Canvas" }, { - "name": "transparent", + "name": "transparent=false", "description": "the transparency of the render view, default false", "type": "Boolean" } - ], - "default": "false" + ] }, "WebGLBatch": { "name": "WebGLBatch", @@ -935,18 +1222,17 @@ "extension_for": [], "module": "PIXI", "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", - "line": 8, - "description": "A WebGLBatch Enables a group of sprites to be drawn using the same settings.\nif a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch. All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster the webGL renderer will run.", + "line": 5, + "description": "A WebGLBatch Enables a group of sprites to be drawn using the same settings.\nif a group of sprites all have the same baseTexture and blendMode then they can be\ngrouped into a batch. All the sprites in a batch can then be drawn in one go by the\nGPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch\neven if the batch only contains one sprite. Batching is handled automatically by the\nwebGL renderer. A good tip is: the smaller the number of batchs there are, the faster\nthe webGL renderer will run.", + "is_constructor": 1, "params": [ { - "name": "an", - "description": "instance of the webGL context" + "name": "gl", + "description": "an instance of the webGL context", + "type": "WebGLContext" } ], - "return": { - "description": "WebGLBatch {@link PIXI.renderers.WebGLBatch}", - "type": "PIXI.renderers.WebGLBatch" - } + "contructor": "" }, "WebGLRenderer": { "name": "WebGLRenderer", @@ -959,16 +1245,16 @@ "module": "PIXI", "file": "src/pixi/renderers/webgl/WebGLRenderer.js", "line": 11, - "description": "the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer should be used for browsers support webGL. This Render works by automatically managing webGLBatchs. So no need for Sprite Batch's or Sprite Cloud's\nDont forget to add the view to your DOM or you will not see anything :)", + "description": "the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer\nshould be used for browsers support webGL. This Render works by automatically managing webGLBatchs.\nSo no need for Sprite Batch's or Sprite Cloud's\nDont forget to add the view to your DOM or you will not see anything :)", "is_constructor": 1, "params": [ { - "name": "width", + "name": "width=0", "description": "the width of the canvas view", "type": "Number" }, { - "name": "height", + "name": "height=0", "description": "the height of the canvas view", "type": "Number" }, @@ -978,12 +1264,16 @@ "type": "Canvas" }, { - "name": "transparent", + "name": "transparent=false", "description": "the transparency of the render view, default false", "type": "Boolean" + }, + { + "name": "antialias=false", + "description": "sets antialias (only applicable in chrome at the moment)", + "type": "Boolean" } - ], - "default": "false" + ] }, "BitmapText": { "name": "BitmapText", @@ -996,7 +1286,7 @@ "module": "PIXI", "file": "src/pixi/text/BitmapText.js", "line": 5, - "description": "A Text Object will create a line(s) of text using bitmap font. To split a line you can use \"\\n\", \"\\r\" or \"\\r\\n\"\nYou can generate the fnt files using \nhttp://www.angelcode.com/products/bmfont/ for windows or\nhttp://www.bmglyph.com/ for mac.", + "description": "A Text Object will create a line(s) of text using bitmap font. To split a line you can use \"\\n\", \"\\r\" or \"\\r\\n\"\nYou can generate the fnt files using\nhttp://www.angelcode.com/products/bmfont/ for windows or\nhttp://www.bmglyph.com/ for mac.", "extends": "DisplayObjectContainer", "is_constructor": 1, "params": [ @@ -1115,7 +1405,9 @@ "file": "src/pixi/textures/BaseTexture.js", "line": 9, "description": "A texture stores the information that represents an image. All textures have a base texture", - "extends": "EventTarget", + "uses": [ + "EventTarget" + ], "is_constructor": 1, "params": [ { @@ -1142,12 +1434,12 @@ "params": [ { "name": "width", - "description": "", + "description": "The width of the render texture", "type": "Number" }, { "name": "height", - "description": "", + "description": "The height of the render texture", "type": "Number" } ] @@ -1163,24 +1455,98 @@ "module": "PIXI", "file": "src/pixi/textures/Texture.js", "line": 8, - "description": "A texture stores the information that represents an image or part of an image. It cannot be added to the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used", - "extends": "EventTarget", + "description": "A texture stores the information that represents an image or part of an image. It cannot be added\nto the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used", + "uses": [ + "EventTarget" + ], "is_constructor": 1, "params": [ { "name": "baseTexture", - "description": "", + "description": "The base texture source to create the texture from", "type": "BaseTexture" }, { - "name": "frmae", - "description": "", + "name": "frame", + "description": "The rectangle frame of the texture to show", "type": "Rectangle" } ] }, - "InteractionManager": { - "name": "InteractionManager", + "EventTarget": { + "name": "EventTarget", + "shortname": "EventTarget", + "classitems": [], + "plugins": [], + "extensions": [], + "plugin_for": [], + "extension_for": [ + "Spine", + "AssetLoader", + "BitmapFontLoader", + "ImageLoader", + "JsonLoader", + "SpriteSheetLoader", + "BaseTexture", + "Texture" + ], + "module": "PIXI", + "file": "src/pixi/utils/EventTarget.js", + "line": 6, + "description": "Adds event emitter functionality to a class", + "example": [ + "\n\t\tfunction MyEmitter() {\n\t\t\tPIXI.EventTarget.call(this); //mixes in event target stuff\n\t\t}\n\n\t\tvar em = new MyEmitter();\n\t\tem.emit({ type: 'eventName', data: 'some data' });" + ] + }, + "PolyK._PointInTriangle": { + "name": "PolyK._PointInTriangle", + "shortname": "PolyK._PointInTriangle", + "classitems": [], + "plugins": [], + "extensions": [], + "plugin_for": [], + "extension_for": [], + "module": "PIXI", + "namespace": "PolyK", + "file": "src/pixi/utils/Polyk.js", + "line": 109, + "description": "Checks if a point is within a triangle", + "access": "private", + "tagname": "" + }, + "PolyK._convex": { + "name": "PolyK._convex", + "shortname": "PolyK._convex", + "classitems": [], + "plugins": [], + "extensions": [], + "plugin_for": [], + "extension_for": [], + "module": "PIXI", + "namespace": "PolyK", + "file": "src/pixi/utils/Polyk.js", + "line": 139, + "description": "Checks if a shape is convex", + "access": "private", + "tagname": "" + }, + "PolyK.AjaxRequest": { + "name": "PolyK.AjaxRequest", + "shortname": "AjaxRequest", + "classitems": [], + "plugins": [], + "extensions": [], + "plugin_for": [], + "extension_for": [], + "module": "PIXI", + "namespace": "PolyK", + "file": "src/pixi/utils/Utils.js", + "line": 81, + "description": "A wrapper for ajax requests to be handled cross browser", + "is_constructor": 1 + }, + "PolyK.InteractionManager": { + "name": "PolyK.InteractionManager", "shortname": "InteractionManager", "classitems": [], "plugins": [], @@ -1188,21 +1554,21 @@ "plugin_for": [], "extension_for": [], "module": "PIXI", + "namespace": "PolyK", "file": "src/pixi/InteractionManager.js", - "line": 7, + "line": 5, "description": "The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive\nThis manager also supports multitouch.", "is_constructor": 1, "params": [ { "name": "stage", - "description": "", + "description": "The stage to handle interactions", "type": "Stage" } - ], - "type": "Stage" + ] }, - "InteractionData": { - "name": "InteractionData", + "PolyK.InteractionData": { + "name": "PolyK.InteractionData", "shortname": "InteractionData", "classitems": [], "plugins": [], @@ -1210,8 +1576,10 @@ "plugin_for": [], "extension_for": [], "module": "PIXI", + "namespace": "PolyK", "file": "src/pixi/InteractionManager.js", - "line": 493, + "line": 646, + "description": "Holds all information related to an Interaction event", "is_constructor": 1 } }, @@ -1224,7 +1592,7 @@ }, { "file": "src/pixi/core/Circle.js", - "line": 14, + "line": 16, "itemtype": "property", "name": "x", "type": "Number", @@ -1233,7 +1601,7 @@ }, { "file": "src/pixi/core/Circle.js", - "line": 21, + "line": 23, "itemtype": "property", "name": "y", "type": "Number", @@ -1242,7 +1610,7 @@ }, { "file": "src/pixi/core/Circle.js", - "line": 28, + "line": 30, "itemtype": "property", "name": "radius", "type": "Number", @@ -1251,17 +1619,20 @@ }, { "file": "src/pixi/core/Circle.js", - "line": 36, + "line": 38, + "description": "Creates a clone of this Circle instance", "itemtype": "method", "name": "clone", "return": { - "description": "a copy of the polygon" + "description": "a copy of the polygon", + "type": "Circle" }, "class": "Circle" }, { "file": "src/pixi/core/Circle.js", - "line": 45, + "line": 49, + "description": "Checks if the x, and y coords passed to this function are contained within this circle", "itemtype": "method", "name": "contains", "params": [ @@ -1277,7 +1648,8 @@ } ], "return": { - "description": "if the x/y coords are within this polygon" + "description": "if the x/y coords are within this polygon", + "type": "Boolean" }, "class": "Circle" }, @@ -1289,7 +1661,7 @@ }, { "file": "src/pixi/core/Ellipse.js", - "line": 15, + "line": 17, "itemtype": "property", "name": "x", "type": "Number", @@ -1298,7 +1670,7 @@ }, { "file": "src/pixi/core/Ellipse.js", - "line": 22, + "line": 24, "itemtype": "property", "name": "y", "type": "Number", @@ -1307,7 +1679,7 @@ }, { "file": "src/pixi/core/Ellipse.js", - "line": 29, + "line": 31, "itemtype": "property", "name": "width", "type": "Number", @@ -1316,7 +1688,7 @@ }, { "file": "src/pixi/core/Ellipse.js", - "line": 36, + "line": 38, "itemtype": "property", "name": "height", "type": "Number", @@ -1325,17 +1697,20 @@ }, { "file": "src/pixi/core/Ellipse.js", - "line": 44, + "line": 46, + "description": "Creates a clone of this Ellipse instance", "itemtype": "method", "name": "clone", "return": { - "description": "a copy of the polygon" + "description": "a copy of the ellipse", + "type": "Ellipse" }, "class": "Ellipse" }, { "file": "src/pixi/core/Ellipse.js", - "line": 53, + "line": 57, + "description": "Checks if the x, and y coords passed to this function are contained within this ellipse", "itemtype": "method", "name": "contains", "params": [ @@ -1351,7 +1726,8 @@ } ], "return": { - "description": "if the x/y coords are within this polygon" + "description": "if the x/y coords are within this ellipse", + "type": "Boolean" }, "class": "Ellipse" }, @@ -1363,7 +1739,7 @@ }, { "file": "src/pixi/core/Point.js", - "line": 14, + "line": 15, "itemtype": "property", "name": "x", "type": "Number", @@ -1372,7 +1748,7 @@ }, { "file": "src/pixi/core/Point.js", - "line": 21, + "line": 22, "itemtype": "property", "name": "y", "type": "Number", @@ -1381,11 +1757,13 @@ }, { "file": "src/pixi/core/Point.js", - "line": 29, + "line": 30, + "description": "Creates a clone of this point", "itemtype": "method", "name": "clone", "return": { - "description": "a copy of the point" + "description": "a copy of the point", + "type": "Point" }, "class": "Point" }, @@ -1397,17 +1775,20 @@ }, { "file": "src/pixi/core/Polygon.js", - "line": 28, + "line": 35, + "description": "Creates a clone of this polygon", "itemtype": "method", "name": "clone", "return": { - "description": "a copy of the polygon" + "description": "a copy of the polygon", + "type": "Polygon" }, "class": "Polygon" }, { "file": "src/pixi/core/Polygon.js", - "line": 42, + "line": 51, + "description": "Checks if the x, and y coords passed to this function are contained within this polygon", "itemtype": "method", "name": "contains", "params": [ @@ -1423,7 +1804,8 @@ } ], "return": { - "description": "if the x/y coords are within this polygon" + "description": "if the x/y coords are within this polygon", + "type": "Boolean" }, "class": "Polygon" }, @@ -1435,7 +1817,7 @@ }, { "file": "src/pixi/core/Rectangle.js", - "line": 16, + "line": 17, "itemtype": "property", "name": "x", "type": "Number", @@ -1444,7 +1826,7 @@ }, { "file": "src/pixi/core/Rectangle.js", - "line": 23, + "line": 24, "itemtype": "property", "name": "y", "type": "Number", @@ -1453,7 +1835,7 @@ }, { "file": "src/pixi/core/Rectangle.js", - "line": 30, + "line": 31, "itemtype": "property", "name": "width", "type": "Number", @@ -1462,7 +1844,7 @@ }, { "file": "src/pixi/core/Rectangle.js", - "line": 37, + "line": 38, "itemtype": "property", "name": "height", "type": "Number", @@ -1471,17 +1853,20 @@ }, { "file": "src/pixi/core/Rectangle.js", - "line": 45, + "line": 46, + "description": "Creates a clone of this Rectangle", "itemtype": "method", "name": "clone", "return": { - "description": "a copy of the rectangle" + "description": "a copy of the rectangle", + "type": "Rectangle" }, "class": "Rectangle" }, { "file": "src/pixi/core/Rectangle.js", - "line": 54, + "line": 57, + "description": "Checks if the x, and y coords passed to this function are contained within this Rectangle", "itemtype": "method", "name": "contains", "params": [ @@ -1497,7 +1882,8 @@ } ], "return": { - "description": "if the x/y coords are within this polygon" + "description": "if the x/y coords are within this Rectangle", + "type": "Boolean" }, "class": "Rectangle" }, @@ -1518,7 +1904,7 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 22, + "line": 23, "description": "The scale factor of the object.", "itemtype": "property", "name": "scale", @@ -1527,7 +1913,7 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 29, + "line": 31, "description": "The pivot point of the displayObject that it rotates around", "itemtype": "property", "name": "pivot", @@ -1536,7 +1922,7 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 36, + "line": 39, "description": "The rotation of the object in radians.", "itemtype": "property", "name": "rotation", @@ -1545,7 +1931,7 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 43, + "line": 47, "description": "The opacity of the object.", "itemtype": "property", "name": "alpha", @@ -1554,7 +1940,7 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 50, + "line": 55, "description": "The visibility of the object.", "itemtype": "property", "name": "visible", @@ -1563,34 +1949,16 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 58, - "description": "[read-only] The display object container that contains this display object.", + "line": 63, + "description": "This is the defined area that will pick up mouse / touch events. It is null by default.\nSetting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children)", "itemtype": "property", - "name": "parent", - "type": "DisplayObjectContainer", - "class": "DisplayObject" - }, - { - "file": "src/pixi/display/DisplayObject.js", - "line": 65, - "description": "[read-only] The stage the display object is connected to, or undefined if it is not connected to the stage.", - "itemtype": "property", - "name": "stage", - "type": "Stage", + "name": "hitArea", + "type": "Rectangle|Circle|Ellipse|Polygon", "class": "DisplayObject" }, { "file": "src/pixi/display/DisplayObject.js", "line": 72, - "description": "This is the defined area that will pick up mouse / touch events. It is null by default.\nSetting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children)", - "itemtype": "property", - "name": "hitArea", - "type": "Rectangle", - "class": "DisplayObject" - }, - { - "file": "src/pixi/display/DisplayObject.js", - "line": 98, "description": "This is used to indicate if the displayObject should display a mouse hand cursor on rollover", "itemtype": "property", "name": "buttonMode", @@ -1599,7 +1967,104 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 109, + "line": 80, + "description": "Can this object be rendered", + "itemtype": "property", + "name": "renderable", + "type": "Boolean", + "class": "DisplayObject" + }, + { + "file": "src/pixi/display/DisplayObject.js", + "line": 88, + "description": "[read-only] The display object container that contains this display object.", + "itemtype": "property", + "name": "parent", + "type": "DisplayObjectContainer", + "readonly": "", + "class": "DisplayObject" + }, + { + "file": "src/pixi/display/DisplayObject.js", + "line": 97, + "description": "[read-only] The stage the display object is connected to, or undefined if it is not connected to the stage.", + "itemtype": "property", + "name": "stage", + "type": "Stage", + "readonly": "", + "class": "DisplayObject" + }, + { + "file": "src/pixi/display/DisplayObject.js", + "line": 106, + "description": "[read-only] The multiplied alpha of the displayobject", + "itemtype": "property", + "name": "worldAlpha", + "type": "Number", + "readonly": "", + "class": "DisplayObject" + }, + { + "file": "src/pixi/display/DisplayObject.js", + "line": 115, + "description": "[read-only] Whether or not the object is interactive, do not toggle directly! use the `interactive` property", + "itemtype": "property", + "name": "_interactive", + "type": "Boolean", + "readonly": "", + "access": "private", + "tagname": "", + "class": "DisplayObject" + }, + { + "file": "src/pixi/display/DisplayObject.js", + "line": 125, + "description": "[read-only] Current transform of the object based on world (parent) factors", + "itemtype": "property", + "name": "worldTransform", + "type": "Mat3", + "readonly": "", + "access": "private", + "tagname": "", + "class": "DisplayObject" + }, + { + "file": "src/pixi/display/DisplayObject.js", + "line": 135, + "description": "[read-only] Current transform of the object locally", + "itemtype": "property", + "name": "localTransform", + "type": "Mat3", + "readonly": "", + "access": "private", + "tagname": "", + "class": "DisplayObject" + }, + { + "file": "src/pixi/display/DisplayObject.js", + "line": 145, + "description": "[NYI] Unkown", + "itemtype": "property", + "name": "color", + "type": "Array<>", + "access": "private", + "tagname": "", + "class": "DisplayObject" + }, + { + "file": "src/pixi/display/DisplayObject.js", + "line": 154, + "description": "[NYI] Holds whether or not this object is dynamic, for rendering optimization", + "itemtype": "property", + "name": "dynamic", + "type": "Boolean", + "access": "private", + "tagname": "", + "class": "DisplayObject" + }, + { + "file": "src/pixi/display/DisplayObject.js", + "line": 174, "description": "A callback that is used when the users clicks on the displayObject with their mouse", "itemtype": "method", "name": "click", @@ -1614,7 +2079,7 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 115, + "line": 180, "description": "A callback that is used when the user clicks the mouse down over the sprite", "itemtype": "method", "name": "mousedown", @@ -1629,7 +2094,7 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 121, + "line": 186, "description": "A callback that is used when the user releases the mouse that was over the displayObject\nfor this callback to be fired the mouse must have been pressed down over the displayObject", "itemtype": "method", "name": "mouseup", @@ -1644,7 +2109,7 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 128, + "line": 193, "description": "A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject\nfor this callback to be fired, The touch must have started over the displayObject", "itemtype": "method", "name": "mouseupoutside", @@ -1659,7 +2124,7 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 135, + "line": 200, "description": "A callback that is used when the users mouse rolls over the displayObject", "itemtype": "method", "name": "mouseover", @@ -1674,7 +2139,7 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 141, + "line": 206, "description": "A callback that is used when the users mouse leaves the displayObject", "itemtype": "method", "name": "mouseout", @@ -1689,7 +2154,7 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 152, + "line": 217, "description": "A callback that is used when the users taps on the sprite with their finger\nbasically a touch version of click", "itemtype": "method", "name": "tap", @@ -1704,7 +2169,7 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 159, + "line": 224, "description": "A callback that is used when the user touch's over the displayObject", "itemtype": "method", "name": "touchstart", @@ -1719,7 +2184,7 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 165, + "line": 230, "description": "A callback that is used when the user releases a touch over the displayObject", "itemtype": "method", "name": "touchend", @@ -1734,7 +2199,7 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 171, + "line": 236, "description": "A callback that is used when the user releases the touch that was over the displayObject\nfor this callback to be fired, The touch must have started over the sprite", "itemtype": "method", "name": "touchendoutside", @@ -1749,7 +2214,7 @@ }, { "file": "src/pixi/display/DisplayObject.js", - "line": 193, + "line": 247, "description": "[Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default\nInstead of using this function you can now simply set the interactive property to true or false", "itemtype": "method", "name": "setInteractive", @@ -1760,31 +2225,36 @@ "type": "Boolean" } ], + "deprecated": true, + "deprecationMessage": "Simply set the `interactive` property directly", "class": "DisplayObject" }, { "file": "src/pixi/display/DisplayObject.js", - "line": 204, + "line": 260, "description": "Indicates if the sprite will have touch and mouse interactivity. It is false by default", "itemtype": "property", "name": "interactive", "type": "Boolean", + "default": "false", "class": "DisplayObject" }, { "file": "src/pixi/display/DisplayObject.js", - "line": 222, + "line": 280, "description": "Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it.\nIn PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping.\nTo remove a mask, set this property to null.", "itemtype": "property", "name": "mask", - "type": "PIXI.Graphics", + "type": "Graphics", "class": "DisplayObject" }, { "file": "src/pixi/display/DisplayObject.js", - "line": 399, - "access": "private", - "tagname": "", + "line": 318, + "description": "Sets the filters for the displayObject. \n* IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer.\nTo remove filters simply set this property to 'null'", + "itemtype": "property", + "name": "filters", + "type": "Array An array of filters", "class": "DisplayObject" }, { @@ -1795,23 +2265,24 @@ }, { "file": "src/pixi/display/DisplayObjectContainer.js", - "line": 16, + "line": 18, "description": "[read-only] The of children of this container.", "itemtype": "property", "name": "children", - "type": "Array", + "type": "Array", + "readonly": "", "class": "DisplayObjectContainer" }, { "file": "src/pixi/display/DisplayObjectContainer.js", - "line": 42, + "line": 32, "description": "Adds a child to the container.", "itemtype": "method", "name": "addChild", "params": [ { - "name": "DisplayObject", - "description": "", + "name": "child", + "description": "The DisplayObject to add to the container", "type": "DisplayObject" } ], @@ -1819,19 +2290,19 @@ }, { "file": "src/pixi/display/DisplayObjectContainer.js", - "line": 139, + "line": 120, "description": "Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown", "itemtype": "method", "name": "addChildAt", "params": [ { - "name": "DisplayObject", - "description": "", + "name": "child", + "description": "The child to add", "type": "DisplayObject" }, { "name": "index", - "description": "", + "description": "The index to place the child in", "type": "Number" } ], @@ -1839,61 +2310,56 @@ }, { "file": "src/pixi/display/DisplayObjectContainer.js", - "line": 227, - "description": "Swaps the depth of 2 displayObjects", + "line": 207, + "description": "[NYI] Swaps the depth of 2 displayObjects", "itemtype": "method", "name": "swapChildren", "params": [ { - "name": "DisplayObject", + "name": "child", "description": "", "type": "DisplayObject" }, { - "name": "DisplayObject2", + "name": "child2", "description": "", "type": "DisplayObject" } ], + "access": "private", + "tagname": "", + "class": "DisplayObjectContainer" + }, + { + "file": "src/pixi/display/DisplayObjectContainer.js", + "line": 256, + "description": "Returns the Child at the specified index", + "itemtype": "method", + "name": "getChildAt", + "params": [ + { + "name": "index", + "description": "The index to get the child from", + "type": "Number" + } + ], "class": "DisplayObjectContainer" }, { "file": "src/pixi/display/DisplayObjectContainer.js", "line": 274, - "description": "Returns the Child at the specified index", - "itemtype": "method", - "name": "getChildAt", - "params": [ - { - "name": "index", - "description": "", - "type": "Number" - } - ], - "class": "DisplayObjectContainer" - }, - { - "file": "src/pixi/display/DisplayObjectContainer.js", - "line": 291, "description": "Removes a child from the container.", "itemtype": "method", "name": "removeChild", "params": [ { - "name": "DisplayObject", - "description": "", + "name": "child", + "description": "The DisplayObject to remove", "type": "DisplayObject" } ], "class": "DisplayObjectContainer" }, - { - "file": "src/pixi/display/DisplayObjectContainer.js", - "line": 358, - "access": "private", - "tagname": "", - "class": "DisplayObjectContainer" - }, { "file": "src/pixi/display/MovieClip.js", "line": 1, @@ -1902,7 +2368,7 @@ }, { "file": "src/pixi/display/MovieClip.js", - "line": 16, + "line": 17, "description": "The array of textures that make up the animation", "itemtype": "property", "name": "textures", @@ -1911,34 +2377,27 @@ }, { "file": "src/pixi/display/MovieClip.js", - "line": 23, - "description": "[read only] The index MovieClips current frame (this may not have to be a whole number)", - "itemtype": "property", - "name": "currentFrame", - "type": "Number", - "class": "MovieClip" - }, - { - "file": "src/pixi/display/MovieClip.js", - "line": 30, + "line": 25, "description": "The speed that the MovieClip will play at. Higher is faster, lower is slower", "itemtype": "property", "name": "animationSpeed", "type": "Number", + "default": "1", "class": "MovieClip" }, { "file": "src/pixi/display/MovieClip.js", - "line": 37, + "line": 34, "description": "Whether or not the movie clip repeats after playing.", "itemtype": "property", "name": "loop", "type": "Boolean", + "default": "true", "class": "MovieClip" }, { "file": "src/pixi/display/MovieClip.js", - "line": 44, + "line": 43, "description": "Function to call when a MovieClip finishes playing", "itemtype": "property", "name": "onComplete", @@ -1948,15 +2407,38 @@ { "file": "src/pixi/display/MovieClip.js", "line": 51, - "description": "[read only] indicates if the MovieClip is currently playing", + "description": "[read-only] The index MovieClips current frame (this may not have to be a whole number)", "itemtype": "property", - "name": "playing", - "type": "Boolean", + "name": "currentFrame", + "type": "Number", + "default": "0", + "readonly": "", "class": "MovieClip" }, { "file": "src/pixi/display/MovieClip.js", - "line": 63, + "line": 61, + "description": "[read-only] Indicates if the MovieClip is currently playing", + "itemtype": "property", + "name": "playing", + "type": "Boolean", + "readonly": "", + "class": "MovieClip" + }, + { + "file": "src/pixi/display/MovieClip.js", + "line": 75, + "description": "[read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures\nassigned to the MovieClip.", + "itemtype": "property", + "name": "totalFrames", + "type": "Number", + "default": "0", + "readonly": "", + "class": "MovieClip" + }, + { + "file": "src/pixi/display/MovieClip.js", + "line": 92, "description": "Stops the MovieClip", "itemtype": "method", "name": "stop", @@ -1964,7 +2446,7 @@ }, { "file": "src/pixi/display/MovieClip.js", - "line": 72, + "line": 102, "description": "Plays the MovieClip", "itemtype": "method", "name": "play", @@ -1972,7 +2454,7 @@ }, { "file": "src/pixi/display/MovieClip.js", - "line": 81, + "line": 112, "description": "Stops the MovieClip and goes to a specific frame", "itemtype": "method", "name": "gotoAndStop", @@ -1987,7 +2469,7 @@ }, { "file": "src/pixi/display/MovieClip.js", - "line": 94, + "line": 126, "description": "Goes to a specific frame and begins playing the MovieClip", "itemtype": "method", "name": "gotoAndPlay", @@ -2008,7 +2490,7 @@ }, { "file": "src/pixi/display/Sprite.js", - "line": 21, + "line": 23, "description": "The anchor sets the origin point of the texture.\nThe default is 0,0 this means the textures origin is the top left \nSetting than anchor to 0.5,0.5 means the textures origin is centered\nSetting the anchor to 1,1 would mean the textures origin points will be the bottom right", "itemtype": "property", "name": "anchor", @@ -2017,7 +2499,7 @@ }, { "file": "src/pixi/display/Sprite.js", - "line": 31, + "line": 34, "description": "The texture that the sprite is using", "itemtype": "property", "name": "texture", @@ -2026,34 +2508,57 @@ }, { "file": "src/pixi/display/Sprite.js", - "line": 38, + "line": 42, "description": "The blend mode of sprite.\ncurrently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN", "itemtype": "property", "name": "blendMode", - "type": "uint", + "type": "Number", "class": "Sprite" }, { "file": "src/pixi/display/Sprite.js", - "line": 46, + "line": 51, "description": "The width of the sprite (this is initially set by the texture)", "itemtype": "property", - "name": "width", - "type": "#Number", + "name": "_width", + "type": "Number", + "access": "private", + "tagname": "", "class": "Sprite" }, { "file": "src/pixi/display/Sprite.js", - "line": 53, + "line": 60, "description": "The height of the sprite (this is initially set by the texture)", "itemtype": "property", - "name": "height", - "type": "#Number", + "name": "_height", + "type": "Number", + "access": "private", + "tagname": "", "class": "Sprite" }, { "file": "src/pixi/display/Sprite.js", - "line": 103, + "line": 86, + "description": "The width of the sprite, setting this will actually modify the scale to acheive the value set", + "itemtype": "property", + "name": "width", + "type": "Number", + "class": "Sprite" + }, + { + "file": "src/pixi/display/Sprite.js", + "line": 102, + "description": "The height of the sprite, setting this will actually modify the scale to acheive the value set", + "itemtype": "property", + "name": "height", + "type": "Number", + "class": "Sprite" + }, + { + "file": "src/pixi/display/Sprite.js", + "line": 118, + "description": "Sets the texture of the sprite", "itemtype": "method", "name": "setTexture", "params": [ @@ -2067,14 +2572,23 @@ }, { "file": "src/pixi/display/Sprite.js", - "line": 119, + "line": 145, + "description": "When the texture is updated, this event will fire to update the scale and frame", + "itemtype": "method", + "name": "onTextureUpdate", + "params": [ + { + "name": "event", + "description": "" + } + ], "access": "private", "tagname": "", "class": "Sprite" }, { "file": "src/pixi/display/Sprite.js", - "line": 135, + "line": 165, "description": "Helper function that creates a sprite that will contain a texture from the TextureCache based on the frameId\n The frame ids are created when a Texture packer file has been loaded", "itemtype": "method", "name": "fromFrame", @@ -2094,15 +2608,16 @@ }, { "file": "src/pixi/display/Sprite.js", - "line": 151, + "line": 182, "description": "Helper function that creates a sprite that will contain a texture based on an image url\n If the image is not in the texture cache it will be loaded", "itemtype": "method", "name": "fromImage", "static": 1, "params": [ { - "name": "The", - "description": "image url of the texture" + "name": "imageId", + "description": "The image url of the texture", + "type": "String" } ], "return": { @@ -2119,21 +2634,70 @@ }, { "file": "src/pixi/display/Stage.js", - "line": 42, - "itemtype": "method", - "name": "updateTransform", - "internal": "", + "line": 18, + "description": "[read-only] Current transform of the object based on world (parent) factors", + "itemtype": "property", + "name": "worldTransform", + "type": "Mat3", + "readonly": "", + "access": "private", + "tagname": "", "class": "Stage" }, { "file": "src/pixi/display/Stage.js", - "line": 65, + "line": 28, + "description": "Whether or not the stage is interactive", + "itemtype": "property", + "name": "interactive", + "type": "Boolean", + "class": "Stage" + }, + { + "file": "src/pixi/display/Stage.js", + "line": 36, + "description": "The interaction manage for this stage, manages all interactive activity on the stage", + "itemtype": "property", + "name": "interactive", + "type": "InteractionManager", + "class": "Stage" + }, + { + "file": "src/pixi/display/Stage.js", + "line": 44, + "description": "Whether the stage is dirty and needs to have interactions updated", + "itemtype": "property", + "name": "dirty", + "type": "Boolean", + "access": "private", + "tagname": "", + "class": "Stage" + }, + { + "file": "src/pixi/display/Stage.js", + "line": 70, + "description": "Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element.\nThis is useful for when you have other DOM elements ontop of the Canvas element.", + "itemtype": "method", + "name": "setInteractionDelegate", + "params": [ + { + "name": "domElement", + "description": "This new domElement which will receive mouse/touch events", + "type": "DOMElement" + } + ], + "class": "Stage" + }, + { + "file": "src/pixi/display/Stage.js", + "line": 109, + "description": "Sets the background color for the stage", "itemtype": "method", "name": "setBackgroundColor", "params": [ { "name": "backgroundColor", - "description": "", + "description": "the color of the background, easiest way to pass this in is in hex format\n\t\tlike: 0xFFFFFF for white", "type": "Number" } ], @@ -2141,7 +2705,7 @@ }, { "file": "src/pixi/display/Stage.js", - "line": 78, + "line": 125, "description": "This will return the point containing global coords of the mouse.", "itemtype": "method", "name": "getMousePosition", @@ -2157,6 +2721,51 @@ "author": "Mat Groves http://matgroves.com/ @Doormat23", "class": "CustomRenderable" }, + { + "file": "src/pixi/extras/CustomRenderable.js", + "line": 24, + "description": "If this object is being rendered by a CanvasRenderer it will call this callback", + "itemtype": "method", + "name": "renderCanvas", + "params": [ + { + "name": "renderer", + "description": "The renderer instance", + "type": "CanvasRenderer" + } + ], + "class": "CustomRenderable" + }, + { + "file": "src/pixi/extras/CustomRenderable.js", + "line": 35, + "description": "If this object is being rendered by a WebGLRenderer it will call this callback to initialize", + "itemtype": "method", + "name": "initWebGL", + "params": [ + { + "name": "renderer", + "description": "The renderer instance", + "type": "WebGLRenderer" + } + ], + "class": "CustomRenderable" + }, + { + "file": "src/pixi/extras/CustomRenderable.js", + "line": 46, + "description": "If this object is being rendered by a WebGLRenderer it will call this callback", + "itemtype": "method", + "name": "renderWebGL", + "params": [ + { + "name": "renderer", + "description": "The renderer instance", + "type": "WebGLRenderer" + } + ], + "class": "CustomRenderable" + }, { "file": "src/pixi/extras/Rope.js", "line": 1, @@ -2171,20 +2780,10 @@ }, { "file": "src/pixi/extras/Spine.js", - "line": 308, + "line": 327, "description": "cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of", "class": "Spine" }, - { - "file": "src/pixi/extras/Spine.js", - "line": 604, - "class": "Spine" - }, - { - "file": "src/pixi/extras/Spine.js", - "line": 611, - "class": "Spine" - }, { "file": "src/pixi/extras/Spine.js", "line": 618, @@ -2192,12 +2791,12 @@ }, { "file": "src/pixi/extras/Spine.js", - "line": 626, + "line": 625, "class": "Spine" }, { "file": "src/pixi/extras/Spine.js", - "line": 633, + "line": 632, "class": "Spine" }, { @@ -2207,27 +2806,27 @@ }, { "file": "src/pixi/extras/Spine.js", - "line": 675, + "line": 647, "class": "Spine" }, { "file": "src/pixi/extras/Spine.js", - "line": 683, + "line": 654, "class": "Spine" }, { "file": "src/pixi/extras/Spine.js", - "line": 698, + "line": 689, "class": "Spine" }, { "file": "src/pixi/extras/Spine.js", - "line": 702, + "line": 697, "class": "Spine" }, { "file": "src/pixi/extras/Spine.js", - "line": 709, + "line": 712, "class": "Spine" }, { @@ -2242,33 +2841,33 @@ }, { "file": "src/pixi/extras/Spine.js", - "line": 735, + "line": 730, + "class": "Spine" + }, + { + "file": "src/pixi/extras/Spine.js", + "line": 737, + "class": "Spine" + }, + { + "file": "src/pixi/extras/Spine.js", + "line": 749, "description": "from the new skin are attached if the corresponding attachment from the old skin was attached.", "class": "Spine" }, { "file": "src/pixi/extras/Spine.js", - "line": 742, + "line": 756, "class": "Spine" }, { "file": "src/pixi/extras/Spine.js", - "line": 746, + "line": 760, "class": "Spine" }, { "file": "src/pixi/extras/Spine.js", - "line": 755, - "class": "Spine" - }, - { - "file": "src/pixi/extras/Spine.js", - "line": 948, - "class": "Spine" - }, - { - "file": "src/pixi/extras/Spine.js", - "line": 954, + "line": 769, "class": "Spine" }, { @@ -2283,12 +2882,22 @@ }, { "file": "src/pixi/extras/Spine.js", - "line": 984, + "line": 972, "class": "Spine" }, { "file": "src/pixi/extras/Spine.js", - "line": 1401, + "line": 978, + "class": "Spine" + }, + { + "file": "src/pixi/extras/Spine.js", + "line": 996, + "class": "Spine" + }, + { + "file": "src/pixi/extras/Spine.js", + "line": 1415, "class": "Spine" }, { @@ -2305,7 +2914,34 @@ }, { "file": "src/pixi/extras/TilingSprite.js", - "line": 22, + "line": 19, + "description": "The texture that the sprite is using", + "itemtype": "property", + "name": "texture", + "type": "Texture", + "class": "TilingSprite" + }, + { + "file": "src/pixi/extras/TilingSprite.js", + "line": 27, + "description": "The width of the tiling sprite", + "itemtype": "property", + "name": "width", + "type": "Number", + "class": "TilingSprite" + }, + { + "file": "src/pixi/extras/TilingSprite.js", + "line": 35, + "description": "The height of the tiling sprite", + "itemtype": "property", + "name": "height", + "type": "Number", + "class": "TilingSprite" + }, + { + "file": "src/pixi/extras/TilingSprite.js", + "line": 43, "description": "The scaling of the image that is being tiled", "itemtype": "property", "name": "tileScale", @@ -2314,21 +2950,232 @@ }, { "file": "src/pixi/extras/TilingSprite.js", - "line": 28, + "line": 51, "description": "The offset position of the image that is being tiled", "itemtype": "property", "name": "tilePosition", "type": "Point", "class": "TilingSprite" }, + { + "file": "src/pixi/extras/TilingSprite.js", + "line": 68, + "description": "Sets the texture of the tiling sprite", + "itemtype": "method", + "name": "setTexture", + "params": [ + { + "name": "texture", + "description": "The PIXI texture that is displayed by the sprite", + "type": "Texture" + } + ], + "class": "TilingSprite" + }, + { + "file": "src/pixi/extras/TilingSprite.js", + "line": 84, + "description": "When the texture is updated, this event will fire to update the frame", + "itemtype": "method", + "name": "onTextureUpdate", + "params": [ + { + "name": "event", + "description": "" + } + ], + "access": "private", + "tagname": "", + "class": "TilingSprite" + }, + { + "file": "src/pixi/filters/AbstractFilter.js", + "line": 1, + "author": "Mat Groves http://matgroves.com/ @Doormat23", + "class": "AbstractFilter" + }, + { + "file": "src/pixi/filters/AbstractFilter.js", + "line": 16, + "description": "An array of passes - some filters contain a few steps this array simply stores the steps in a liniear fashion.\nFor example the blur filter has two passes blurX and blurY.", + "itemtype": "property", + "name": "passes", + "type": "Array an array of filter objects", + "access": "private", + "tagname": "", + "class": "AbstractFilter" + }, + { + "file": "src/pixi/filters/AbstractFilter.js", + "line": 29, + "itemtype": "property", + "name": "uniforms", + "access": "private", + "tagname": "", + "class": "AbstractFilter" + }, + { + "file": "src/pixi/filters/BlurFilter.js", + "line": 1, + "author": "Mat Groves http://matgroves.com/ @Doormat23", + "class": "BlurFilter" + }, + { + "file": "src/pixi/filters/BlurFilter.js", + "line": 24, + "description": "Sets the strength of both the blurX and blurY properties simultaneously", + "itemtype": "property", + "name": "blur", + "type": "Number the strength of the blur", + "default": "2", + "class": "BlurFilter" + }, + { + "file": "src/pixi/filters/BlurFilter.js", + "line": 40, + "description": "Sets the strength of the blurX property simultaneously", + "itemtype": "property", + "name": "blurX", + "type": "Number the strength of the blurX", + "default": "2", + "class": "BlurFilter" + }, + { + "file": "src/pixi/filters/BlurFilter.js", + "line": 56, + "description": "Sets the strength of the blurX property simultaneously", + "itemtype": "property", + "name": "blurY", + "type": "Number the strength of the blurY", + "default": "2", + "class": "BlurFilter" + }, + { + "file": "src/pixi/filters/BlurXFilter.js", + "line": 1, + "author": "Mat Groves http://matgroves.com/ @Doormat23", + "class": "ColorMatrixFilter" + }, + { + "file": "src/pixi/filters/BlurYFilter.js", + "line": 1, + "author": "Mat Groves http://matgroves.com/ @Doormat23", + "class": "ColorMatrixFilter" + }, + { + "file": "src/pixi/filters/ColorMatrixFilter.js", + "line": 1, + "author": "Mat Groves http://matgroves.com/ @Doormat23", + "class": "ColorMatrixFilter" + }, + { + "file": "src/pixi/filters/ColorMatrixFilter.js", + "line": 45, + "description": "Sets the matrix of the color matrix filter", + "itemtype": "property", + "name": "matrix", + "type": "Array and array of 26 numbers", + "default": "[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]", + "class": "ColorMatrixFilter" + }, + { + "file": "src/pixi/filters/DisplacementFilter.js", + "line": 1, + "author": "Mat Groves http://matgroves.com/ @Doormat23", + "class": "DisplacementFilter" + }, + { + "file": "src/pixi/filters/DisplacementFilter.js", + "line": 92, + "description": "The texture used for the displacemtent map * must be power of 2 texture at the moment", + "itemtype": "property", + "name": "map", + "type": "Texture", + "class": "DisplacementFilter" + }, + { + "file": "src/pixi/filters/DisplacementFilter.js", + "line": 107, + "description": "The multiplier used to scale the displacement result from the map calculation.", + "itemtype": "property", + "name": "scale", + "type": "Point", + "class": "DisplacementFilter" + }, + { + "file": "src/pixi/filters/DisplacementFilter.js", + "line": 122, + "description": "The offset used to move the displacement map.", + "itemtype": "property", + "name": "offset", + "type": "Point", + "class": "DisplacementFilter" + }, { "file": "src/pixi/filters/FilterBlock.js", "line": 1, "author": "Mat Groves http://matgroves.com/ @Doormat23", - "class": "AssetLoader" + "class": "GreyFilter" }, { - "file": "src/pixi/filters/MaskFilter.js", + "file": "src/pixi/filters/GreyFilter.js", + "line": 1, + "author": "Mat Groves http://matgroves.com/ @Doormat23", + "class": "GreyFilter" + }, + { + "file": "src/pixi/filters/GreyFilter.js", + "line": 40, + "description": "The strength of the grey. 1 will make the object black and white, 0 will make the object its normal color", + "itemtype": "property", + "name": "grey", + "class": "GreyFilter" + }, + { + "file": "src/pixi/filters/InvertFilter.js", + "line": 1, + "author": "Mat Groves http://matgroves.com/ @Doormat23", + "class": "InvertFilter" + }, + { + "file": "src/pixi/filters/InvertFilter.js", + "line": 41, + "description": "The strength of the invert. 1 will fully invert the colors, 0 will make the object its normal color", + "itemtype": "property", + "name": "invert", + "class": "InvertFilter" + }, + { + "file": "src/pixi/filters/PixelateFilter.js", + "line": 1, + "author": "Mat Groves http://matgroves.com/ @Doormat23", + "class": "PixelateFilter" + }, + { + "file": "src/pixi/filters/PixelateFilter.js", + "line": 50, + "description": "This a point that describes the size of the blocs. x is the width of the block and y is the the height", + "itemtype": "property", + "name": "size", + "type": "Point", + "class": "PixelateFilter" + }, + { + "file": "src/pixi/filters/SepiaFilter.js", + "line": 1, + "description": "/**\n * @author Mat Groves http://matgroves.com/ @Doormat23", + "class": "SepiaFilter" + }, + { + "file": "src/pixi/filters/SepiaFilter.js", + "line": 44, + "description": "The strength of the sepia. 1 will apply the full sepia effect, 0 will make the object its normal color", + "itemtype": "property", + "name": "sepia", + "class": "SepiaFilter" + }, + { + "file": "src/pixi/filters/SmartBlurFilter.js", "line": 1, "author": "Mat Groves http://matgroves.com/ @Doormat23", "class": "AssetLoader" @@ -2341,16 +3188,34 @@ }, { "file": "src/pixi/loaders/AssetLoader.js", - "line": 18, + "line": 25, "description": "The array of asset URLs that are going to be loaded", "itemtype": "property", "name": "assetURLs", - "type": "Array", + "type": "Array", + "class": "AssetLoader" + }, + { + "file": "src/pixi/loaders/AssetLoader.js", + "line": 33, + "description": "Whether the requests should be treated as cross origin", + "itemtype": "property", + "name": "crossorigin", + "type": "Boolean", "class": "AssetLoader" }, { "file": "src/pixi/loaders/AssetLoader.js", "line": 41, + "description": "Maps file extension to loader types", + "itemtype": "property", + "name": "loadersByType", + "type": "Object", + "class": "AssetLoader" + }, + { + "file": "src/pixi/loaders/AssetLoader.js", + "line": 61, "description": "Fired when an item has loaded", "itemtype": "event", "name": "onProgress", @@ -2358,7 +3223,7 @@ }, { "file": "src/pixi/loaders/AssetLoader.js", - "line": 46, + "line": 66, "description": "Fired when all the assets have loaded", "itemtype": "event", "name": "onComplete", @@ -2366,14 +3231,18 @@ }, { "file": "src/pixi/loaders/AssetLoader.js", - "line": 54, - "description": "This will begin loading the assets sequentially", + "line": 74, + "description": "Starts loading the assets sequentially", + "itemtype": "method", + "name": "load", "class": "AssetLoader" }, { "file": "src/pixi/loaders/AssetLoader.js", - "line": 82, + "line": 104, "description": "Invoked after each file is loaded", + "itemtype": "method", + "name": "onAssetLoaded", "access": "private", "tagname": "", "class": "AssetLoader" @@ -2384,24 +3253,67 @@ "author": "Mat Groves http://matgroves.com/ @Doormat23", "class": "BitmapFontLoader" }, + { + "file": "src/pixi/loaders/BitmapFontLoader.js", + "line": 26, + "description": "The url of the bitmap font data", + "itemtype": "property", + "name": "url", + "type": "String", + "class": "BitmapFontLoader" + }, { "file": "src/pixi/loaders/BitmapFontLoader.js", "line": 34, - "description": "This will begin loading the JSON file", + "description": "Whether the requests should be treated as cross origin", + "itemtype": "property", + "name": "crossorigin", + "type": "Boolean", + "class": "BitmapFontLoader" + }, + { + "file": "src/pixi/loaders/BitmapFontLoader.js", + "line": 42, + "description": "[read-only] The base url of the bitmap font data", + "itemtype": "property", + "name": "baseUrl", + "type": "String", + "readonly": "", "class": "BitmapFontLoader" }, { "file": "src/pixi/loaders/BitmapFontLoader.js", "line": 51, - "description": "Invoked when XML file is loaded", + "description": "[read-only] The texture of the bitmap font", + "itemtype": "property", + "name": "baseUrl", + "type": "String", + "class": "BitmapFontLoader" + }, + { + "file": "src/pixi/loaders/BitmapFontLoader.js", + "line": 63, + "description": "Loads the XML font data", + "itemtype": "method", + "name": "load", + "class": "BitmapFontLoader" + }, + { + "file": "src/pixi/loaders/BitmapFontLoader.js", + "line": 82, + "description": "Invoked when XML file is loaded, parses the data", + "itemtype": "method", + "name": "onXMLLoaded", "access": "private", "tagname": "", "class": "BitmapFontLoader" }, { "file": "src/pixi/loaders/BitmapFontLoader.js", - "line": 121, + "line": 153, "description": "Invoked when all files are loaded (xml/fnt and texture)", + "itemtype": "method", + "name": "onLoaded", "access": "private", "tagname": "", "class": "BitmapFontLoader" @@ -2414,18 +3326,62 @@ }, { "file": "src/pixi/loaders/ImageLoader.js", - "line": 24, - "description": "Loads image or takes it from cache", + "line": 20, + "description": "The texture being loaded", + "itemtype": "property", + "name": "texture", + "type": "Texture", "class": "ImageLoader" }, { "file": "src/pixi/loaders/ImageLoader.js", - "line": 43, + "line": 28, + "description": "if the image is loaded with loadFramedSpriteSheet\nframes will contain the sprite sheet frames", + "class": "ImageLoader" + }, + { + "file": "src/pixi/loaders/ImageLoader.js", + "line": 39, + "description": "Loads image or takes it from cache", + "itemtype": "method", + "name": "load", + "class": "ImageLoader" + }, + { + "file": "src/pixi/loaders/ImageLoader.js", + "line": 60, "description": "Invoked when image file is loaded or it is already cached and ready to use", + "itemtype": "method", + "name": "onLoaded", "access": "private", "tagname": "", "class": "ImageLoader" }, + { + "file": "src/pixi/loaders/ImageLoader.js", + "line": 71, + "description": "Loads image and split it to uniform sized frames", + "itemtype": "method", + "name": "loadFramedSpriteSheet", + "params": [ + { + "name": "frameWidth", + "description": "with of each frame", + "type": "Number" + }, + { + "name": "frameHeight", + "description": "height of each frame", + "type": "Number" + }, + { + "name": "textureName", + "description": "if given, the frames will be cached in - format", + "type": "String" + } + ], + "class": "ImageLoader" + }, { "file": "src/pixi/loaders/JsonLoader.js", "line": 1, @@ -2434,30 +3390,76 @@ }, { "file": "src/pixi/loaders/JsonLoader.js", - "line": 28, - "description": "This will begin loading the JSON file", + "line": 19, + "description": "The url of the bitmap font data", + "itemtype": "property", + "name": "url", + "type": "String", "class": "JsonLoader" }, { "file": "src/pixi/loaders/JsonLoader.js", - "line": 43, + "line": 27, + "description": "Whether the requests should be treated as cross origin", + "itemtype": "property", + "name": "crossorigin", + "type": "Boolean", + "class": "JsonLoader" + }, + { + "file": "src/pixi/loaders/JsonLoader.js", + "line": 35, + "description": "[read-only] The base url of the bitmap font data", + "itemtype": "property", + "name": "baseUrl", + "type": "String", + "readonly": "", + "class": "JsonLoader" + }, + { + "file": "src/pixi/loaders/JsonLoader.js", + "line": 44, + "description": "[read-only] Whether the data has loaded yet", + "itemtype": "property", + "name": "loaded", + "type": "Boolean", + "readonly": "", + "class": "JsonLoader" + }, + { + "file": "src/pixi/loaders/JsonLoader.js", + "line": 58, + "description": "Loads the JSON data", + "itemtype": "method", + "name": "load", + "class": "JsonLoader" + }, + { + "file": "src/pixi/loaders/JsonLoader.js", + "line": 75, "description": "Invoke when JSON file is loaded", + "itemtype": "method", + "name": "onJSONLoaded", "access": "private", "tagname": "", "class": "JsonLoader" }, { "file": "src/pixi/loaders/JsonLoader.js", - "line": 108, + "line": 140, "description": "Invoke when json file loaded", + "itemtype": "method", + "name": "onLoaded", "access": "private", "tagname": "", "class": "JsonLoader" }, { "file": "src/pixi/loaders/JsonLoader.js", - "line": 120, + "line": 154, "description": "Invoke when error occured", + "itemtype": "method", + "name": "onError", "access": "private", "tagname": "", "class": "JsonLoader" @@ -2470,8 +3472,56 @@ }, { "file": "src/pixi/loaders/SpineLoader.js", - "line": 54, + "line": 28, + "description": "The url of the bitmap font data", + "itemtype": "property", + "name": "url", + "type": "String", + "class": "Spine" + }, + { + "file": "src/pixi/loaders/SpineLoader.js", + "line": 36, + "description": "Whether the requests should be treated as cross origin", + "itemtype": "property", + "name": "crossorigin", + "type": "Boolean", + "class": "Spine" + }, + { + "file": "src/pixi/loaders/SpineLoader.js", + "line": 44, + "description": "[read-only] Whether the data has loaded yet", + "itemtype": "property", + "name": "loaded", + "type": "Boolean", + "readonly": "", + "class": "Spine" + }, + { + "file": "src/pixi/loaders/SpineLoader.js", + "line": 56, + "description": "Loads the JSON data", + "itemtype": "method", + "name": "load", + "class": "Spine" + }, + { + "file": "src/pixi/loaders/SpineLoader.js", + "line": 72, "description": "Invoke when JSON file is loaded", + "itemtype": "method", + "name": "onJSONLoaded", + "access": "private", + "tagname": "", + "class": "Spine" + }, + { + "file": "src/pixi/loaders/SpineLoader.js", + "line": 87, + "description": "Invoke when JSON file is loaded", + "itemtype": "method", + "name": "onLoaded", "access": "private", "tagname": "", "class": "Spine" @@ -2484,22 +3534,74 @@ }, { "file": "src/pixi/loaders/SpriteSheetLoader.js", - "line": 37, - "description": "This will begin loading the JSON file", + "line": 29, + "description": "The url of the bitmap font data", + "itemtype": "property", + "name": "url", + "type": "String", "class": "SpriteSheetLoader" }, { "file": "src/pixi/loaders/SpriteSheetLoader.js", - "line": 50, + "line": 37, + "description": "Whether the requests should be treated as cross origin", + "itemtype": "property", + "name": "crossorigin", + "type": "Boolean", + "class": "SpriteSheetLoader" + }, + { + "file": "src/pixi/loaders/SpriteSheetLoader.js", + "line": 45, + "description": "[read-only] The base url of the bitmap font data", + "itemtype": "property", + "name": "baseUrl", + "type": "String", + "readonly": "", + "class": "SpriteSheetLoader" + }, + { + "file": "src/pixi/loaders/SpriteSheetLoader.js", + "line": 54, + "description": "The texture being loaded", + "itemtype": "property", + "name": "texture", + "type": "Texture", + "class": "SpriteSheetLoader" + }, + { + "file": "src/pixi/loaders/SpriteSheetLoader.js", + "line": 62, + "description": "The frames of the sprite sheet", + "itemtype": "property", + "name": "frames", + "type": "Object", + "class": "SpriteSheetLoader" + }, + { + "file": "src/pixi/loaders/SpriteSheetLoader.js", + "line": 74, + "description": "This will begin loading the JSON file", + "itemtype": "method", + "name": "load", + "class": "SpriteSheetLoader" + }, + { + "file": "src/pixi/loaders/SpriteSheetLoader.js", + "line": 89, "description": "Invoke when JSON file is loaded", + "itemtype": "method", + "name": "onJSONLoaded", "access": "private", "tagname": "", "class": "SpriteSheetLoader" }, { "file": "src/pixi/loaders/SpriteSheetLoader.js", - "line": 85, + "line": 126, "description": "Invoke when all files are loaded (json and texture)", + "itemtype": "method", + "name": "onLoaded", "access": "private", "tagname": "", "class": "SpriteSheetLoader" @@ -2512,24 +3614,73 @@ }, { "file": "src/pixi/primitives/Graphics.js", - "line": 34, + "line": 21, + "description": "The alpha of the fill of this graphics object", + "itemtype": "property", + "name": "fillAlpha", + "type": "Number", + "class": "Graphics" + }, + { + "file": "src/pixi/primitives/Graphics.js", + "line": 29, + "description": "The width of any lines drawn", + "itemtype": "property", + "name": "lineWidth", + "type": "Number", + "class": "Graphics" + }, + { + "file": "src/pixi/primitives/Graphics.js", + "line": 37, + "description": "The color of any lines drawn", + "itemtype": "property", + "name": "lineColor", + "type": "String", + "class": "Graphics" + }, + { + "file": "src/pixi/primitives/Graphics.js", + "line": 45, + "description": "Graphics data", + "itemtype": "property", + "name": "graphicsData", + "type": "Array", + "access": "private", + "tagname": "", + "class": "Graphics" + }, + { + "file": "src/pixi/primitives/Graphics.js", + "line": 54, + "description": "Current path", + "itemtype": "property", + "name": "currentPath", + "type": "Object", + "access": "private", + "tagname": "", + "class": "Graphics" + }, + { + "file": "src/pixi/primitives/Graphics.js", + "line": 68, "description": "Specifies a line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method.", "itemtype": "method", "name": "lineStyle", "params": [ { "name": "lineWidth", - "description": "", + "description": "width of the line to draw, will update the object's stored style", "type": "Number" }, { "name": "color", - "description": "", + "description": "color of the line to draw, will update the object's stored style", "type": "Number" }, { "name": "alpha", - "description": "", + "description": "alpha of the line to draw, will update the object's stored style", "type": "Number" } ], @@ -2537,19 +3688,19 @@ }, { "file": "src/pixi/primitives/Graphics.js", - "line": 55, + "line": 90, "description": "Moves the current drawing position to (x, y).", "itemtype": "method", "name": "moveTo", "params": [ { "name": "x", - "description": "", + "description": "the X coord to move to", "type": "Number" }, { "name": "y", - "description": "", + "description": "the Y coord to move to", "type": "Number" } ], @@ -2557,19 +3708,19 @@ }, { "file": "src/pixi/primitives/Graphics.js", - "line": 73, - "description": "Draws a line using the current line style from the current drawing position to (x, y); the current drawing position is then set to (x, y).", + "line": 109, + "description": "Draws a line using the current line style from the current drawing position to (x, y);\nthe current drawing position is then set to (x, y).", "itemtype": "method", "name": "lineTo", "params": [ { "name": "x", - "description": "", + "description": "the X coord to draw to", "type": "Number" }, { "name": "y", - "description": "", + "description": "the Y coord to draw to", "type": "Number" } ], @@ -2577,8 +3728,8 @@ }, { "file": "src/pixi/primitives/Graphics.js", - "line": 85, - "description": "Specifies a simple one-color fill that subsequent calls to other Graphics methods (such as lineTo() or drawCircle()) use when drawing.", + "line": 123, + "description": "Specifies a simple one-color fill that subsequent calls to other Graphics methods\n(such as lineTo() or drawCircle()) use when drawing.", "itemtype": "method", "name": "beginFill", "params": [ @@ -2597,7 +3748,7 @@ }, { "file": "src/pixi/primitives/Graphics.js", - "line": 98, + "line": 138, "description": "Applies a fill to the lines and shapes that were added since the last call to the beginFill() method.", "itemtype": "method", "name": "endFill", @@ -2605,28 +3756,28 @@ }, { "file": "src/pixi/primitives/Graphics.js", - "line": 109, + "line": 150, "itemtype": "method", "name": "drawRect", "params": [ { "name": "x", - "description": "", + "description": "The X coord of the top-left of the rectangle", "type": "Number" }, { "name": "y", - "description": "", + "description": "The Y coord of the top-left of the rectangle", "type": "Number" }, { "name": "width", - "description": "", + "description": "The width of the rectangle", "type": "Number" }, { "name": "height", - "description": "", + "description": "The height of the rectangle", "type": "Number" } ], @@ -2634,24 +3785,24 @@ }, { "file": "src/pixi/primitives/Graphics.js", - "line": 128, + "line": 170, "description": "Draws a circle.", "itemtype": "method", "name": "drawCircle", "params": [ { "name": "x", - "description": "", + "description": "The X coord of the center of the circle", "type": "Number" }, { "name": "y", - "description": "", + "description": "The Y coord of the center of the circle", "type": "Number" }, { "name": "radius", - "description": "", + "description": "The radius of the circle", "type": "Number" } ], @@ -2659,7 +3810,7 @@ }, { "file": "src/pixi/primitives/Graphics.js", - "line": 147, + "line": 190, "description": "Draws an elipse.", "itemtype": "method", "name": "drawElipse", @@ -2689,7 +3840,7 @@ }, { "file": "src/pixi/primitives/Graphics.js", - "line": 167, + "line": 211, "description": "Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings.", "itemtype": "method", "name": "clear", @@ -2709,7 +3860,7 @@ }, { "file": "src/pixi/renderers/canvas/CanvasRenderer.js", - "line": 24, + "line": 21, "description": "The width of the canvas view", "itemtype": "property", "name": "width", @@ -2719,7 +3870,7 @@ }, { "file": "src/pixi/renderers/canvas/CanvasRenderer.js", - "line": 31, + "line": 30, "description": "The height of the canvas view", "itemtype": "property", "name": "height", @@ -2729,7 +3880,7 @@ }, { "file": "src/pixi/renderers/canvas/CanvasRenderer.js", - "line": 41, + "line": 39, "description": "The canvas element that the everything is drawn to", "itemtype": "property", "name": "view", @@ -2738,7 +3889,7 @@ }, { "file": "src/pixi/renderers/canvas/CanvasRenderer.js", - "line": 55, + "line": 47, "description": "The canvas context that the everything is drawn to", "itemtype": "property", "name": "context", @@ -2762,48 +3913,110 @@ }, { "file": "src/pixi/renderers/canvas/CanvasRenderer.js", - "line": 110, + "line": 113, "description": "resizes the canvas view to the specified width and height", + "itemtype": "method", + "name": "resize", "params": [ { - "name": "the", - "description": "new width of the canvas view" + "name": "width", + "description": "the new width of the canvas view", + "type": "Number" }, { - "name": "the", - "description": "new height of the canvas view" + "name": "height", + "description": "the new height of the canvas view", + "type": "Number" } ], "class": "CanvasRenderer" }, { "file": "src/pixi/renderers/canvas/CanvasRenderer.js", - "line": 124, + "line": 129, + "description": "Renders a display object", + "itemtype": "method", + "name": "renderDisplayObject", + "params": [ + { + "name": "displayObject", + "description": "The displayObject to render", + "type": "DisplayObject" + } + ], "access": "private", "tagname": "", "class": "CanvasRenderer" }, { "file": "src/pixi/renderers/canvas/CanvasRenderer.js", - "line": 235, + "line": 250, + "description": "Renders a flat strip", + "itemtype": "method", + "name": "renderStripFlat", + "params": [ + { + "name": "strip", + "description": "The Strip to render", + "type": "Strip" + } + ], "access": "private", "tagname": "", "class": "CanvasRenderer" }, { "file": "src/pixi/renderers/canvas/CanvasRenderer.js", - "line": 268, + "line": 287, + "description": "Renders a tiling sprite", + "itemtype": "method", + "name": "renderTilingSprite", + "params": [ + { + "name": "sprite", + "description": "The tilingsprite to render", + "type": "TilingSprite" + } + ], "access": "private", "tagname": "", "class": "CanvasRenderer" }, { "file": "src/pixi/renderers/canvas/CanvasRenderer.js", - "line": 299, + "line": 320, + "description": "Renders a strip", + "itemtype": "method", + "name": "renderStrip", + "params": [ + { + "name": "strip", + "description": "The Strip to render", + "type": "Strip" + } + ], "access": "private", "tagname": "", "class": "CanvasRenderer" }, + { + "file": "src/pixi/renderers/webgl/PixiShader.js", + "line": 1, + "author": "Mat Groves http://matgroves.com/ @Doormat23", + "class": "WebGLBatch" + }, + { + "file": "src/pixi/renderers/webgl/PrimitiveShader.js", + "line": 1, + "author": "Mat Groves http://matgroves.com/ @Doormat23", + "class": "WebGLBatch" + }, + { + "file": "src/pixi/renderers/webgl/StripShader.js", + "line": 1, + "author": "Mat Groves http://matgroves.com/ @Doormat23", + "class": "WebGLBatch" + }, { "file": "src/pixi/renderers/webgl/WebGLBatch.js", "line": 1, @@ -2833,20 +4046,37 @@ }, { "file": "src/pixi/renderers/webgl/WebGLBatch.js", - "line": 67, + "line": 71, "description": "Cleans the batch so that is can be returned to an object pool and reused", + "itemtype": "method", + "name": "clean", "class": "WebGLBatch" }, { "file": "src/pixi/renderers/webgl/WebGLBatch.js", - "line": 98, + "line": 90, + "description": "Recreates the buffers in the event of a context loss", + "itemtype": "method", + "name": "restoreLostContext", + "params": [ + { + "name": "gl", + "description": "", + "type": "WebGLContext" + } + ], + "class": "WebGLBatch" + }, + { + "file": "src/pixi/renderers/webgl/WebGLBatch.js", + "line": 105, "description": "inits the batch's texture and blend mode based if the supplied sprite", "itemtype": "method", "name": "init", "params": [ { "name": "sprite", - "description": "the first sprite to be added to the batch. Only sprites with the same base texture and blend mode will be allowed to be added to this batch", + "description": "the first sprite to be added to the batch. Only sprites with\n\t\tthe same base texture and blend mode will be allowed to be added to this batch", "type": "Sprite" } ], @@ -2854,7 +4084,7 @@ }, { "file": "src/pixi/renderers/webgl/WebGLBatch.js", - "line": 117, + "line": 125, "description": "inserts a sprite before the specified sprite", "itemtype": "method", "name": "insertBefore", @@ -2874,7 +4104,7 @@ }, { "file": "src/pixi/renderers/webgl/WebGLBatch.js", - "line": 145, + "line": 153, "description": "inserts a sprite after the specified sprite", "itemtype": "method", "name": "insertAfter", @@ -2894,7 +4124,7 @@ }, { "file": "src/pixi/renderers/webgl/WebGLBatch.js", - "line": 175, + "line": 182, "description": "removes a sprite from the batch", "itemtype": "method", "name": "remove", @@ -2909,7 +4139,7 @@ }, { "file": "src/pixi/renderers/webgl/WebGLBatch.js", - "line": 218, + "line": 226, "description": "Splits the batch into two with the specified sprite being the start of the new batch.", "itemtype": "method", "name": "split", @@ -2928,7 +4158,7 @@ }, { "file": "src/pixi/renderers/webgl/WebGLBatch.js", - "line": 268, + "line": 267, "description": "Merges two batchs together", "itemtype": "method", "name": "merge", @@ -2943,14 +4173,15 @@ }, { "file": "src/pixi/renderers/webgl/WebGLBatch.js", - "line": 293, - "description": "Grows the size of the batch. As the elements in the batch cannot have a dynamic size this function is used to increase the size of the batch. It also creates a little extra room so that the batch does not need to be resized every time a sprite is added", - "methos": "growBatch", + "line": 292, + "description": "Grows the size of the batch. As the elements in the batch cannot have a dynamic size this\nfunction is used to increase the size of the batch. It also creates a little extra room so\nthat the batch does not need to be resized every time a sprite is added", + "itemtype": "method", + "name": "growBatch", "class": "WebGLBatch" }, { "file": "src/pixi/renderers/webgl/WebGLBatch.js", - "line": 346, + "line": 347, "description": "Refresh's all the data in the batch and sync's it with the webGL buffers", "itemtype": "method", "name": "refresh", @@ -2958,7 +4189,7 @@ }, { "file": "src/pixi/renderers/webgl/WebGLBatch.js", - "line": 401, + "line": 403, "description": "Updates all the relevant geometry and uploads the data to the GPU", "itemtype": "method", "name": "update", @@ -2966,18 +4197,157 @@ }, { "file": "src/pixi/renderers/webgl/WebGLBatch.js", - "line": 513, + "line": 508, "description": "Draws the batch to the frame buffer", "itemtype": "method", "name": "render", "class": "WebGLBatch" }, + { + "file": "src/pixi/renderers/webgl/WebGLFilterManager.js", + "line": 1, + "author": "Mat Groves http://matgroves.com/ @Doormat23", + "class": "CanvasGraphics" + }, { "file": "src/pixi/renderers/webgl/WebGLGraphics.js", "line": 1, "author": "Mat Groves http://matgroves.com/ @Doormat23", "class": "CanvasGraphics" }, + { + "file": "src/pixi/renderers/webgl/WebGLGraphics.js", + "line": 15, + "description": "Renders the graphics object", + "static": 1, + "access": "private", + "tagname": "", + "itemtype": "method", + "name": "renderGraphics", + "params": [ + { + "name": "graphics", + "description": "", + "type": "Graphics" + }, + { + "name": "projection", + "description": "", + "type": "Object" + } + ], + "class": "CanvasGraphics" + }, + { + "file": "src/pixi/renderers/webgl/WebGLGraphics.js", + "line": 87, + "description": "Updates the graphics object", + "static": 1, + "access": "private", + "tagname": "", + "itemtype": "method", + "name": "updateGraphics", + "params": [ + { + "name": "graphics", + "description": "", + "type": "Graphics" + } + ], + "class": "CanvasGraphics" + }, + { + "file": "src/pixi/renderers/webgl/WebGLGraphics.js", + "line": 139, + "description": "Builds a rectangle to draw", + "static": 1, + "access": "private", + "tagname": "", + "itemtype": "method", + "name": "buildRectangle", + "params": [ + { + "name": "graphics", + "description": "", + "type": "Graphics" + }, + { + "name": "webGLData", + "description": "", + "type": "Object" + } + ], + "class": "CanvasGraphics" + }, + { + "file": "src/pixi/renderers/webgl/WebGLGraphics.js", + "line": 204, + "description": "Builds a circle to draw", + "static": 1, + "access": "private", + "tagname": "", + "itemtype": "method", + "name": "buildCircle", + "params": [ + { + "name": "graphics", + "description": "", + "type": "Graphics" + }, + { + "name": "webGLData", + "description": "", + "type": "Object" + } + ], + "class": "CanvasGraphics" + }, + { + "file": "src/pixi/renderers/webgl/WebGLGraphics.js", + "line": 272, + "description": "Builds a line to draw", + "static": 1, + "access": "private", + "tagname": "", + "itemtype": "method", + "name": "buildLine", + "params": [ + { + "name": "graphics", + "description": "", + "type": "Graphics" + }, + { + "name": "webGLData", + "description": "", + "type": "Object" + } + ], + "class": "CanvasGraphics" + }, + { + "file": "src/pixi/renderers/webgl/WebGLGraphics.js", + "line": 463, + "description": "Builds a polygon to draw", + "static": 1, + "access": "private", + "tagname": "", + "itemtype": "method", + "name": "buildPoly", + "params": [ + { + "name": "graphics", + "description": "", + "type": "Graphics" + }, + { + "name": "webGLData", + "description": "", + "type": "Object" + } + ], + "class": "CanvasGraphics" + }, { "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", "line": 1, @@ -2986,35 +4356,315 @@ }, { "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", - "line": 725, + "line": 33, + "description": "Add a display object to the webgl renderer", + "itemtype": "method", + "name": "setRenderable", + "params": [ + { + "name": "displayObject", + "description": "", + "type": "DisplayObject" + } + ], "access": "private", "tagname": "", "class": "WebGLBatch" }, { "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", - "line": 732, + "line": 55, + "description": "Renders the stage to its webgl view", + "itemtype": "method", + "name": "render", + "params": [ + { + "name": "projection", + "description": "", + "type": "Object" + } + ], + "class": "WebGLBatch" + }, + { + "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", + "line": 91, + "description": "Renders a specific displayObject", + "itemtype": "method", + "name": "renderSpecific", + "params": [ + { + "name": "displayObject", + "description": "", + "type": "DisplayObject" + }, + { + "name": "projection", + "description": "", + "type": "Object" + } + ], "access": "private", "tagname": "", "class": "WebGLBatch" }, { "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", - "line": 787, + "line": 251, + "description": "Renders a specific renderable", + "itemtype": "method", + "name": "renderSpecial", + "params": [ + { + "name": "renderable", + "description": "", + "type": "DisplayObject" + }, + { + "name": "projection", + "description": "", + "type": "Object" + } + ], "access": "private", "tagname": "", "class": "WebGLBatch" }, { "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", - "line": 875, + "line": 334, + "description": "Updates a webgl texture", + "itemtype": "method", + "name": "updateTexture", + "params": [ + { + "name": "displayObject", + "description": "", + "type": "DisplayObject" + } + ], "access": "private", "tagname": "", "class": "WebGLBatch" }, { "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", - "line": 912, + "line": 376, + "description": "Adds filter blocks", + "itemtype": "method", + "name": "addFilterBlocks", + "params": [ + { + "name": "start", + "description": "", + "type": "FilterBlock" + }, + { + "name": "end", + "description": "", + "type": "FilterBlock" + } + ], + "access": "private", + "tagname": "", + "class": "WebGLBatch" + }, + { + "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", + "line": 416, + "description": "Remove filter blocks", + "itemtype": "method", + "name": "removeFilterBlocks", + "params": [ + { + "name": "start", + "description": "", + "type": "FilterBlock" + }, + { + "name": "end", + "description": "", + "type": "FilterBlock" + } + ], + "access": "private", + "tagname": "", + "class": "WebGLBatch" + }, + { + "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", + "line": 430, + "description": "Adds a display object and children to the webgl context", + "itemtype": "method", + "name": "addDisplayObjectAndChildren", + "params": [ + { + "name": "displayObject", + "description": "", + "type": "DisplayObject" + } + ], + "access": "private", + "tagname": "", + "class": "WebGLBatch" + }, + { + "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", + "line": 487, + "description": "Removes a display object and children to the webgl context", + "itemtype": "method", + "name": "removeDisplayObjectAndChildren", + "params": [ + { + "name": "displayObject", + "description": "", + "type": "DisplayObject" + } + ], + "access": "private", + "tagname": "", + "class": "WebGLBatch" + }, + { + "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", + "line": 509, + "description": "Inserts a displayObject into the linked list", + "itemtype": "method", + "name": "insertObject", + "params": [ + { + "name": "displayObject", + "description": "", + "type": "DisplayObject" + }, + { + "name": "previousObject", + "description": "", + "type": "DisplayObject" + }, + { + "name": "nextObject", + "description": "", + "type": "DisplayObject" + } + ], + "access": "private", + "tagname": "", + "class": "WebGLBatch" + }, + { + "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", + "line": 647, + "description": "Inserts a displayObject into the linked list", + "itemtype": "method", + "name": "insertAfter", + "params": [ + { + "name": "item", + "description": "", + "type": "DisplayObject" + }, + { + "name": "displayObject", + "description": "The object to insert", + "type": "DisplayObject" + } + ], + "access": "private", + "tagname": "", + "class": "WebGLBatch" + }, + { + "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", + "line": 702, + "description": "Removes a displayObject from the linked list", + "itemtype": "method", + "name": "removeObject", + "params": [ + { + "name": "displayObject", + "description": "The object to remove", + "type": "DisplayObject" + } + ], + "access": "private", + "tagname": "", + "class": "WebGLBatch" + }, + { + "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", + "line": 781, + "description": "Initializes a tiling sprite", + "itemtype": "method", + "name": "initTilingSprite", + "params": [ + { + "name": "sprite", + "description": "The tiling sprite to initialize", + "type": "TilingSprite" + } + ], + "access": "private", + "tagname": "", + "class": "WebGLBatch" + }, + { + "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", + "line": 840, + "description": "Renders a Strip", + "itemtype": "method", + "name": "renderStrip", + "params": [ + { + "name": "strip", + "description": "The strip to render", + "type": "Strip" + }, + { + "name": "projection", + "description": "", + "type": "Object" + } + ], + "access": "private", + "tagname": "", + "class": "WebGLBatch" + }, + { + "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", + "line": 932, + "description": "Renders a TilingSprite", + "itemtype": "method", + "name": "renderTilingSprite", + "params": [ + { + "name": "sprite", + "description": "The tiling sprite to render", + "type": "TilingSprite" + }, + { + "name": "projectionMatrix", + "description": "", + "type": "Object" + } + ], + "access": "private", + "tagname": "", + "class": "WebGLBatch" + }, + { + "file": "src/pixi/renderers/webgl/WebGLRenderGroup.js", + "line": 974, + "description": "Initializes a strip to be rendered", + "itemtype": "method", + "name": "initStrip", + "params": [ + { + "name": "strip", + "description": "The strip to initialize", + "type": "Strip" + } + ], "access": "private", "tagname": "", "class": "WebGLBatch" @@ -3027,35 +4677,47 @@ }, { "file": "src/pixi/renderers/webgl/WebGLRenderer.js", - "line": 90, + "line": 104, + "description": "Gets a new WebGLBatch from the pool", + "static": 1, + "itemtype": "method", + "name": "getBatch", + "return": { + "description": "", + "type": "WebGLBatch" + }, "access": "private", "tagname": "", "class": "WebGLRenderer" }, { "file": "src/pixi/renderers/webgl/WebGLRenderer.js", - "line": 105, + "line": 124, + "description": "Puts a batch back into the pool", + "static": 1, + "itemtype": "method", + "name": "returnBatch", + "params": [ + { + "name": "batch", + "description": "The batch to return", + "type": "WebGLBatch" + } + ], "access": "private", "tagname": "", "class": "WebGLRenderer" }, { "file": "src/pixi/renderers/webgl/WebGLRenderer.js", - "line": 115, - "access": "private", - "tagname": "", - "class": "WebGLRenderer" - }, - { - "file": "src/pixi/renderers/webgl/WebGLRenderer.js", - "line": 121, + "line": 138, "description": "Renders the stage to its webGL view", "itemtype": "method", "name": "render", "params": [ { "name": "stage", - "description": "the PIXI.Stage element to be rendered", + "description": "the Stage element to be rendered", "type": "Stage" } ], @@ -3063,14 +4725,53 @@ }, { "file": "src/pixi/renderers/webgl/WebGLRenderer.js", - "line": 204, + "line": 209, + "description": "Updates the textures loaded into this webgl renderer", + "static": 1, + "itemtype": "method", + "name": "updateTextures", "access": "private", "tagname": "", "class": "WebGLRenderer" }, { "file": "src/pixi/renderers/webgl/WebGLRenderer.js", - "line": 263, + "line": 225, + "description": "Updates a loaded webgl texture", + "static": 1, + "itemtype": "method", + "name": "updateTexture", + "params": [ + { + "name": "texture", + "description": "The texture to update", + "type": "Texture" + } + ], + "access": "private", + "tagname": "", + "class": "WebGLRenderer" + }, + { + "file": "src/pixi/renderers/webgl/WebGLRenderer.js", + "line": 269, + "description": "Destroys a loaded webgl texture", + "itemtype": "method", + "name": "destroyTexture", + "params": [ + { + "name": "texture", + "description": "The texture to update", + "type": "Texture" + } + ], + "access": "private", + "tagname": "", + "class": "WebGLRenderer" + }, + { + "file": "src/pixi/renderers/webgl/WebGLRenderer.js", + "line": 288, "description": "resizes the webGL view to the specified width and height", "itemtype": "method", "name": "resize", @@ -3090,21 +4791,41 @@ }, { "file": "src/pixi/renderers/webgl/WebGLRenderer.js", - "line": 290, + "line": 319, + "description": "Handles a lost webgl context", + "itemtype": "method", + "name": "handleContextLost", + "params": [ + { + "name": "event", + "description": "", + "type": "Event" + } + ], "access": "private", "tagname": "", "class": "WebGLRenderer" }, { "file": "src/pixi/renderers/webgl/WebGLRenderer.js", - "line": 299, + "line": 332, + "description": "Handles a restored webgl context", + "itemtype": "method", + "name": "handleContextRestored", + "params": [ + { + "name": "event", + "description": "", + "type": "Event" + } + ], "access": "private", "tagname": "", "class": "WebGLRenderer" }, { "file": "src/pixi/renderers/webgl/WebGLShaders.js", - "line": 2, + "line": 1, "author": "Mat Groves http://matgroves.com/ @Doormat23", "class": "BitmapText" }, @@ -3116,7 +4837,7 @@ }, { "file": "src/pixi/text/BitmapText.js", - "line": 33, + "line": 34, "description": "Set the copy for the text object", "itemtype": "method", "name": "setText", @@ -3131,7 +4852,7 @@ }, { "file": "src/pixi/text/BitmapText.js", - "line": 44, + "line": 46, "description": "Set the style of the text", "itemtype": "method", "name": "setStyle", @@ -3160,15 +4881,20 @@ }, { "file": "src/pixi/text/BitmapText.js", - "line": 64, + "line": 67, "description": "Renders text", + "itemtype": "method", + "name": "updateText", "access": "private", "tagname": "", "class": "BitmapText" }, { "file": "src/pixi/text/BitmapText.js", - "line": 137, + "line": 142, + "description": "Updates the transfor of this object", + "itemtype": "method", + "name": "updateTransform", "access": "private", "tagname": "", "class": "BitmapText" @@ -3181,7 +4907,7 @@ }, { "file": "src/pixi/text/Text.js", - "line": 37, + "line": 38, "description": "Set the style of the text", "itemtype": "method", "name": "setStyle", @@ -3238,7 +4964,7 @@ }, { "name": "[style.font=\"bold", - "description": "20pt Arial\"] The style and size of the font", + "description": "20pt Arial\"] The style and size of the font", "type": "String" } ], @@ -3246,7 +4972,7 @@ }, { "file": "src/pixi/text/Text.js", - "line": 63, + "line": 65, "description": "Set the copy for the text object. To split a line you can use \"\\n\"", "methos": "setText", "params": [ @@ -3260,35 +4986,66 @@ }, { "file": "src/pixi/text/Text.js", - "line": 74, + "line": 77, "description": "Renders text", + "itemtype": "method", + "name": "updateText", "access": "private", "tagname": "", "class": "Text" }, { "file": "src/pixi/text/Text.js", - "line": 143, + "line": 148, "description": "Updates texture size based on canvas size", + "itemtype": "method", + "name": "updateTexture", "access": "private", "tagname": "", "class": "Text" }, { "file": "src/pixi/text/Text.js", - "line": 161, + "line": 167, + "description": "Updates the transfor of this object", + "itemtype": "method", + "name": "updateTransform", "access": "private", "tagname": "", "class": "Text" }, { "file": "src/pixi/text/Text.js", - "line": 203, + "line": 216, "description": "A Text Object will apply wordwrap", + "itemtype": "method", + "name": "wordWrap", + "params": [ + { + "name": "text", + "description": "", + "type": "String" + } + ], "access": "private", "tagname": "", "class": "Text" }, + { + "file": "src/pixi/text/Text.js", + "line": 270, + "description": "Destroys this text object", + "itemtype": "method", + "name": "destroy", + "params": [ + { + "name": "destroyTexture", + "description": "", + "type": "Boolean" + } + ], + "class": "Text" + }, { "file": "src/pixi/textures/BaseTexture.js", "line": 1, @@ -3297,25 +5054,37 @@ }, { "file": "src/pixi/textures/BaseTexture.js", - "line": 27, - "description": "[read only] The width of the base texture set when the image has loaded", + "line": 21, + "description": "[read-only] The width of the base texture set when the image has loaded", "itemtype": "property", "name": "width", "type": "Number", + "readonly": "", "class": "BaseTexture" }, { "file": "src/pixi/textures/BaseTexture.js", - "line": 33, - "description": "[read only] The height of the base texture set when the image has loaded", + "line": 30, + "description": "[read-only] The height of the base texture set when the image has loaded", "itemtype": "property", "name": "height", "type": "Number", + "readonly": "", "class": "BaseTexture" }, { "file": "src/pixi/textures/BaseTexture.js", - "line": 40, + "line": 39, + "description": "[read-only] Describes if the base texture has loaded or not", + "itemtype": "property", + "name": "hasLoaded", + "type": "Boolean", + "readonly": "", + "class": "BaseTexture" + }, + { + "file": "src/pixi/textures/BaseTexture.js", + "line": 48, "description": "The source that is loaded to create the texture", "itemtype": "property", "name": "source", @@ -3324,8 +5093,16 @@ }, { "file": "src/pixi/textures/BaseTexture.js", - "line": 101, - "description": "Helper function that returns a base texture based on an image url\n If the image is not in the base texture cache it will be created and loaded", + "line": 99, + "description": "Destroys this base texture", + "itemtype": "method", + "name": "destroy", + "class": "BaseTexture" + }, + { + "file": "src/pixi/textures/BaseTexture.js", + "line": 114, + "description": "Helper function that returns a base texture based on an image url\nIf the image is not in the base texture cache it will be created and loaded", "static": 1, "itemtype": "method", "name": "fromImage", @@ -3349,14 +5126,34 @@ }, { "file": "src/pixi/textures/RenderTexture.js", - "line": 112, + "line": 57, + "description": "Initializes the webgl data for this texture", + "itemtype": "method", + "name": "initWebGL", + "access": "private", + "tagname": "", + "class": "RenderTexture" + }, + { + "file": "src/pixi/textures/RenderTexture.js", + "line": 125, + "description": "Initializes the canvas data for this texture", + "itemtype": "method", + "name": "initCanvas", + "access": "private", + "tagname": "", + "class": "RenderTexture" + }, + { + "file": "src/pixi/textures/RenderTexture.js", + "line": 141, "description": "This function will draw the display object to the texture.", "itemtype": "method", - "name": "render", + "name": "renderWebGL", "params": [ { "name": "displayObject", - "description": "", + "description": "The display object to render this texture on", "type": "DisplayObject" }, { @@ -3365,6 +5162,30 @@ "type": "Boolean" } ], + "access": "private", + "tagname": "", + "class": "RenderTexture" + }, + { + "file": "src/pixi/textures/RenderTexture.js", + "line": 214, + "description": "This function will draw the display object to the texture.", + "itemtype": "method", + "name": "renderCanvas", + "params": [ + { + "name": "displayObject", + "description": "The display object to render this texture on", + "type": "DisplayObject" + }, + { + "name": "clear", + "description": "If true the texture will be cleared before the displayObject is drawn", + "type": "Boolean" + } + ], + "access": "private", + "tagname": "", "class": "RenderTexture" }, { @@ -3384,23 +5205,63 @@ }, { "file": "src/pixi/textures/Texture.js", - "line": 40, + "line": 39, "description": "The frame specifies the region of the base texture that this texture uses", "itemtype": "property", "name": "frame", - "type": "#Rectangle", + "type": "Rectangle", "class": "Texture" }, { "file": "src/pixi/textures/Texture.js", - "line": 83, + "line": 47, + "description": "The trim point", + "itemtype": "property", + "name": "trim", + "type": "Point", + "class": "Texture" + }, + { + "file": "src/pixi/textures/Texture.js", + "line": 73, + "description": "Called when the base texture is loaded", + "itemtype": "method", + "name": "onBaseTextureLoaded", + "params": [ + { + "name": "event", + "description": "" + } + ], + "access": "private", + "tagname": "", + "class": "Texture" + }, + { + "file": "src/pixi/textures/Texture.js", + "line": 93, + "description": "Destroys this texture", + "itemtype": "method", + "name": "destroy", + "params": [ + { + "name": "destroyBase", + "description": "Whether to destroy the base texture as well", + "type": "Boolean" + } + ], + "class": "Texture" + }, + { + "file": "src/pixi/textures/Texture.js", + "line": 104, "description": "Specifies the rectangle region of the baseTexture", "itemtype": "method", "name": "setFrame", "params": [ { "name": "frame", - "description": "", + "description": "The frame of the texture to set it to", "type": "Rectangle" } ], @@ -3408,8 +5269,8 @@ }, { "file": "src/pixi/textures/Texture.js", - "line": 105, - "description": "Helper function that returns a texture based on an image url\n If the image is not in the texture cache it will be created and loaded", + "line": 127, + "description": "Helper function that returns a texture based on an image url\nIf the image is not in the texture cache it will be created and loaded", "static": 1, "itemtype": "method", "name": "fromImage", @@ -3418,6 +5279,11 @@ "name": "imageUrl", "description": "The image url of the texture", "type": "String" + }, + { + "name": "crossorigin", + "description": "Whether requests should be treated as crossorigin", + "type": "Boolean" } ], "return": { @@ -3427,8 +5293,9 @@ }, { "file": "src/pixi/textures/Texture.js", - "line": 127, - "description": "Helper function that returns a texture based on a frame id\n If the frame id is not in the texture cache an error will be thrown", + "line": 150, + "description": "Helper function that returns a texture based on a frame id\nIf the frame id is not in the texture cache an error will be thrown", + "static": 1, "itemtype": "method", "name": "fromFrame", "params": [ @@ -3445,8 +5312,8 @@ }, { "file": "src/pixi/textures/Texture.js", - "line": 142, - "description": "Helper function that returns a texture based on a canvas element\n If the canvas is not in the texture cache it will be created and loaded", + "line": 166, + "description": "Helper function that returns a texture based on a canvas element\nIf the canvas is not in the texture cache it will be created and loaded", "static": 1, "itemtype": "method", "name": "fromCanvas", @@ -3464,7 +5331,7 @@ }, { "file": "src/pixi/textures/Texture.js", - "line": 158, + "line": 182, "description": "Adds a texture to the textureCache.", "static": 1, "itemtype": "method", @@ -3485,7 +5352,7 @@ }, { "file": "src/pixi/textures/Texture.js", - "line": 171, + "line": 195, "description": "Remove a texture from the textureCache.", "static": 1, "itemtype": "method", @@ -3507,12 +5374,12 @@ "file": "src/pixi/utils/Detector.js", "line": 1, "author": "Mat Groves http://matgroves.com/ @Doormat23", - "class": "InteractionManager" + "class": "EventTarget" }, { "file": "src/pixi/utils/Detector.js", "line": 5, - "description": "This helper function will automatically detect which renderer you should be using.\nWebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by the browser then this function will return a canvas renderer", + "description": "This helper function will automatically detect which renderer you should be using.\nWebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by\nthe browser then this function will return a canvas renderer", "itemtype": "method", "name": "autoDetectRenderer", "static": 1, @@ -3533,89 +5400,348 @@ "type": "Canvas" }, { - "name": "transparent", + "name": "transparent=false", "description": "the transparency of the render view, default false", "type": "Boolean" + }, + { + "name": "antialias=false", + "description": "sets antialias (only applicable in webGL chrome at the moment)\n\nantialias", + "type": "Boolean" } ], - "default": "false", - "class": "InteractionManager" + "class": "EventTarget" }, { "file": "src/pixi/utils/EventTarget.js", "line": 1, "description": "https://github.com/mrdoob/eventtarget.js/\nTHankS mr DOob!", - "class": "InteractionManager" + "class": "EventTarget" + }, + { + "file": "src/pixi/utils/Polyk.js", + "line": 36, + "description": "Triangulates shapes for webGL graphic fills", + "itemtype": "method", + "name": "Triangulate", + "is_constructor": 1, + "class": "PolyK._PointInTriangle", + "namespace": "PolyK" }, { "file": "src/pixi/utils/Utils.js", - "line": 38, - "description": "Provides bind in a cross browser way.", - "class": "InteractionManager" + "line": 8, + "description": "A polyfill for requestAnimationFrame", + "itemtype": "method", + "name": "requestAnimationFrame", + "class": "PolyK.AjaxRequest", + "namespace": "PolyK" + }, + { + "file": "src/pixi/utils/Utils.js", + "line": 13, + "description": "A polyfill for cancelAnimationFrame", + "itemtype": "method", + "name": "cancelAnimationFrame", + "class": "PolyK.AjaxRequest", + "namespace": "PolyK" + }, + { + "file": "src/pixi/utils/Utils.js", + "line": 43, + "description": "Converts a hex color number to an [R, G, B] array", + "itemtype": "method", + "name": "HEXtoRGB", + "params": [ + { + "name": "hex", + "description": "", + "type": "Number" + } + ], + "class": "PolyK.AjaxRequest", + "namespace": "PolyK" + }, + { + "file": "src/pixi/utils/Utils.js", + "line": 53, + "description": "A polyfill for Function.prototype.bind", + "itemtype": "method", + "name": "bind", + "class": "PolyK.AjaxRequest", + "namespace": "PolyK" }, { "file": "src/pixi/InteractionManager.js", "line": 1, "author": "Mat Groves http://matgroves.com/ @Doormat23", - "class": "InteractionManager" + "class": "PolyK.InteractionManager", + "namespace": "PolyK" }, { "file": "src/pixi/InteractionManager.js", - "line": 17, + "line": 15, "description": "a refference to the stage", "itemtype": "property", "name": "stage", "type": "Stage", - "class": "InteractionManager" + "class": "PolyK.InteractionManager", + "namespace": "PolyK" }, { "file": "src/pixi/InteractionManager.js", - "line": 30, + "line": 23, "description": "the mouse data", "itemtype": "property", "name": "mouse", "type": "InteractionData", - "class": "InteractionManager" + "class": "PolyK.InteractionManager", + "namespace": "PolyK" }, { "file": "src/pixi/InteractionManager.js", - "line": 37, + "line": 31, "description": "an object that stores current touches (InteractionData) by id reference", "itemtype": "property", "name": "touchs", "type": "Object", - "class": "InteractionManager" + "class": "PolyK.InteractionManager", + "namespace": "PolyK" }, { "file": "src/pixi/InteractionManager.js", - "line": 499, + "line": 70, + "description": "Collects an interactive sprite recursively to have their interactions managed", + "itemtype": "method", + "name": "collectInteractiveSprite", + "params": [ + { + "name": "displayObject", + "description": "the displayObject to collect", + "type": "DisplayObject" + }, + { + "name": "iParent", + "description": "", + "type": "DisplayObject" + } + ], + "access": "private", + "tagname": "", + "class": "PolyK.InteractionManager", + "namespace": "PolyK" + }, + { + "file": "src/pixi/InteractionManager.js", + "line": 114, + "description": "Sets the target for event delegation", + "itemtype": "method", + "name": "setTarget", + "params": [ + { + "name": "target", + "description": "the renderer to bind events to", + "type": "WebGLRenderer|CanvasRenderer" + } + ], + "access": "private", + "tagname": "", + "class": "PolyK.InteractionManager", + "namespace": "PolyK" + }, + { + "file": "src/pixi/InteractionManager.js", + "line": 135, + "description": "Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM\nelements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element\nto receive those events", + "itemtype": "method", + "name": "setTargetDomElement", + "params": [ + { + "name": "domElement", + "description": "the dom element which will receive mouse and touch events", + "type": "DOMElement" + } + ], + "access": "private", + "tagname": "", + "class": "PolyK.InteractionManager", + "namespace": "PolyK" + }, + { + "file": "src/pixi/InteractionManager.js", + "line": 185, + "description": "updates the state of interactive objects", + "itemtype": "method", + "name": "update", + "access": "private", + "tagname": "", + "class": "PolyK.InteractionManager", + "namespace": "PolyK" + }, + { + "file": "src/pixi/InteractionManager.js", + "line": 273, + "description": "Is called when the mouse moves accross the renderer element", + "itemtype": "method", + "name": "onMouseMove", + "params": [ + { + "name": "event", + "description": "The DOM event of the mouse moving", + "type": "Event" + } + ], + "access": "private", + "tagname": "", + "class": "PolyK.InteractionManager", + "namespace": "PolyK" + }, + { + "file": "src/pixi/InteractionManager.js", + "line": 305, + "description": "Is called when the mouse button is pressed down on the renderer element", + "itemtype": "method", + "name": "onMouseDown", + "params": [ + { + "name": "event", + "description": "The DOM event of a mouse button being pressed down", + "type": "Event" + } + ], + "access": "private", + "tagname": "", + "class": "PolyK.InteractionManager", + "namespace": "PolyK" + }, + { + "file": "src/pixi/InteractionManager.js", + "line": 370, + "description": "Is called when the mouse button is released on the renderer element", + "itemtype": "method", + "name": "onMouseUp", + "params": [ + { + "name": "event", + "description": "The DOM event of a mouse button being released", + "type": "Event" + } + ], + "access": "private", + "tagname": "", + "class": "PolyK.InteractionManager", + "namespace": "PolyK" + }, + { + "file": "src/pixi/InteractionManager.js", + "line": 422, + "description": "Tests if the current mouse coords hit a sprite", + "itemtype": "method", + "name": "hitTest", + "params": [ + { + "name": "item", + "description": "The displayObject to test for a hit", + "type": "DisplayObject" + }, + { + "name": "interactionData", + "description": "The interactiondata object to update in the case of a hit", + "type": "InteractionData" + } + ], + "access": "private", + "tagname": "", + "class": "PolyK.InteractionManager", + "namespace": "PolyK" + }, + { + "file": "src/pixi/InteractionManager.js", + "line": 495, + "description": "Is called when a touch is moved accross the renderer element", + "itemtype": "method", + "name": "onTouchMove", + "params": [ + { + "name": "event", + "description": "The DOM event of a touch moving accross the renderer view", + "type": "Event" + } + ], + "access": "private", + "tagname": "", + "class": "PolyK.InteractionManager", + "namespace": "PolyK" + }, + { + "file": "src/pixi/InteractionManager.js", + "line": 526, + "description": "Is called when a touch is started on the renderer element", + "itemtype": "method", + "name": "onTouchStart", + "params": [ + { + "name": "event", + "description": "The DOM event of a touch starting on the renderer view", + "type": "Event" + } + ], + "access": "private", + "tagname": "", + "class": "PolyK.InteractionManager", + "namespace": "PolyK" + }, + { + "file": "src/pixi/InteractionManager.js", + "line": 575, + "description": "Is called when a touch is ended on the renderer element", + "itemtype": "method", + "name": "onTouchEnd", + "params": [ + { + "name": "event", + "description": "The DOM event of a touch ending on the renderer view", + "type": "Event" + } + ], + "access": "private", + "tagname": "", + "class": "PolyK.InteractionManager", + "namespace": "PolyK" + }, + { + "file": "src/pixi/InteractionManager.js", + "line": 654, "description": "This point stores the global coords of where the touch/mouse event happened", "itemtype": "property", "name": "global", "type": "Point", - "class": "InteractionData" + "class": "PolyK.InteractionData", + "namespace": "PolyK" }, { "file": "src/pixi/InteractionManager.js", - "line": 509, + "line": 665, "description": "The target Sprite that was interacted with", "itemtype": "property", "name": "target", "type": "Sprite", - "class": "InteractionData" + "class": "PolyK.InteractionData", + "namespace": "PolyK" }, { "file": "src/pixi/InteractionManager.js", - "line": 516, + "line": 673, "description": "When passed to an event handler, this will be the original DOM Event that was captured", "itemtype": "property", "name": "originalEvent", "type": "Event", - "class": "InteractionData" + "class": "PolyK.InteractionData", + "namespace": "PolyK" }, { "file": "src/pixi/InteractionManager.js", - "line": 524, + "line": 682, "description": "This will return the local coords of the specified displayObject for this InteractionData", "itemtype": "method", "name": "getLocalPosition", @@ -3630,39 +5756,67 @@ "description": "A point containing the coords of the InteractionData position relative to the DisplayObject", "type": "Point" }, - "class": "InteractionData" + "class": "PolyK.InteractionData", + "namespace": "PolyK" }, { "file": "src/pixi/Intro.js", "line": 1, "author": "Mat Groves http://matgroves.com/ @Doormat23", - "class": "" + "class": "", + "namespace": "PolyK" }, { "file": "src/pixi/Outro.js", "line": 1, "author": "Mat Groves http://matgroves.com/ @Doormat23", - "class": "" + "class": "", + "namespace": "PolyK" }, { "file": "src/pixi/Pixi.js", "line": 1, "author": "Mat Groves http://matgroves.com/ @Doormat23", - "class": "" + "class": "", + "namespace": "PolyK" } ], "warnings": [ { - "message": "unknown tag: internal", - "line": " src/pixi/display/Stage.js:42" + "message": "unknown tag: contructor", + "line": " src/pixi/filters/BlurFilter.js:6" + }, + { + "message": "unknown tag: contructor", + "line": " src/pixi/filters/ColorMatrixFilter.js:5" + }, + { + "message": "unknown tag: contructor", + "line": " src/pixi/filters/DisplacementFilter.js:6" + }, + { + "message": "unknown tag: contructor", + "line": " src/pixi/filters/GreyFilter.js:6" + }, + { + "message": "unknown tag: contructor", + "line": " src/pixi/filters/InvertFilter.js:5" + }, + { + "message": "unknown tag: contructor", + "line": " src/pixi/filters/PixelateFilter.js:5" + }, + { + "message": "unknown tag: contructor", + "line": " src/pixi/filters/SepiaFilter.js:7" + }, + { + "message": "unknown tag: contructor", + "line": " src/pixi/renderers/webgl/WebGLRenderGroup.js:5" }, { "message": "unknown tag: methos", - "line": " src/pixi/renderers/webgl/WebGLBatch.js:293" - }, - { - "message": "unknown tag: methos", - "line": " src/pixi/text/Text.js:63" + "line": " src/pixi/text/Text.js:65" }, { "message": "Missing item type", @@ -3688,18 +5842,10 @@ "message": "Missing item type", "line": " src/pixi/display/DisplayObject.js:1" }, - { - "message": "Missing item type", - "line": " src/pixi/display/DisplayObject.js:399" - }, { "message": "Missing item type", "line": " src/pixi/display/DisplayObjectContainer.js:1" }, - { - "message": "Missing item type", - "line": " src/pixi/display/DisplayObjectContainer.js:358" - }, { "message": "Missing item type", "line": " src/pixi/display/MovieClip.js:1" @@ -3708,10 +5854,6 @@ "message": "Missing item type", "line": " src/pixi/display/Sprite.js:1" }, - { - "message": "Missing item type", - "line": " src/pixi/display/Sprite.js:119" - }, { "message": "Missing item type", "line": " src/pixi/display/Stage.js:1" @@ -3730,15 +5872,7 @@ }, { "message": "Missing item type\ncx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of", - "line": " src/pixi/extras/Spine.js:308" - }, - { - "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:604" - }, - { - "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:611" + "line": " src/pixi/extras/Spine.js:327" }, { "message": "Missing item type", @@ -3746,11 +5880,11 @@ }, { "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:626" + "line": " src/pixi/extras/Spine.js:625" }, { "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:633" + "line": " src/pixi/extras/Spine.js:632" }, { "message": "Missing item type", @@ -3758,23 +5892,23 @@ }, { "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:675" + "line": " src/pixi/extras/Spine.js:647" }, { "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:683" + "line": " src/pixi/extras/Spine.js:654" }, { "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:698" + "line": " src/pixi/extras/Spine.js:689" }, { "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:702" + "line": " src/pixi/extras/Spine.js:697" }, { "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:709" + "line": " src/pixi/extras/Spine.js:712" }, { "message": "Missing item type", @@ -3784,29 +5918,29 @@ "message": "Missing item type", "line": " src/pixi/extras/Spine.js:723" }, + { + "message": "Missing item type", + "line": " src/pixi/extras/Spine.js:730" + }, + { + "message": "Missing item type", + "line": " src/pixi/extras/Spine.js:737" + }, { "message": "Missing item type\nfrom the new skin are attached if the corresponding attachment from the old skin was attached.", - "line": " src/pixi/extras/Spine.js:735" + "line": " src/pixi/extras/Spine.js:749" }, { "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:742" + "line": " src/pixi/extras/Spine.js:756" }, { "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:746" + "line": " src/pixi/extras/Spine.js:760" }, { "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:755" - }, - { - "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:948" - }, - { - "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:954" + "line": " src/pixi/extras/Spine.js:769" }, { "message": "Missing item type", @@ -3818,11 +5952,19 @@ }, { "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:984" + "line": " src/pixi/extras/Spine.js:972" }, { "message": "Missing item type", - "line": " src/pixi/extras/Spine.js:1401" + "line": " src/pixi/extras/Spine.js:978" + }, + { + "message": "Missing item type", + "line": " src/pixi/extras/Spine.js:996" + }, + { + "message": "Missing item type", + "line": " src/pixi/extras/Spine.js:1415" }, { "message": "Missing item type", @@ -3832,98 +5974,82 @@ "message": "Missing item type", "line": " src/pixi/extras/TilingSprite.js:1" }, + { + "message": "Missing item type", + "line": " src/pixi/filters/AbstractFilter.js:1" + }, + { + "message": "Missing item type", + "line": " src/pixi/filters/BlurFilter.js:1" + }, + { + "message": "Missing item type", + "line": " src/pixi/filters/BlurXFilter.js:1" + }, + { + "message": "Missing item type", + "line": " src/pixi/filters/BlurYFilter.js:1" + }, + { + "message": "Missing item type", + "line": " src/pixi/filters/ColorMatrixFilter.js:1" + }, + { + "message": "Missing item type", + "line": " src/pixi/filters/DisplacementFilter.js:1" + }, { "message": "Missing item type", "line": " src/pixi/filters/FilterBlock.js:1" }, { "message": "Missing item type", - "line": " src/pixi/filters/MaskFilter.js:1" + "line": " src/pixi/filters/GreyFilter.js:1" + }, + { + "message": "Missing item type", + "line": " src/pixi/filters/InvertFilter.js:1" + }, + { + "message": "Missing item type", + "line": " src/pixi/filters/PixelateFilter.js:1" + }, + { + "message": "Missing item type\n/**\n * @author Mat Groves http://matgroves.com/ @Doormat23", + "line": " src/pixi/filters/SepiaFilter.js:1" + }, + { + "message": "Missing item type", + "line": " src/pixi/filters/SmartBlurFilter.js:1" }, { "message": "Missing item type", "line": " src/pixi/loaders/AssetLoader.js:1" }, - { - "message": "Missing item type\nThis will begin loading the assets sequentially", - "line": " src/pixi/loaders/AssetLoader.js:54" - }, - { - "message": "Missing item type\nInvoked after each file is loaded", - "line": " src/pixi/loaders/AssetLoader.js:82" - }, { "message": "Missing item type", "line": " src/pixi/loaders/BitmapFontLoader.js:1" }, - { - "message": "Missing item type\nThis will begin loading the JSON file", - "line": " src/pixi/loaders/BitmapFontLoader.js:34" - }, - { - "message": "Missing item type\nInvoked when XML file is loaded", - "line": " src/pixi/loaders/BitmapFontLoader.js:51" - }, - { - "message": "Missing item type\nInvoked when all files are loaded (xml/fnt and texture)", - "line": " src/pixi/loaders/BitmapFontLoader.js:121" - }, { "message": "Missing item type", "line": " src/pixi/loaders/ImageLoader.js:1" }, { - "message": "Missing item type\nLoads image or takes it from cache", - "line": " src/pixi/loaders/ImageLoader.js:24" - }, - { - "message": "Missing item type\nInvoked when image file is loaded or it is already cached and ready to use", - "line": " src/pixi/loaders/ImageLoader.js:43" + "message": "Missing item type\nif the image is loaded with loadFramedSpriteSheet\nframes will contain the sprite sheet frames", + "line": " src/pixi/loaders/ImageLoader.js:28" }, { "message": "Missing item type", "line": " src/pixi/loaders/JsonLoader.js:1" }, - { - "message": "Missing item type\nThis will begin loading the JSON file", - "line": " src/pixi/loaders/JsonLoader.js:28" - }, - { - "message": "Missing item type\nInvoke when JSON file is loaded", - "line": " src/pixi/loaders/JsonLoader.js:43" - }, - { - "message": "Missing item type\nInvoke when json file loaded", - "line": " src/pixi/loaders/JsonLoader.js:108" - }, - { - "message": "Missing item type\nInvoke when error occured", - "line": " src/pixi/loaders/JsonLoader.js:120" - }, { "message": "Missing item type", "line": " src/pixi/loaders/SpineLoader.js:1" }, - { - "message": "Missing item type\nInvoke when JSON file is loaded", - "line": " src/pixi/loaders/SpineLoader.js:54" - }, { "message": "Missing item type", "line": " src/pixi/loaders/SpriteSheetLoader.js:1" }, - { - "message": "Missing item type\nThis will begin loading the JSON file", - "line": " src/pixi/loaders/SpriteSheetLoader.js:37" - }, - { - "message": "Missing item type\nInvoke when JSON file is loaded", - "line": " src/pixi/loaders/SpriteSheetLoader.js:50" - }, - { - "message": "Missing item type\nInvoke when all files are loaded (json and texture)", - "line": " src/pixi/loaders/SpriteSheetLoader.js:85" - }, { "message": "Missing item type", "line": " src/pixi/primitives/Graphics.js:1" @@ -3937,24 +6063,16 @@ "line": " src/pixi/renderers/canvas/CanvasRenderer.js:1" }, { - "message": "Missing item type\nresizes the canvas view to the specified width and height", - "line": " src/pixi/renderers/canvas/CanvasRenderer.js:110" + "message": "Missing item type", + "line": " src/pixi/renderers/webgl/PixiShader.js:1" }, { "message": "Missing item type", - "line": " src/pixi/renderers/canvas/CanvasRenderer.js:124" + "line": " src/pixi/renderers/webgl/PrimitiveShader.js:1" }, { "message": "Missing item type", - "line": " src/pixi/renderers/canvas/CanvasRenderer.js:235" - }, - { - "message": "Missing item type", - "line": " src/pixi/renderers/canvas/CanvasRenderer.js:268" - }, - { - "message": "Missing item type", - "line": " src/pixi/renderers/canvas/CanvasRenderer.js:299" + "line": " src/pixi/renderers/webgl/StripShader.js:1" }, { "message": "Missing item type", @@ -3973,12 +6091,8 @@ "line": " src/pixi/renderers/webgl/WebGLBatch.js:31" }, { - "message": "Missing item type\nCleans the batch so that is can be returned to an object pool and reused", - "line": " src/pixi/renderers/webgl/WebGLBatch.js:67" - }, - { - "message": "Missing item type\nGrows the size of the batch. As the elements in the batch cannot have a dynamic size this function is used to increase the size of the batch. It also creates a little extra room so that the batch does not need to be resized every time a sprite is added", - "line": " src/pixi/renderers/webgl/WebGLBatch.js:293" + "message": "Missing item type", + "line": " src/pixi/renderers/webgl/WebGLFilterManager.js:1" }, { "message": "Missing item type", @@ -3988,93 +6102,25 @@ "message": "Missing item type", "line": " src/pixi/renderers/webgl/WebGLRenderGroup.js:1" }, - { - "message": "Missing item type", - "line": " src/pixi/renderers/webgl/WebGLRenderGroup.js:725" - }, - { - "message": "Missing item type", - "line": " src/pixi/renderers/webgl/WebGLRenderGroup.js:732" - }, - { - "message": "Missing item type", - "line": " src/pixi/renderers/webgl/WebGLRenderGroup.js:787" - }, - { - "message": "Missing item type", - "line": " src/pixi/renderers/webgl/WebGLRenderGroup.js:875" - }, - { - "message": "Missing item type", - "line": " src/pixi/renderers/webgl/WebGLRenderGroup.js:912" - }, { "message": "Missing item type", "line": " src/pixi/renderers/webgl/WebGLRenderer.js:1" }, { "message": "Missing item type", - "line": " src/pixi/renderers/webgl/WebGLRenderer.js:90" - }, - { - "message": "Missing item type", - "line": " src/pixi/renderers/webgl/WebGLRenderer.js:105" - }, - { - "message": "Missing item type", - "line": " src/pixi/renderers/webgl/WebGLRenderer.js:115" - }, - { - "message": "Missing item type", - "line": " src/pixi/renderers/webgl/WebGLRenderer.js:204" - }, - { - "message": "Missing item type", - "line": " src/pixi/renderers/webgl/WebGLRenderer.js:290" - }, - { - "message": "Missing item type", - "line": " src/pixi/renderers/webgl/WebGLRenderer.js:299" - }, - { - "message": "Missing item type", - "line": " src/pixi/renderers/webgl/WebGLShaders.js:2" + "line": " src/pixi/renderers/webgl/WebGLShaders.js:1" }, { "message": "Missing item type", "line": " src/pixi/text/BitmapText.js:1" }, - { - "message": "Missing item type\nRenders text", - "line": " src/pixi/text/BitmapText.js:64" - }, - { - "message": "Missing item type", - "line": " src/pixi/text/BitmapText.js:137" - }, { "message": "Missing item type", "line": " src/pixi/text/Text.js:1" }, { "message": "Missing item type\nSet the copy for the text object. To split a line you can use \"\\n\"", - "line": " src/pixi/text/Text.js:63" - }, - { - "message": "Missing item type\nRenders text", - "line": " src/pixi/text/Text.js:74" - }, - { - "message": "Missing item type\nUpdates texture size based on canvas size", - "line": " src/pixi/text/Text.js:143" - }, - { - "message": "Missing item type", - "line": " src/pixi/text/Text.js:161" - }, - { - "message": "Missing item type\nA Text Object will apply wordwrap", - "line": " src/pixi/text/Text.js:203" + "line": " src/pixi/text/Text.js:65" }, { "message": "Missing item type", @@ -4096,10 +6142,6 @@ "message": "Missing item type\nhttps://github.com/mrdoob/eventtarget.js/\nTHankS mr DOob!", "line": " src/pixi/utils/EventTarget.js:1" }, - { - "message": "Missing item type\nProvides bind in a cross browser way.", - "line": " src/pixi/utils/Utils.js:38" - }, { "message": "Missing item type", "line": " src/pixi/InteractionManager.js:1" diff --git a/docs/files/src_pixi_InteractionManager.js.html b/docs/files/src_pixi_InteractionManager.js.html index e30e1a9..224d190 100644 --- a/docs/files/src_pixi_InteractionManager.js.html +++ b/docs/files/src_pixi_InteractionManager.js.html @@ -2,12 +2,12 @@ - src/pixi/InteractionManager.js - Pixi.JS - - - - - + src/pixi/InteractionManager.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,80 +166,103 @@
    -

    File: src/pixi/InteractionManager.js

    +

    File: src/pixi/InteractionManager.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    -
    -
    -
    -/**
    -The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive
    -This manager also supports multitouch.
    -@class InteractionManager
    -@constructor
    -@param stage {Stage}
    -@type Stage
    -*/
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    + 
    + /**
    + * The interaction manager deals with mouse and touch events. Any DisplayObject can be interactive
    + * This manager also supports multitouch.
    + *
    + * @class InteractionManager
    + * @constructor
    + * @param stage {Stage} The stage to handle interactions
    + */
     PIXI.InteractionManager = function(stage)
     {
    -	/**
    +	/**
     	 * a refference to the stage
    +	 *
     	 * @property stage
     	 * @type Stage
    -	 */
    +	 */
     	this.stage = stage;
     
    -	// helpers
    -	this.tempPoint = new PIXI.Point();
    -	//this.tempMatrix =  mat3.create();
    -	
    -	this.mouseoverEnabled = true;
    -	
    -	/**
    -	 * the mouse data 
    +	/**
    +	 * the mouse data
    +	 *
     	 * @property mouse
     	 * @type InteractionData
    -	 */
    +	 */
     	this.mouse = new PIXI.InteractionData();
    -	
    -	/**
    -	 * an object that stores current touches (InteractionData) by id reference 
    +
    +	/**
    +	 * an object that stores current touches (InteractionData) by id reference
    +	 *
     	 * @property touchs
     	 * @type Object
    -	 */
    +	 */
     	this.touchs = {};
    -	
    -	//tiny little interactiveData pool!
    -	this.pool = [];
    -	
    -	this.interactiveItems = [];
     
    +
    +	
    +	// helpers
    +	this.tempPoint = new PIXI.Point();
    +	//this.tempMatrix =  mat3.create();
    +
    +	this.mouseoverEnabled = true;
    +
    +	//tiny little interactiveData pool!
    +	this.pool = [];
    +
    +	this.interactiveItems = [];
    +	this.interactionDOMElement = null;
    +
    +	//this will make it so that you dont have to call bind all the time
    +	this.onMouseMove = this.onMouseMove.bind( this );
    +	this.onMouseDown = this.onMouseDown.bind(this);
    +	this.onMouseOut = this.onMouseOut.bind(this);
    +	this.onMouseUp = this.onMouseUp.bind(this);
    +
    +	this.onTouchStart = this.onTouchStart.bind(this);
    +	this.onTouchEnd = this.onTouchEnd.bind(this);
    +	this.onTouchMove = this.onTouchMove.bind(this);
    +	
    +	
     	this.last = 0;
     }
     
    -// constructor
    -PIXI.InteractionManager.constructor = PIXI.InteractionManager;
    +// constructor
    +PIXI.InteractionManager.prototype.constructor = PIXI.InteractionManager;
     
    +/**
    + * Collects an interactive sprite recursively to have their interactions managed
    + *
    + * @method collectInteractiveSprite
    + * @param displayObject {DisplayObject} the displayObject to collect
    + * @param iParent {DisplayObject}
    + * @private
    + */
     PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObject, iParent)
     {
     	var children = displayObject.children;
     	var length = children.length;
     	
    -	/// make an interaction tree... {item.__interactiveParent}
    +	/// make an interaction tree... {item.__interactiveParent}
     	for (var i = length-1; i >= 0; i--)
     	{
     		var child = children[i];
     		
    -		if(child.visible) {
    -			// push all interactive bits
    +//		if(child.visible) {
    +			// push all interactive bits
     			if(child.interactive)
     			{
     				iParent.interactiveChildren = true;
    -				//child.__iParent = iParent;
    +				//child.__iParent = iParent;
     				this.interactiveItems.push(child);
     
     				if(child.children.length > 0)
    @@ -232,48 +279,102 @@ PIXI.InteractionManager.prototype.collectInteractiveSprite = function(displayObj
     					this.collectInteractiveSprite(child, iParent);
     				}
     			}
    -		}
    +//		}
     	}
     }
     
    +/**
    + * Sets the target for event delegation
    + *
    + * @method setTarget
    + * @param target {WebGLRenderer|CanvasRenderer} the renderer to bind events to
    + * @private
    + */
     PIXI.InteractionManager.prototype.setTarget = function(target)
     {
    -	if (window.navigator.msPointerEnabled) 
    -	{
    -		// time to remove some of that zoom in ja..
    -		target.view.style["-ms-content-zooming"] = "none";
    -    	target.view.style["-ms-touch-action"] = "none"
    -    
    -		// DO some window specific touch!
    -	}
    -	
     	this.target = target;
    -	target.view.addEventListener('mousemove',  this.onMouseMove.bind(this), true);
    -	target.view.addEventListener('mousedown',  this.onMouseDown.bind(this), true);
    - 	document.body.addEventListener('mouseup',  this.onMouseUp.bind(this), true);
    - 	target.view.addEventListener('mouseout',   this.onMouseUp.bind(this), true);
    -	
    -	// aint no multi touch just yet!
    -	target.view.addEventListener("touchstart", this.onTouchStart.bind(this), true);
    -	target.view.addEventListener("touchend", this.onTouchEnd.bind(this), true);
    -	target.view.addEventListener("touchmove", this.onTouchMove.bind(this), true);
    +
    +	//check if the dom element has been set. If it has don't do anything
    +	if( this.interactionDOMElement === null ) {
    +
    +		this.setTargetDomElement( target.view );
    +	}
    +
    + 	document.body.addEventListener('mouseup',  this.onMouseUp, true);
     }
     
    +
    +/**
    + * Sets the dom element which will receive mouse/touch events. This is useful for when you have other DOM
    + * elements ontop of the renderers Canvas element. With this you'll be able to delegate another dom element
    + * to receive those events
    + *
    + * @method setTargetDomElement
    + * @param domElement {DOMElement} the dom element which will receive mouse and touch events
    + * @private
    + */
    +PIXI.InteractionManager.prototype.setTargetDomElement = function(domElement)
    +{
    +	//remove previouse listeners
    +	if( this.interactionDOMElement !== null ) 
    +	{
    +		this.interactionDOMElement.style['-ms-content-zooming'] = '';
    +    	this.interactionDOMElement.style['-ms-touch-action'] = '';
    +
    +		this.interactionDOMElement.removeEventListener('mousemove',  this.onMouseMove, true);
    +		this.interactionDOMElement.removeEventListener('mousedown',  this.onMouseDown, true);
    +	 	this.interactionDOMElement.removeEventListener('mouseout',   this.onMouseOut, true);
    +
    +	 	// aint no multi touch just yet!
    +		this.interactionDOMElement.removeEventListener('touchstart', this.onTouchStart, true);
    +		this.interactionDOMElement.removeEventListener('touchend', this.onTouchEnd, true);
    +		this.interactionDOMElement.removeEventListener('touchmove', this.onTouchMove, true);
    +	}
    +
    +
    +	if (window.navigator.msPointerEnabled) 
    +	{
    +		// time to remove some of that zoom in ja..
    +		domElement.style['-ms-content-zooming'] = 'none';
    +    	domElement.style['-ms-touch-action'] = 'none';
    +    
    +		// DO some window specific touch!
    +	}
    +
    +	this.interactionDOMElement = domElement;
    +
    +	domElement.addEventListener('mousemove',  this.onMouseMove, true);
    +	domElement.addEventListener('mousedown',  this.onMouseDown, true);
    + 	domElement.addEventListener('mouseout',   this.onMouseOut, true);
    +
    + 	// aint no multi touch just yet!
    +	domElement.addEventListener('touchstart', this.onTouchStart, true);
    +	domElement.addEventListener('touchend', this.onTouchEnd, true);
    +	domElement.addEventListener('touchmove', this.onTouchMove, true);
    +}
    +
    +
    +/**
    + * updates the state of interactive objects
    + *
    + * @method update
    + * @private
    + */
     PIXI.InteractionManager.prototype.update = function()
     {
     	if(!this.target)return;
     	
    -	// frequency of 30fps??
    +	// frequency of 30fps??
     	var now = Date.now();
     	var diff = now - this.last;
    -	diff = (diff * 30) / 1000;
    +	diff = (diff * 30) / 1000;
     	if(diff < 1)return;
     	this.last = now;
    -	//
    +	//
     	
    -	// ok.. so mouse events??
    -	// yes for now :)
    -	// OPTIMSE - how often to check??
    +	// ok.. so mouse events??
    +	// yes for now :)
    +	// OPTIMSE - how often to check??
     	if(this.dirty)
     	{
     		this.dirty = false;
    @@ -287,34 +388,37 @@ PIXI.InteractionManager.prototype.update = function()
     		this.interactiveItems = [];
     		
     		if(this.stage.interactive)this.interactiveItems.push(this.stage);
    -		// go through and collect all the objects that are interactive..
    +		// go through and collect all the objects that are interactive..
     		this.collectInteractiveSprite(this.stage, this.stage);
     	}
     	
    -	// loop through interactive objects!
    +	// loop through interactive objects!
     	var length = this.interactiveItems.length;
     	
    -	this.target.view.style.cursor = "default";	
    +	this.interactionDOMElement.style.cursor = "default";	
     				
     	for (var i = 0; i < length; i++)
     	{
     		var item = this.interactiveItems[i];
    -		if(!item.visible)continue;
     		
    -		// OPTIMISATION - only calculate every time if the mousemove function exists..
    -		// OK so.. does the object have any other interactive functions?
    -		// hit-test the clip!
    +		
    +		//if(!item.visible)continue;
    +		
    +		// OPTIMISATION - only calculate every time if the mousemove function exists..
    +		// OK so.. does the object have any other interactive functions?
    +		// hit-test the clip!
     		
     		
     		if(item.mouseover || item.mouseout || item.buttonMode)
     		{
    -			// ok so there are some functions so lets hit test it..
    +			// ok so there are some functions so lets hit test it..
     			item.__hit = this.hitTest(item, this.mouse);
    -			// ok so deal with interactions..
    -			// loks like there was a hit!
    +			this.mouse.target = item;
    +			// ok so deal with interactions..
    +			// loks like there was a hit!
     			if(item.__hit)
     			{
    -				if(item.buttonMode)this.target.view.style.cursor = "pointer";	
    +				if(item.buttonMode) this.interactionDOMElement.style.cursor = "pointer";	
     				
     				if(!item.__isOver)
     				{
    @@ -327,25 +431,32 @@ PIXI.InteractionManager.prototype.update = function()
     			{
     				if(item.__isOver)
     				{
    -					// roll out!
    +					// roll out!
     					if(item.mouseout)item.mouseout(this.mouse);
     					item.__isOver = false;	
     				}
     			}
     		}
     		
    -		// --->
    +		// --->
     	}
     }
     
    +/**
    + * Is called when the mouse moves accross the renderer element
    + *
    + * @method onMouseMove
    + * @param event {Event} The DOM event of the mouse moving
    + * @private
    + */
     PIXI.InteractionManager.prototype.onMouseMove = function(event)
     {
    -	this.mouse.originalEvent = event || window.event; //IE uses window.event
    -	// TODO optimize by not check EVERY TIME! maybe half as often? //
    -	var rect = this.target.view.getBoundingClientRect();
    +	this.mouse.originalEvent = event || window.event; //IE uses window.event
    +	// TODO optimize by not check EVERY TIME! maybe half as often? //
    +	var rect = this.interactionDOMElement.getBoundingClientRect();
     	
    -	this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width);
    -	this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height);
    +	this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width);
    +	this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height);
     	
     	var length = this.interactiveItems.length;
     	var global = this.mouse.global;
    @@ -357,29 +468,35 @@ PIXI.InteractionManager.prototype.onMouseMove = function(event)
     		
     		if(item.mousemove)
     		{
    -			//call the function!
    +			//call the function!
     			item.mousemove(this.mouse);
     		}
     	}
     }
     
    +/**
    + * Is called when the mouse button is pressed down on the renderer element
    + *
    + * @method onMouseDown
    + * @param event {Event} The DOM event of a mouse button being pressed down
    + * @private
    + */
     PIXI.InteractionManager.prototype.onMouseDown = function(event)
     {
    -	event.preventDefault();
    -	this.mouse.originalEvent = event || window.event; //IE uses window.event
    +	this.mouse.originalEvent = event || window.event; //IE uses window.event
     	
    -	// loop through inteaction tree...
    -	// hit test each item! -> 
    -	// get interactive items under point??
    -	//stage.__i
    +	// loop through inteaction tree...
    +	// hit test each item! -> 
    +	// get interactive items under point??
    +	//stage.__i
     	var length = this.interactiveItems.length;
     	var global = this.mouse.global;
     	
     	var index = 0;
     	var parent = this.stage;
     	
    -	// while 
    -	// hit test 
    +	// while 
    +	// hit test 
     	for (var i = 0; i < length; i++)
     	{
     		var item = this.interactiveItems[i];
    @@ -391,20 +508,47 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event)
     			
     			if(item.__hit)
     			{
    -				//call the function!
    +				//call the function!
     				if(item.mousedown)item.mousedown(this.mouse);
     				item.__isDown = true;
     				
    -				// just the one!
    +				// just the one!
     				if(!item.interactiveChildren)break;
     			}
     		}
     	}
     }
     
    +
    +PIXI.InteractionManager.prototype.onMouseOut = function(event)
    +{
    +	var length = this.interactiveItems.length;
    +	
    +	this.interactionDOMElement.style.cursor = "default";	
    +				
    +	for (var i = 0; i < length; i++)
    +	{
    +		var item = this.interactiveItems[i];
    +		
    +		if(item.__isOver)
    +		{
    +			this.mouse.target = item;
    +			if(item.mouseout)item.mouseout(this.mouse);
    +			item.__isOver = false;	
    +		}
    +	}
    +}
    +
    +/**
    + * Is called when the mouse button is released on the renderer element
    + *
    + * @method onMouseUp
    + * @param event {Event} The DOM event of a mouse button being released
    + * @private
    + */
     PIXI.InteractionManager.prototype.onMouseUp = function(event)
     {
    -	this.mouse.originalEvent = event || window.event; //IE uses window.event
    +	this.mouse.originalEvent = event || window.event; //IE uses window.event
     	
     	var global = this.mouse.global;
     	
    @@ -422,7 +566,7 @@ PIXI.InteractionManager.prototype.onMouseUp = function(event)
     			
     			if(item.__hit && !up)
     			{
    -				//call the function!
    +				//call the function!
     				if(item.mouseup)
     				{
     					item.mouseup(this.mouse);
    @@ -447,30 +591,42 @@ PIXI.InteractionManager.prototype.onMouseUp = function(event)
     	}
     }
     
    +/**
    + * Tests if the current mouse coords hit a sprite
    + *
    + * @method hitTest
    + * @param item {DisplayObject} The displayObject to test for a hit
    + * @param interactionData {InteractionData} The interactiondata object to update in the case of a hit
    + * @private
    + */
     PIXI.InteractionManager.prototype.hitTest = function(item, interactionData)
     {
     	var global = interactionData.global;
     	
    -	if(!item.visible)return false;
    +	if(item.vcount !== PIXI.visibleCount)return false;
     
     	var isSprite = (item instanceof PIXI.Sprite),
     		worldTransform = item.worldTransform,
     		a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2],
     		a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5],
    -		id = 1 / (a00 * a11 + a01 * -a10),
    +		id = 1 / (a00 * a11 + a01 * -a10),
     		x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id,
     		y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id;
     
    -	//a sprite or display object with a hit area defined
    +	interactionData.target = item;
    +	
    +	//a sprite or display object with a hit area defined
     	if(item.hitArea && item.hitArea.contains) {
     		if(item.hitArea.contains(x, y)) {
    -			if(isSprite)
    -				interactionData.target = item;
    +			//if(isSprite)
    +			interactionData.target = item;
     
     			return true;
     		}
    +		
    +		return false;
     	}
    -	// a sprite with no hitarea defined
    +	// a sprite with no hitarea defined
     	else if(isSprite)
     	{
     		var width = item.texture.frame.width,
    @@ -484,7 +640,7 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData)
     		
     			if(y > y1 && y < y1 + height)
     			{
    -				// set the target property if a hit is true!
    +				// set the target property if a hit is true!
     				interactionData.target = item
     				return true;
     			}
    @@ -497,28 +653,38 @@ PIXI.InteractionManager.prototype.hitTest = function(item, interactionData)
     	{
     		var tempItem = item.children[i];
     		var hit = this.hitTest(tempItem, interactionData);
    -		if(hit)return true;
    +		if(hit)
    +		{
    +			// hmm.. TODO SET CORRECT TARGET?
    +			interactionData.target = item
    +			return true;
    +		}
     	}
     
     	return false;	
     }
     
    -
    -
    +/**
    + * Is called when a touch is moved accross the renderer element
    + *
    + * @method onTouchMove
    + * @param event {Event} The DOM event of a touch moving accross the renderer view
    + * @private
    + */
     PIXI.InteractionManager.prototype.onTouchMove = function(event)
     {
    -	this.mouse.originalEvent = event || window.event; //IE uses window.event
    -	var rect = this.target.view.getBoundingClientRect();
    +	var rect = this.interactionDOMElement.getBoundingClientRect();
     	var changedTouches = event.changedTouches;
     	
     	for (var i=0; i < changedTouches.length; i++) 
     	{
     		var touchEvent = changedTouches[i];
     		var touchData = this.touchs[touchEvent.identifier];
    +		touchData.originalEvent =  event || window.event;
     		
    -		// update the touch position
    -		touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width);
    -		touchData.global.y = (touchEvent.clientY - rect.top)  * (this.target.height / rect.height);
    +		// update the touch position
    +		touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width);
    +		touchData.global.y = (touchEvent.clientY - rect.top)  * (this.target.height / rect.height);
     	}
     	
     	var length = this.interactiveItems.length;
    @@ -529,12 +695,16 @@ PIXI.InteractionManager.prototype.onTouchMove = function(event)
     	}
     }
     
    +/**
    + * Is called when a touch is started on the renderer element
    + *
    + * @method onTouchStart
    + * @param event {Event} The DOM event of a touch starting on the renderer view
    + * @private
    + */
     PIXI.InteractionManager.prototype.onTouchStart = function(event)
     {
    -	event.preventDefault();
    -	this.mouse.originalEvent = event || window.event; //IE uses window.event
    -	
    -	var rect = this.target.view.getBoundingClientRect();
    +	var rect = this.interactionDOMElement.getBoundingClientRect();
     	
     	var changedTouches = event.changedTouches;
     	for (var i=0; i < changedTouches.length; i++) 
    @@ -544,9 +714,11 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event)
     		var touchData = this.pool.pop();
     		if(!touchData)touchData = new PIXI.InteractionData();
     		
    +		touchData.originalEvent =  event || window.event;
    +		
     		this.touchs[touchEvent.identifier] = touchData;
    -		touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width);
    -		touchData.global.y = (touchEvent.clientY - rect.top)  * (this.target.height / rect.height);
    +		touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width);
    +		touchData.global.y = (touchEvent.clientY - rect.top)  * (this.target.height / rect.height);
     		
     		var length = this.interactiveItems.length;
     		
    @@ -560,7 +732,7 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event)
     				
     				if(item.__hit)
     				{
    -					//call the function!
    +					//call the function!
     					if(item.touchstart)item.touchstart(touchData);
     					item.__isDown = true;
     					item.__touchData = touchData;
    @@ -570,36 +742,41 @@ PIXI.InteractionManager.prototype.onTouchStart = function(event)
     			}
     		}
     	}
    -	
     }
     
    +/**
    + * Is called when a touch is ended on the renderer element
    + *
    + * @method onTouchEnd
    + * @param event {Event} The DOM event of a touch ending on the renderer view
    + * @private
    + */
     PIXI.InteractionManager.prototype.onTouchEnd = function(event)
     {
    -	this.mouse.originalEvent = event || window.event; //IE uses window.event
    -	var rect = this.target.view.getBoundingClientRect();
    +	//this.mouse.originalEvent = event || window.event; //IE uses window.event
    +	var rect = this.interactionDOMElement.getBoundingClientRect();
     	var changedTouches = event.changedTouches;
     	
     	for (var i=0; i < changedTouches.length; i++) 
     	{
    -		 
     		var touchEvent = changedTouches[i];
     		var touchData = this.touchs[touchEvent.identifier];
     		var up = false;
    -		touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width);
    -		touchData.global.y = (touchEvent.clientY - rect.top)  * (this.target.height / rect.height);
    +		touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width);
    +		touchData.global.y = (touchEvent.clientY - rect.top)  * (this.target.height / rect.height);
     		
     		var length = this.interactiveItems.length;
     		for (var j = 0; j < length; j++)
     		{
     			var item = this.interactiveItems[j];
    -			var itemTouchData = item.__touchData; // <-- Here!
    +			var itemTouchData = item.__touchData; // <-- Here!
     			item.__hit = this.hitTest(item, touchData);
     		
     			if(itemTouchData == touchData)
     			{
    -				// so this one WAS down...
    -				
    -				// hitTest??
    +				// so this one WAS down...
    +				touchData.originalEvent =  event || window.event;
    +				// hitTest??
     				
     				if(item.touchend || item.tap)
     				{
    @@ -632,67 +809,71 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event)
     				
     			}
     		}
    -		// remove the touch..
    +		// remove the touch..
     		this.pool.push(touchData);
     		this.touchs[touchEvent.identifier] = null;
     	}
     }
     
    -/**
    -@class InteractionData
    -@constructor
    -*/
    +/**
    + * Holds all information related to an Interaction event
    + *
    + * @class InteractionData
    + * @constructor
    + */
     PIXI.InteractionData = function()
     {
    -	/**
    -	 * This point stores the global coords of where the touch/mouse event happened
    +	/**
    +	 * This point stores the global coords of where the touch/mouse event happened
    +	 *
     	 * @property global 
     	 * @type Point
    -	 */
    +	 */
     	this.global = new PIXI.Point();
     	
    -	// this is here for legacy... but will remove
    +	// this is here for legacy... but will remove
     	this.local = new PIXI.Point();
     
    -	/**
    +	/**
     	 * The target Sprite that was interacted with
    +	 *
     	 * @property target
     	 * @type Sprite
    -	 */
    +	 */
     	this.target;
     
    -	/**
    +	/**
     	 * When passed to an event handler, this will be the original DOM Event that was captured
    +	 *
     	 * @property originalEvent
     	 * @type Event
    -	 */
    +	 */
     	this.originalEvent;
     }
     
    -/**
    +/**
      * This will return the local coords of the specified displayObject for this InteractionData
    + *
      * @method getLocalPosition
      * @param displayObject {DisplayObject} The DisplayObject that you would like the local coords off
      * @return {Point} A point containing the coords of the InteractionData position relative to the DisplayObject
    - */
    + */
     PIXI.InteractionData.prototype.getLocalPosition = function(displayObject)
     {
     	var worldTransform = displayObject.worldTransform;
     	var global = this.global;
     	
    -	// do a cheeky transform to get the mouse coords;
    +	// do a cheeky transform to get the mouse coords;
     	var a00 = worldTransform[0], a01 = worldTransform[1], a02 = worldTransform[2],
             a10 = worldTransform[3], a11 = worldTransform[4], a12 = worldTransform[5],
    -        id = 1 / (a00 * a11 + a01 * -a10);
    -	// set the mouse coords...
    +        id = 1 / (a00 * a11 + a01 * -a10);
    +	// set the mouse coords...
     	return new PIXI.Point(a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id,
     							   a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id)
     }
     
    -// constructor
    -PIXI.InteractionData.constructor = PIXI.InteractionData;
    -
    -
    +// constructor
    +PIXI.InteractionData.prototype.constructor = PIXI.InteractionData;
     
         
    @@ -703,13 +884,13 @@ PIXI.InteractionData.constructor = PIXI.InteractionData;
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_Intro.js.html b/docs/files/src_pixi_Intro.js.html index e5f2ae9..f44df3b 100644 --- a/docs/files/src_pixi_Intro.js.html +++ b/docs/files/src_pixi_Intro.js.html @@ -2,12 +2,12 @@ - src/pixi/Intro.js - Pixi.JS - - - - - + src/pixi/Intro.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,13 +166,13 @@
    -

    File: src/pixi/Intro.js

    +

    File: src/pixi/Intro.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
     (function(){
     
    @@ -163,13 +187,13 @@
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_Outro.js.html b/docs/files/src_pixi_Outro.js.html index 1eacb07..b8e33d6 100644 --- a/docs/files/src_pixi_Outro.js.html +++ b/docs/files/src_pixi_Outro.js.html @@ -2,12 +2,12 @@ - src/pixi/Outro.js - Pixi.JS - - - - - + src/pixi/Outro.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,24 +166,24 @@
    -

    File: src/pixi/Outro.js

    +

    File: src/pixi/Outro.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    -
    - if (typeof exports !== 'undefined') {
    -    if (typeof module !== 'undefined' && module.exports) {
    -      exports = module.exports = PIXI;
    -    }
    -    exports.PIXI = PIXI;
    -  } else {
    -    root.PIXI = PIXI;
    -  }
    -
    -
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +    if (typeof exports !== 'undefined') {
    +        if (typeof module !== 'undefined' && module.exports) {
    +            exports = module.exports = PIXI;
    +        }
    +        exports.PIXI = PIXI;
    +    } else if (typeof define !== 'undefined' && define.amd) {
    +        define(PIXI);
    +    } else {
    +        root.PIXI = PIXI;
    +    }
     }).call(this);
         
    @@ -170,13 +194,13 @@
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_Pixi.js.html b/docs/files/src_pixi_Pixi.js.html index 3ac2a71..08affe9 100644 --- a/docs/files/src_pixi_Pixi.js.html +++ b/docs/files/src_pixi_Pixi.js.html @@ -2,12 +2,12 @@ - src/pixi/Pixi.js - Pixi.JS - - - - - + src/pixi/Pixi.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,17 +166,17 @@
    -

    File: src/pixi/Pixi.js

    +

    File: src/pixi/Pixi.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -/**
    -@module PIXI
    - */
    +/**
    + * @module PIXI
    + */
     var PIXI = PIXI || {};
     
         
    @@ -164,13 +188,13 @@ var PIXI = PIXI || {};
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_core_Circle.js.html b/docs/files/src_pixi_core_Circle.js.html index a3eb2f7..5eef8ec 100644 --- a/docs/files/src_pixi_core_Circle.js.html +++ b/docs/files/src_pixi_core_Circle.js.html @@ -2,12 +2,12 @@ - src/pixi/core/Circle.js - Pixi.JS - - - - - + src/pixi/core/Circle.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,60 +166,66 @@
    -

    File: src/pixi/core/Circle.js

    +

    File: src/pixi/core/Circle.js

    -/**
    +/**
      * @author Chad Engler <chad@pantherdev.com>
    - */
    + */
     
    -/**
    +/**
    + * The Circle object can be used to specify a hit area for displayobjects
    + *
      * @class Circle
      * @constructor
      * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle
      * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle
      * @param radius {Number} The radius of the circle
    - */
    + */
     PIXI.Circle = function(x, y, radius)
     {
    -    /**
    +    /**
          * @property x
          * @type Number
          * @default 0
    -     */
    +     */
         this.x = x || 0;
    -    
    -    /**
    +
    +    /**
          * @property y
          * @type Number
          * @default 0
    -     */
    +     */
         this.y = y || 0;
     
    -    /**
    +    /**
          * @property radius
          * @type Number
          * @default 0
    -     */
    +     */
         this.radius = radius || 0;
     }
     
    -/**
    +/**
    + * Creates a clone of this Circle instance
    + *
      * @method clone
    - * @return a copy of the polygon
    - */
    + * @return {Circle} a copy of the polygon
    + */
     PIXI.Circle.prototype.clone = function()
     {
         return new PIXI.Circle(this.x, this.y, this.radius);
     }
     
    -/**
    +/**
    + * Checks if the x, and y coords passed to this function are contained within this circle
    + *
      * @method contains
      * @param x {Number} The X coord of the point to test
      * @param y {Number} The Y coord of the point to test
    - * @return if the x/y coords are within this polygon
    - */
    + * @return {Boolean} if the x/y coords are within this polygon
    + */
     PIXI.Circle.prototype.contains = function(x, y)
     {
         if(this.radius <= 0)
    @@ -211,7 +241,8 @@ PIXI.Circle.prototype.contains = function(x, y)
         return (dx + dy <= r2);
     }
     
    -PIXI.Circle.constructor = PIXI.Circle;
    +// constructor
    +PIXI.Circle.prototype.constructor = PIXI.Circle;
     
     
         
    @@ -223,13 +254,13 @@ PIXI.Circle.constructor = PIXI.Circle;
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_core_Ellipse.js.html b/docs/files/src_pixi_core_Ellipse.js.html index 756dc05..c6e13fa 100644 --- a/docs/files/src_pixi_core_Ellipse.js.html +++ b/docs/files/src_pixi_core_Ellipse.js.html @@ -2,12 +2,12 @@ - src/pixi/core/Ellipse.js - Pixi.JS - - - - - + src/pixi/core/Ellipse.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,77 +166,83 @@
    -

    File: src/pixi/core/Ellipse.js

    +

    File: src/pixi/core/Ellipse.js

    -/**
    +/**
      * @author Chad Engler <chad@pantherdev.com>
    - */
    + */
     
    -/**
    +/**
    + * The Ellipse object can be used to specify a hit area for displayobjects
    + *
      * @class Ellipse
      * @constructor
    - * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this circle
    - * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this circle
    - * @param width {Number} The overall height of this ellipse
    - * @param height {Number} The overall width of this ellipse
    - */
    + * @param x {Number} The X coord of the upper-left corner of the framing rectangle of this ellipse
    + * @param y {Number} The Y coord of the upper-left corner of the framing rectangle of this ellipse
    + * @param width {Number} The overall width of this ellipse
    + * @param height {Number} The overall height of this ellipse
    + */
     PIXI.Ellipse = function(x, y, width, height)
     {
    -    /**
    +    /**
          * @property x
          * @type Number
          * @default 0
    -     */
    +     */
         this.x = x || 0;
    -    
    -    /**
    +
    +    /**
          * @property y
          * @type Number
          * @default 0
    -     */
    +     */
         this.y = y || 0;
    -    
    -    /**
    +
    +    /**
          * @property width
          * @type Number
          * @default 0
    -     */
    +     */
         this.width = width || 0;
    -    
    -    /**
    +
    +    /**
          * @property height
          * @type Number
          * @default 0
    -     */
    +     */
         this.height = height || 0;
     }
     
    -/**
    +/**
    + * Creates a clone of this Ellipse instance
    + *
      * @method clone
    - * @return a copy of the polygon
    - */
    + * @return {Ellipse} a copy of the ellipse
    + */
     PIXI.Ellipse.prototype.clone = function()
     {
         return new PIXI.Ellipse(this.x, this.y, this.width, this.height);
     }
     
    -/**
    +/**
    + * Checks if the x, and y coords passed to this function are contained within this ellipse
    + *
      * @method contains
      * @param x {Number} The X coord of the point to test
      * @param y {Number} The Y coord of the point to test
    - * @return if the x/y coords are within this polygon
    - */
    + * @return {Boolean} if the x/y coords are within this ellipse
    + */
     PIXI.Ellipse.prototype.contains = function(x, y)
     {
         if(this.width <= 0 || this.height <= 0)
             return false;
     
    -    //normalize the coords to an ellipse with center 0,0
    -    //and a radius of 0.5
    -    var normx = ((x - this.x) / this.width) - 0.5,
    -        normy = ((y - this.y) / this.height) - 0.5;
    +    //normalize the coords to an ellipse with center 0,0
    +    //and a radius of 0.5
    +    var normx = ((x - this.x) / this.width) - 0.5,
    +        normy = ((y - this.y) / this.height) - 0.5;
     
         normx *= normx;
         normy *= normy;
    @@ -225,8 +255,8 @@ PIXI.Ellipse.getBounds = function()
         return new PIXI.Rectangle(this.x, this.y, this.width, this.height);
     }
     
    -PIXI.Ellipse.constructor = PIXI.Ellipse;
    -
    +// constructor
    +PIXI.Ellipse.prototype.constructor = PIXI.Ellipse;
     
         
    @@ -237,13 +267,13 @@ PIXI.Ellipse.constructor = PIXI.Ellipse;
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_core_Point.js.html b/docs/files/src_pixi_core_Point.js.html index 0d67d6c..04e593d 100644 --- a/docs/files/src_pixi_core_Point.js.html +++ b/docs/files/src_pixi_core_Point.js.html @@ -2,12 +2,12 @@ - src/pixi/core/Point.js - Pixi.JS - - - - - + src/pixi/core/Point.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,49 +166,52 @@
    -

    File: src/pixi/core/Point.js

    +

    File: src/pixi/core/Point.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -/**
    +/**
      * The Point object represents a location in a two-dimensional coordinate system, where x represents the horizontal axis and y represents the vertical axis.
    + *
      * @class Point
    - * @constructor 
    + * @constructor
      * @param x {Number} position of the point
      * @param y {Number} position of the point
    - */
    + */
     PIXI.Point = function(x, y)
     {
    -	/**
    -	 * @property x 
    +	/**
    +	 * @property x
     	 * @type Number
     	 * @default 0
    -	 */
    +	 */
     	this.x = x || 0;
    -	
    -	/**
    +
    +	/**
     	 * @property y
     	 * @type Number
     	 * @default 0
    -	 */
    +	 */
     	this.y = y || 0;
     }
     
    -/** 
    +/**
    + * Creates a clone of this point
    + *
      * @method clone
    - * @return a copy of the point
    - */
    + * @return {Point} a copy of the point
    + */
     PIXI.Point.prototype.clone = function()
     {
     	return new PIXI.Point(this.x, this.y);
     }
     
    -// constructor
    -PIXI.Point.constructor = PIXI.Point;
    +// constructor
    +PIXI.Point.prototype.constructor = PIXI.Point;
     
     
         
    @@ -196,13 +223,13 @@ PIXI.Point.constructor = PIXI.Point;
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_core_Polygon.js.html b/docs/files/src_pixi_core_Polygon.js.html index 4ea7868..2ba82b6 100644 --- a/docs/files/src_pixi_core_Polygon.js.html +++ b/docs/files/src_pixi_core_Polygon.js.html @@ -2,12 +2,12 @@ - src/pixi/core/Polygon.js - Pixi.JS - - - - - + src/pixi/core/Polygon.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,23 +166,30 @@
    -

    File: src/pixi/core/Polygon.js

    +

    File: src/pixi/core/Polygon.js

    -/**
    +/**
      * @author Adrien Brault <adrien.brault@gmail.com>
    - */
    + */
     
    -/**
    +/**
      * @class Polygon
      * @constructor
    - * @param points {Array<Point>|Array<Number>} This cna be an array of Points or a flat array of numbers
    - *      that will be interpreted as [x,y, x,y, ...]
    - */
    + * @param points* {Array<Point>|Array<Number>|Point...|Number...} This can be an array of Points that form the polygon,
    + *      a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be
    + *      all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the
    + *      arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are
    + *      Numbers.
    + */
     PIXI.Polygon = function(points)
     {
    -    //if this is a flat array of numbers, convert it to points
    +    //if points isn't an array, use arguments as the array
    +    if(!(points instanceof Array))
    +        points = Array.prototype.slice.call(arguments);
    +
    +    //if this is a flat array of numbers, convert it to points
         if(typeof points[0] === 'number') {
             var p = [];
             for(var i = 0, il = points.length; i < il; i+=2) {
    @@ -173,10 +204,12 @@ PIXI.Polygon = function(points)
     	this.points = points;
     }
     
    -/**
    +/**
    + * Creates a clone of this polygon
    + *
      * @method clone
    - * @return a copy of the polygon
    - */
    + * @return {Polygon} a copy of the polygon
    + */
     PIXI.Polygon.prototype.clone = function()
     {
     	var points = [];
    @@ -187,22 +220,24 @@ PIXI.Polygon.prototype.clone = function()
     	return new PIXI.Polygon(points);
     }
     
    -/**
    +/**
    + * Checks if the x, and y coords passed to this function are contained within this polygon
    + *
      * @method contains
      * @param x {Number} The X coord of the point to test
      * @param y {Number} The Y coord of the point to test
    - * @return if the x/y coords are within this polygon
    - */
    + * @return {Boolean} if the x/y coords are within this polygon
    + */
     PIXI.Polygon.prototype.contains = function(x, y)
     {
         var inside = false;
     
    -    // use some raycasting to test hits
    -    // https://github.com/substack/point-in-polygon/blob/master/index.js
    +    // use some raycasting to test hits
    +    // https://github.com/substack/point-in-polygon/blob/master/index.js
         for(var i = 0, j = this.points.length - 1; i < this.points.length; j = i++) {
             var xi = this.points[i].x, yi = this.points[i].y,
                 xj = this.points[j].x, yj = this.points[j].y,
    -            intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
    +            intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
     
             if(intersect) inside = !inside;
         }
    @@ -210,8 +245,8 @@ PIXI.Polygon.prototype.contains = function(x, y)
         return inside;
     }
     
    -PIXI.Polygon.constructor = PIXI.Polygon;
    -
    +// constructor
    +PIXI.Polygon.prototype.constructor = PIXI.Polygon;
     
         
    @@ -222,13 +257,13 @@ PIXI.Polygon.constructor = PIXI.Polygon;
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_core_Rectangle.js.html b/docs/files/src_pixi_core_Rectangle.js.html index de18763..ff73bde 100644 --- a/docs/files/src_pixi_core_Rectangle.js.html +++ b/docs/files/src_pixi_core_Rectangle.js.html @@ -2,12 +2,12 @@ - src/pixi/core/Rectangle.js - Pixi.JS - - - - - + src/pixi/core/Rectangle.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,80 +166,85 @@
    -

    File: src/pixi/core/Rectangle.js

    +

    File: src/pixi/core/Rectangle.js

    -/**
    - * @author Mat Groves http://matgroves.com/
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/
    + */
     
    -/**
    +/**
      * the Rectangle object is an area defined by its position, as indicated by its top-left corner point (x, y) and by its width and its height.
    + *
      * @class Rectangle
    - * @constructor 
    - * @param x {Number} position of the rectangle
    - * @param y {Number} position of the rectangle
    - * @param width {Number} of the rectangle
    - * @param height {Number} of the rectangle
    - */
    + * @constructor
    + * @param x {Number} The X coord of the upper-left corner of the rectangle
    + * @param y {Number} The Y coord of the upper-left corner of the rectangle
    + * @param width {Number} The overall width of this rectangle
    + * @param height {Number} The overall height of this rectangle
    + */
     PIXI.Rectangle = function(x, y, width, height)
     {
    -	/**
    +	/**
     	 * @property x
     	 * @type Number
     	 * @default 0
    -	 */
    +	 */
     	this.x = x || 0;
    -	
    -	/**
    +
    +	/**
     	 * @property y
     	 * @type Number
     	 * @default 0
    -	 */
    +	 */
     	this.y = y || 0;
    -	
    -	/**
    +
    +	/**
     	 * @property width
     	 * @type Number
     	 * @default 0
    -	 */
    +	 */
     	this.width = width || 0;
    -	
    -	/**
    +
    +	/**
     	 * @property height
     	 * @type Number
     	 * @default 0
    -	 */
    +	 */
     	this.height = height || 0;
     }
     
    -/** 
    +/**
    + * Creates a clone of this Rectangle
    + *
      * @method clone
    - * @return a copy of the rectangle
    - */
    + * @return {Rectangle} a copy of the rectangle
    + */
     PIXI.Rectangle.prototype.clone = function()
     {
     	return new PIXI.Rectangle(this.x, this.y, this.width, this.height);
     }
     
    -/**
    +/**
    + * Checks if the x, and y coords passed to this function are contained within this Rectangle
    + *
      * @method contains
      * @param x {Number} The X coord of the point to test
      * @param y {Number} The Y coord of the point to test
    - * @return if the x/y coords are within this polygon
    - */
    + * @return {Boolean} if the x/y coords are within this Rectangle
    + */
     PIXI.Rectangle.prototype.contains = function(x, y)
     {
         if(this.width <= 0 || this.height <= 0)
             return false;
     
     	var x1 = this.x;
    -	if(x > x1 && x < x1 + this.width)
    +	if(x >= x1 && x <= x1 + this.width)
     	{
     		var y1 = this.y;
    -		
    -		if(y > y1 && y < y1 + this.height)
    +
    +		if(y >= y1 && y <= y1 + this.height)
     		{
     			return true;
     		}
    @@ -224,8 +253,8 @@ PIXI.Rectangle.prototype.contains = function(x, y)
     	return false;
     }
     
    -// constructor
    -PIXI.Rectangle.constructor = PIXI.Rectangle;
    +// constructor
    +PIXI.Rectangle.prototype.constructor = PIXI.Rectangle;
     
     
         
    @@ -237,13 +266,13 @@ PIXI.Rectangle.constructor = PIXI.Rectangle;
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_display_DisplayObject.js.html b/docs/files/src_pixi_display_DisplayObject.js.html index f4c2f15..57725eb 100644 --- a/docs/files/src_pixi_display_DisplayObject.js.html +++ b/docs/files/src_pixi_display_DisplayObject.js.html @@ -2,12 +2,12 @@ - src/pixi/display/DisplayObject.js - Pixi.JS - - - - - + src/pixi/display/DisplayObject.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,218 +166,276 @@
    -

    File: src/pixi/display/DisplayObject.js

    +

    File: src/pixi/display/DisplayObject.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -/**
    - * this is the base class for all objects that are rendered on the screen.
    +/**
    + * The base class for all objects that are rendered on the screen.
    + *
      * @class DisplayObject
      * @constructor
    - */
    + */
     PIXI.DisplayObject = function()
     {
     	this.last = this;
     	this.first = this;
    -	
    -	/**
    +	/**
     	 * The coordinate of the object relative to the local coordinates of the parent.
    +	 *
     	 * @property position
     	 * @type Point
    -	 */
    +	 */
     	this.position = new PIXI.Point();
    -	
    -	/**
    +
    +	/**
     	 * The scale factor of the object.
    +	 *
     	 * @property scale
     	 * @type Point
    -	 */
    -	this.scale = new PIXI.Point(1,1);//{x:1, y:1};
    -	
    -	/**
    +	 */
    +	this.scale = new PIXI.Point(1,1);//{x:1, y:1};
    +
    +	/**
     	 * The pivot point of the displayObject that it rotates around
    +	 *
     	 * @property pivot
     	 * @type Point
    -	 */
    +	 */
     	this.pivot = new PIXI.Point(0,0);
    -	
    -	/**
    +
    +	/**
     	 * The rotation of the object in radians.
    +	 *
     	 * @property rotation
     	 * @type Number
    -	 */
    +	 */
     	this.rotation = 0;
    -	
    -	/**
    +
    +	/**
     	 * The opacity of the object.
    +	 *
     	 * @property alpha
     	 * @type Number
    -	 */	
    +	 */	
     	this.alpha = 1;
    -	
    -	/**
    +
    +	/**
     	 * The visibility of the object.
    +	 *
     	 * @property visible
     	 * @type Boolean
    -	 */	
    +	 */	
     	this.visible = true;
    -	this.worldVisible = false;
    -	
    -	/**
    -	 * [read-only] The display object container that contains this display object.
    -	 * @property parent
    -	 * @type DisplayObjectContainer
    -	 */	
    -	this.parent = null;
    -	
    -	/**
    -	 * [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage.
    -	 * @property stage
    -	 * @type Stage
    -	 */	
    -	this.stage = null;
    -	
    -	/**
    -	 * This is the defined area that will pick up mouse / touch events. It is null by default.
    +
    +	/**
    +	 * This is the defined area that will pick up mouse / touch events. It is null by default.
     	 * Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children)
    +	 *
     	 * @property hitArea
    -	 * @type Rectangle
    -	 */	
    +	 * @type Rectangle|Circle|Ellipse|Polygon
    +	 */	
     	this.hitArea = null;
    -	
    -	this.worldAlpha = 1;
    -	this.color = [];
    -	
    -	this.worldTransform = PIXI.mat3.create()//mat3.identity();
    -	this.localTransform = PIXI.mat3.create()//mat3.identity();
    -	
    -	this.dynamic = true;
    -	// chach that puppy!
    -	this._sr = 0;
    -	this._cr = 1;
    -	
    -	this.childIndex = 0;
    -	
    -	this.renderable = false;
    -	
    -	// [readonly] best not to toggle directly! use setInteractive()
    -	this._interactive = false;
    -	
    -	/**
    +
    +	/**
     	 * This is used to indicate if the displayObject should display a mouse hand cursor on rollover
    +	 *
     	 * @property buttonMode
     	 * @type Boolean
    -	 */
    +	 */
     	this.buttonMode = false;
    +
    +	/**
    +	 * Can this object be rendered
    +	 *
    +	 * @property renderable
    +	 * @type Boolean
    +	 */
    +	this.renderable = false;
    +
    +	/**
    +	 * [read-only] The display object container that contains this display object.
    +	 *
    +	 * @property parent
    +	 * @type DisplayObjectContainer
    +	 * @readOnly
    +	 */	
    +	this.parent = null;
    +
    +	/**
    +	 * [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage.
    +	 *
    +	 * @property stage
    +	 * @type Stage
    +	 * @readOnly
    +	 */	
    +	this.stage = null;
    +
    +	/**
    +	 * [read-only] The multiplied alpha of the displayobject
    +	 *
    +	 * @property worldAlpha
    +	 * @type Number
    +	 * @readOnly
    +	 */
    +	this.worldAlpha = 1;
    +
    +	/**
    +	 * [read-only] Whether or not the object is interactive, do not toggle directly! use the `interactive` property
    +	 *
    +	 * @property _interactive
    +	 * @type Boolean
    +	 * @readOnly
    +	 * @private
    +	 */
    +	this._interactive = false;
    +
    +	/**
    +	 * [read-only] Current transform of the object based on world (parent) factors
    +	 *
    +	 * @property worldTransform
    +	 * @type Mat3
    +	 * @readOnly
    +	 * @private
    +	 */
    +	this.worldTransform = PIXI.mat3.create()//mat3.identity();
    +
    +	/**
    +	 * [read-only] Current transform of the object locally
    +	 *
    +	 * @property localTransform
    +	 * @type Mat3
    +	 * @readOnly
    +	 * @private
    +	 */
    +	this.localTransform = PIXI.mat3.create()//mat3.identity();
    +
    +	/**
    +	 * [NYI] Unkown
    +	 *
    +	 * @property color
    +	 * @type Array<>
    +	 * @private
    +	 */
    +	this.color = [];
    +
    +	/**
    +	 * [NYI] Holds whether or not this object is dynamic, for rendering optimization
    +	 *
    +	 * @property dynamic
    +	 * @type Boolean
    +	 * @private
    +	 */
    +	this.dynamic = true;
    +
    +	// chach that puppy!
    +	this._sr = 0;
    +	this._cr = 1;
    +
    +
    +	this.filterArea = new PIXI.Rectangle(0,0,1,1);
     	
    -	/*
    +	/*
     	 * MOUSE Callbacks
    -	 */
    -	
    -	/**
    +	 */
    +
    +	/**
     	 * A callback that is used when the users clicks on the displayObject with their mouse
     	 * @method click
     	 * @param interactionData {InteractionData}
    -	 */
    -	
    -	/**
    +	 */
    +
    +	/**
     	 * A callback that is used when the user clicks the mouse down over the sprite
     	 * @method mousedown
     	 * @param interactionData {InteractionData}
    -	 */
    -	 
    -	/**
    +	 */
    +
    +	/**
     	 * A callback that is used when the user releases the mouse that was over the displayObject
     	 * for this callback to be fired the mouse must have been pressed down over the displayObject
     	 * @method mouseup
     	 * @param interactionData {InteractionData}
    -	 */
    -	
    -	/**
    +	 */
    +
    +	/**
     	 * A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject
     	 * for this callback to be fired, The touch must have started over the displayObject
     	 * @method mouseupoutside
     	 * @param interactionData {InteractionData}
    -	 */
    -	
    -	/**
    +	 */
    +
    +	/**
     	 * A callback that is used when the users mouse rolls over the displayObject
     	 * @method mouseover
     	 * @param interactionData {InteractionData}
    -	 */
    -	
    -	/**
    +	 */
    +
    +	/**
     	 * A callback that is used when the users mouse leaves the displayObject
     	 * @method mouseout
     	 * @param interactionData {InteractionData}
    -	 */
    -	
    -	
    -	/*
    +	 */
    +
    +
    +	/*
     	 * TOUCH Callbacks
    -	 */
    -	
    -	/**
    +	 */
    +
    +	/**
     	 * A callback that is used when the users taps on the sprite with their finger
     	 * basically a touch version of click
     	 * @method tap
     	 * @param interactionData {InteractionData}
    -	 */
    -	
    -	/**
    +	 */
    +
    +	/**
     	 * A callback that is used when the user touch's over the displayObject
     	 * @method touchstart
     	 * @param interactionData {InteractionData}
    -	 */
    -	 
    -	/**
    +	 */
    +
    +	/**
     	 * A callback that is used when the user releases a touch over the displayObject
     	 * @method touchend
     	 * @param interactionData {InteractionData}
    -	 */
    -	
    -	/**
    +	 */
    +
    +	/**
     	 * A callback that is used when the user releases the touch that was over the displayObject
     	 * for this callback to be fired, The touch must have started over the sprite
     	 * @method touchendoutside
     	 * @param interactionData {InteractionData}
    -	 */
    +	 */
     }
     
    -// constructor
    -PIXI.DisplayObject.constructor = PIXI.DisplayObject;
    +// constructor
    +PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject;
     
    -//TODO make visible a getter setter
    -/*
    -Object.defineProperty(PIXI.DisplayObject.prototype, 'visible', {
    -    get: function() {
    -        return this._visible;
    -    },
    -    set: function(value) {
    -        this._visible = value;
    -    }
    -});*/
    -
    -/**
    +/**
      * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default
      * Instead of using this function you can now simply set the interactive property to true or false
    + *
      * @method setInteractive
      * @param interactive {Boolean}
    - */
    + * @deprecated Simply set the `interactive` property directly
    + */
     PIXI.DisplayObject.prototype.setInteractive = function(interactive)
     {
     	this.interactive = interactive;
     }
     
    -/**
    +/**
      * Indicates if the sprite will have touch and mouse interactivity. It is false by default
    + *
      * @property interactive
      * @type Boolean
    - */
    + * @default false
    + */
     Object.defineProperty(PIXI.DisplayObject.prototype, 'interactive', {
         get: function() {
             return this._interactive;
    @@ -361,65 +443,129 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'interactive', {
         set: function(value) {
         	this._interactive = value;
         	
    -    	// TODO more to be done here..
    -		// need to sort out a re-crawl!
    +    	// TODO more to be done here..
    +		// need to sort out a re-crawl!
     		if(this.stage)this.stage.dirty = true;
         }
     });
     
    -/**
    +/**
      * Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it.
      * In PIXI a regular mask must be a PIXI.Ggraphics object. This allows for much faster masking in canvas as it utilises shape clipping.
      * To remove a mask, set this property to null.
    + *
      * @property mask
    - * @type PIXI.Graphics
    - */
    + * @type Graphics
    + */
     Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', {
         get: function() {
             return this._mask;
         },
         set: function(value) {
         	
    -        this._mask = value;
    -        
    +    	
             if(value)
             {
    -	        this.addFilter(value)
    +        	if(this._mask)
    +	    	{
    +	    		value.start = this._mask.start;
    +	    		value.end = this._mask.end;
    +	    	}
    +    		else
    +    		{
    +		        this.addFilter(value);
    +		        value.renderable = false;
    +    		}
             }
             else
             {
    -        	 this.removeFilter();
    +        	 this.removeFilter(this._mask);
    +			 this._mask.renderable = true;
             }
    +        
    +        this._mask = value;
         }
     });
     
    -/* 
    - * private
    - */
    -PIXI.DisplayObject.prototype.addFilter = function(mask)
    +/**
    + * Sets the filters for the displayObject. 
    + * * IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer.
    + * To remove filters simply set this property to 'null'
    + * @property filters
    + * @type Array An array of filters
    + */
    +Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', {
    +    get: function() {
    +        return this._filters;
    +    },
    +    set: function(value) {
    +    	
    +        if(value)
    +        {
    +        	if(this._filters)this.removeFilter(this._filters);
    +	        this.addFilter(value);
    +
    +		    // now put all the passes in one place..
    +	        var passes = [];
    +	        for (var i = 0; i < value.length; i++) 
    +	        {
    +	        	var filterPasses = value[i].passes;
    +	        	for (var j = 0; j < filterPasses.length; j++) 
    +	        	{
    +	        		passes.push(filterPasses[j]);
    +	        	};
    +	        };
    +
    +	        value.start.filterPasses = passes;
    +        }
    +        else
    +        {
    +        	if(this._filters)this.removeFilter(this._filters);
    +        }
    +        
    +        this._filters = value;
    +
    +       
    +
    +        
    +    }
    +});
    +
    +/*
    + * Adds a filter to this displayObject
    + *
    + * @method addFilter
    + * @param mask {Graphics} the graphics object to use as a filter
    + * @private
    + */
    +PIXI.DisplayObject.prototype.addFilter = function(data)
     {
    -	if(this.filter)return;
    -	this.filter = true;
    +	//if(this.filter)return;
    +	//this.filter = true;
    +//	data[0].target = this;
     	
    -	
    -	// insert a filter block..
    +
    +	// insert a filter block..
    +	// TODO Onject pool thease bad boys..
     	var start = new PIXI.FilterBlock();
     	var end = new PIXI.FilterBlock();
     	
    +	data.start = start;
    +	data.end = end;
     	
    -	start.mask = mask;
    -	end.mask = mask;
    +	start.data = data;
    +	end.data = data;
     	
     	start.first = start.last =  this;
     	end.first = end.last = this;
     	
     	start.open = true;
     	
    -	/*
    -	 * 
    +	start.target = this;
    +	
    +	/*
     	 * insert start
    -	 * 
    -	 */
    +	 */
     	
     	var childFirst = start
     	var childLast = start
    @@ -446,13 +592,11 @@ PIXI.DisplayObject.prototype.addFilter = function(mask)
     	}
     	
     	
    -	// now insert the end filter block..
    +	// now insert the end filter block..
     	
    -	/*
    -	 * 
    +	/*
     	 * insert end filter
    -	 * 
    -	 */
    +	 */
     	var childFirst = end
     	var childLast = end
     	var nextObject = null;
    @@ -484,23 +628,28 @@ PIXI.DisplayObject.prototype.addFilter = function(mask)
     	
     	this.first = start;
     	
    -	// if webGL...
    +	// if webGL...
     	if(this.__renderGroup)
     	{
     		this.__renderGroup.addFilterBlocks(start, end);
     	}
     	
    -	mask.renderable = false;
    -	
     }
     
    -PIXI.DisplayObject.prototype.removeFilter = function()
    +/*
    + * Removes the filter to this displayObject
    + *
    + * @method removeFilter
    + * @private
    + */
    +PIXI.DisplayObject.prototype.removeFilter = function(data)
     {
    -	if(!this.filter)return;
    -	this.filter = false;
    +	//if(!this.filter)return;
    +	//this.filter = false;
    +	console.log("YUOIO")
    +	// modify the list..
    +	var startBlock = data.start;
     	
    -	// modify the list..
    -	var startBlock = this.first;
     	
     	var nextObject = startBlock._iNext;
     	var previousObject = startBlock._iPrev;
    @@ -510,9 +659,8 @@ PIXI.DisplayObject.prototype.removeFilter = function()
     	
     	this.first = startBlock._iNext;
     	
    -	
    -	// remove the end filter
    -	var lastBlock = this.last;
    +	// remove the end filter
    +	var lastBlock = data.end;
     	
     	var nextObject = lastBlock._iNext;
     	var previousObject = lastBlock._iPrev;
    @@ -520,11 +668,9 @@ PIXI.DisplayObject.prototype.removeFilter = function()
     	if(nextObject)nextObject._iPrev = previousObject;
     	previousObject._iNext = nextObject;		
     	
    -	// this is always true too!
    -//	if(this.last == lastBlock)
    -	//{
    +	// this is always true too!
     	var tempLast =  lastBlock._iPrev;	
    -	// need to make sure the parents last is updated too
    +	// need to make sure the parents last is updated too
     	var updateLast = this;
     	while(updateLast.last == lastBlock)
     	{
    @@ -533,24 +679,23 @@ PIXI.DisplayObject.prototype.removeFilter = function()
     		if(!updateLast)break;
     	}
     	
    -	var mask = startBlock.mask
    -	mask.renderable = true;
    -	
    -	// if webGL...
    +	// if webGL...
     	if(this.__renderGroup)
     	{
     		this.__renderGroup.removeFilterBlocks(startBlock, lastBlock);
     	}
    -	//}
     }
     
    -/**
    +/*
    + * Updates the object transform for rendering
    + *
    + * @method updateTransform
      * @private
    - */
    + */
     PIXI.DisplayObject.prototype.updateTransform = function()
     {
    -	// TODO OPTIMIZE THIS!! with dirty
    -	if(this.rotation != this.rotationCache)
    +	// TODO OPTIMIZE THIS!! with dirty
    +	if(this.rotation !== this.rotationCache)
     	{
     		this.rotationCache = this.rotation;
     		this._sr =  Math.sin(this.rotation);
    @@ -560,18 +705,18 @@ PIXI.DisplayObject.prototype.updateTransform = function()
     	var localTransform = this.localTransform;
     	var parentTransform = this.parent.worldTransform;
     	var worldTransform = this.worldTransform;
    -	//console.log(localTransform)
    +	//console.log(localTransform)
     	localTransform[0] = this._cr * this.scale.x;
     	localTransform[1] = -this._sr * this.scale.y
     	localTransform[3] = this._sr * this.scale.x;
     	localTransform[4] = this._cr * this.scale.y;
     	
    -	// TODO --> do we even need a local matrix???
    +	// TODO --> do we even need a local matrix???
     	
     	var px = this.pivot.x;
     	var py = this.pivot.y;
        	
    -    // Cache the matrix values (makes for huge speed increases!)
    +    // Cache the matrix values (makes for huge speed increases!)
         var a00 = localTransform[0], a01 = localTransform[1], a02 = this.position.x - localTransform[0] * px - py * localTransform[1],
             a10 = localTransform[3], a11 = localTransform[4], a12 = this.position.y - localTransform[4] * py - px * localTransform[3],
     
    @@ -589,12 +734,15 @@ PIXI.DisplayObject.prototype.updateTransform = function()
         worldTransform[4] = b10 * a01 + b11 * a11;
         worldTransform[5] = b10 * a02 + b11 * a12 + b12;
     
    -	// because we are using affine transformation, we can optimise the matrix concatenation process.. wooo!
    -	// mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform);
    +	// because we are using affine transformation, we can optimise the matrix concatenation process.. wooo!
    +	// mat3.multiply(this.localTransform, this.parent.worldTransform, this.worldTransform);
     	this.worldAlpha = this.alpha * this.parent.worldAlpha;
    +	
    +	this.vcount = PIXI.visibleCount;
     
     }
     
    +PIXI.visibleCount = 0;
         
    @@ -604,13 +752,13 @@ PIXI.DisplayObject.prototype.updateTransform = function()
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_display_DisplayObjectContainer.js.html b/docs/files/src_pixi_display_DisplayObjectContainer.js.html index 0875822..f44463c 100644 --- a/docs/files/src_pixi_display_DisplayObjectContainer.js.html +++ b/docs/files/src_pixi_display_DisplayObjectContainer.js.html @@ -2,12 +2,12 @@ - src/pixi/display/DisplayObjectContainer.js - Pixi.JS - - - - - + src/pixi/display/DisplayObjectContainer.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,76 +166,62 @@
    -

    File: src/pixi/display/DisplayObjectContainer.js

    +

    File: src/pixi/display/DisplayObjectContainer.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
     
    -/**
    - * A DisplayObjectContainer represents a collection of display objects. It is the base class of all display objects that act as a container for other objects.
    +/**
    + * A DisplayObjectContainer represents a collection of display objects.
    + * It is the base class of all display objects that act as a container for other objects.
    + *
      * @class DisplayObjectContainer 
      * @extends DisplayObject
      * @constructor
    - */
    + */
     PIXI.DisplayObjectContainer = function()
     {
     	PIXI.DisplayObject.call( this );
     	
    -	/**
    +	/**
     	 * [read-only] The of children of this container.
    -	 * @property children {Array}
    -	 */	
    +	 *
    +	 * @property children
    +	 * @type Array<DisplayObject>
    +	 * @readOnly
    +	 */	
     	this.children = [];
    -	//s
    -	this.renderable = false;
    -	
     }
     
    -// constructor
    -PIXI.DisplayObjectContainer.constructor = PIXI.DisplayObjectContainer;
    +// constructor
     PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype );
    +PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer;
     
    -//TODO make visible a getter setter
    -/*
    -Object.defineProperty(PIXI.DisplayObjectContainer.prototype, 'visible', {
    -    get: function() {
    -        return this._visible;
    -    },
    -    set: function(value) {
    -        this._visible = value;
    -        
    -    }
    -});*/
    -
    -/**
    +/**
      * Adds a child to the container.
    + *
      * @method addChild
    - * @param  DisplayObject {DisplayObject}
    - */
    + * @param child {DisplayObject} The DisplayObject to add to the container
    + */
     PIXI.DisplayObjectContainer.prototype.addChild = function(child)
     {
    -	
    -	//this.addChildAt(child, this.children.length)
    -	//return;
    -	
     	if(child.parent != undefined)
     	{
     		
    -		//// COULD BE THIS???
    +		//// COULD BE THIS???
     		child.parent.removeChild(child);
    -	//	return;
    +	//	return;
     	}
    -	
    +
     	child.parent = this;
    -	//child.childIndex = this.children.length;
     	
     	this.children.push(child);	
     	
    -	// updae the stage refference..
    +	// update the stage refference..
     	
     	if(this.stage)
     	{
    @@ -225,17 +235,16 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child)
     		while(tmpChild)
     	}
     	
    -	// LINKED LIST //
    +	// LINKED LIST //
     	
    -	// modify the list..
    +	// modify the list..
     	var childFirst = child.first
     	var childLast = child.last;
    -//	console.log(childFirst)
     	var nextObject;
     	var previousObject;
     	
    -	// this could be wrong if there is a filter??
    -	if(this.filter)
    +	// this could be wrong if there is a filter??
    +	if(this._filters || this._mask)
     	{
     		previousObject =  this.last._iPrev;
     	}
    @@ -243,14 +252,11 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child)
     	{
     		previousObject = this.last;
     	}
    -//	if(this.last._iNext)
    -	
    -	//console.log( this.last._iNext);
    +
     	nextObject = previousObject._iNext;
     	
    -	// always true in this case
    -	//this.last = child.last;
    -	// need to make sure the parents last is updated too
    +	// always true in this case
    +	// need to make sure the parents last is updated too
     	var updateLast = this;
     	var prevLast = previousObject;
     	
    @@ -271,25 +277,25 @@ PIXI.DisplayObjectContainer.prototype.addChild = function(child)
     	
     	childFirst._iPrev = previousObject;
     	previousObject._iNext = childFirst;		
    -	
    -//	console.log(childFirst);
    -	// need to remove any render groups..
    +
    +	// need to remove any render groups..
     	if(this.__renderGroup)
     	{
    -		// being used by a renderTexture.. if it exists then it must be from a render texture;
    +		// being used by a renderTexture.. if it exists then it must be from a render texture;
     		if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child);
    -		// add them to the new render group..
    +		// add them to the new render group..
     		this.__renderGroup.addDisplayObjectAndChildren(child);
     	}
     	
     }
     
    -/**
    +/**
      * Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown
    + *
      * @method addChildAt
    - * @param DisplayObject {DisplayObject}
    - * @param index {Number}
    - */
    + * @param child {DisplayObject} The child to add
    + * @param index {Number} The index to place the child in
    + */
     PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index)
     {
     	if(index >= 0 && index <= this.children.length)
    @@ -312,8 +318,8 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index)
     			while(tmpChild)
     		}
     		
    -		// modify the list..
    -		var childFirst = child.first
    +		// modify the list..
    +		var childFirst = child.first;
     		var childLast = child.last;
     		var nextObject;
     		var previousObject;
    @@ -321,7 +327,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index)
     		if(index == this.children.length)
     		{
     			previousObject =  this.last;
    -			var updateLast = this;//.parent;
    +			var updateLast = this;
     			var prevLast = this.last;
     			while(updateLast)
     			{
    @@ -343,7 +349,7 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index)
     		
     		nextObject = previousObject._iNext;
     		
    -		// always true in this case
    +		// always true in this case
     		if(nextObject)
     		{
     			nextObject._iPrev = childLast;
    @@ -352,19 +358,17 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index)
     		
     		childFirst._iPrev = previousObject;
     		previousObject._iNext = childFirst;		
    -		
    -		
    +
     		this.children.splice(index, 0, child);
    -		// need to remove any render groups..
    +		// need to remove any render groups..
     		if(this.__renderGroup)
     		{
    -			// being used by a renderTexture.. if it exists then it must be from a render texture;
    +			// being used by a renderTexture.. if it exists then it must be from a render texture;
     			if(child.__renderGroup)child.__renderGroup.removeDisplayObjectAndChildren(child);
    -			// add them to the new render group..
    +			// add them to the new render group..
     			this.__renderGroup.addDisplayObjectAndChildren(child);
     		}
     		
    -		console.log(this.children)
     	}
     	else
     	{
    @@ -372,35 +376,37 @@ PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index)
     	}
     }
     
    -/**
    - * Swaps the depth of 2 displayObjects
    +/**
    + * [NYI] Swaps the depth of 2 displayObjects
    + *
      * @method swapChildren
    - * @param  DisplayObject {DisplayObject}
    - * @param  DisplayObject2 {DisplayObject}
    - */
    + * @param child {DisplayObject}
    + * @param child2 {DisplayObject}
    + * @private
    + */
     PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2)
     {
    -	/*
    +	/*
     	 * this funtion needs to be recoded.. 
     	 * can be done a lot faster..
    -	 */
    +	 */
     	return;
     	
    -	// need to fix this function :/
    -	/*
    -	// TODO I already know this??
    +	// need to fix this function :/
    +	/*
    +	// TODO I already know this??
     	var index = this.children.indexOf( child );
     	var index2 = this.children.indexOf( child2 );
     	
     	if ( index !== -1 && index2 !== -1 ) 
     	{
    -		// cool
    +		// cool
     		
    -		/*
    +		/*
     		if(this.stage)
     		{
    -			// this is to satisfy the webGL batching..
    -			// TODO sure there is a nicer way to achieve this!
    +			// this is to satisfy the webGL batching..
    +			// TODO sure there is a nicer way to achieve this!
     			this.stage.__removeChild(child);
     			this.stage.__removeChild(child2);
     			
    @@ -408,7 +414,7 @@ PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2)
     			this.stage.__addChild(child2);
     		}
     		
    -		// swap the positions..
    +		// swap the positions..
     		this.children[index] = child2;
     		this.children[index2] = child;
     		
    @@ -416,14 +422,15 @@ PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2)
     	else
     	{
     		throw new Error(child + " Both the supplied DisplayObjects must be a child of the caller " + this);
    -	}*/
    +	}*/
     }
     
    -/**
    +/**
      * Returns the Child at the specified index
    + *
      * @method getChildAt
    - * @param  index {Number}
    - */
    + * @param index {Number} The index to get the child from
    + */
     PIXI.DisplayObjectContainer.prototype.getChildAt = function(index)
     {
     	if(index >= 0 && index < this.children.length)
    @@ -436,20 +443,20 @@ PIXI.DisplayObjectContainer.prototype.getChildAt = function(index)
     	}
     }
     
    -/**
    +/**
      * Removes a child from the container.
    + *
      * @method removeChild
    - * @param  DisplayObject {DisplayObject}
    - */
    + * @param child {DisplayObject} The DisplayObject to remove
    + */
     PIXI.DisplayObjectContainer.prototype.removeChild = function(child)
     {
     	var index = this.children.indexOf( child );
     	if ( index !== -1 ) 
     	{
    -		//console.log(">>")
    -		// unlink //
    -		// modify the list..
    -		var childFirst = child.first
    +		// unlink //
    +		// modify the list..
    +		var childFirst = child.first;
     		var childLast = child.last;
     		
     		var nextObject = childLast._iNext;
    @@ -461,7 +468,7 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child)
     		if(this.last == childLast)
     		{
     			var tempLast =  childFirst._iPrev;	
    -			// need to make sure the parents last is updated too
    +			// need to make sure the parents last is updated too
     			var updateLast = this;
     			while(updateLast.last == childLast.last)
     			{
    @@ -474,7 +481,7 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child)
     		childLast._iNext = null;
     		childFirst._iPrev = null;
     		 
    -		// update the stage reference..
    +		// update the stage reference..
     		if(this.stage)
     		{
     			var tmpChild = child;
    @@ -487,7 +494,7 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child)
     			while(tmpChild)
     		}
     	
    -		// webGL trim
    +		// webGL trim
     		if(child.__renderGroup)
     		{
     			child.__renderGroup.removeDisplayObjectAndChildren(child);
    @@ -502,10 +509,12 @@ PIXI.DisplayObjectContainer.prototype.removeChild = function(child)
     	}
     }
     
    -
    -/**
    +/*
    + * Updates the container's children's transform for rendering
    + *
    + * @method updateTransform
      * @private
    - */
    + */
     PIXI.DisplayObjectContainer.prototype.updateTransform = function()
     {
     	if(!this.visible)return;
    @@ -517,7 +526,6 @@ PIXI.DisplayObjectContainer.prototype.updateTransform = function()
     		this.children[i].updateTransform();	
     	}
     }
    -
         
    @@ -527,13 +535,13 @@ PIXI.DisplayObjectContainer.prototype.updateTransform = function()
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_display_MovieClip.js.html b/docs/files/src_pixi_display_MovieClip.js.html index 87e0a59..600d7f1 100644 --- a/docs/files/src_pixi_display_MovieClip.js.html +++ b/docs/files/src_pixi_display_MovieClip.js.html @@ -2,12 +2,12 @@ - src/pixi/display/MovieClip.js - Pixi.JS - - - - - + src/pixi/display/MovieClip.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,95 +166,127 @@
    -

    File: src/pixi/display/MovieClip.js

    +

    File: src/pixi/display/MovieClip.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -/**
    +/**
      * A MovieClip is a simple way to display an animation depicted by a list of textures.
    + *
      * @class MovieClip
      * @extends Sprite
      * @constructor
    - * @param textures {Array} an array of {Texture} objects that make up the animation
    - */
    + * @param textures {Array<Texture>} an array of {Texture} objects that make up the animation
    + */
     PIXI.MovieClip = function(textures)
     {
    -	PIXI.Sprite.call( this, textures[0]);
    -	
    -	/**
    +	PIXI.Sprite.call(this, textures[0]);
    +
    +	/**
     	 * The array of textures that make up the animation
    +	 *
     	 * @property textures
     	 * @type Array
    -	 */
    +	 */
     	this.textures = textures;
    -	
    -	/**
    -	 * [read only] The index MovieClips current frame (this may not have to be a whole number)
    -	 * @property currentFrame
    -	 * @type Number
    -	 */
    -	this.currentFrame = 0; 
    -	
    -	/**
    +
    +	/**
     	 * The speed that the MovieClip will play at. Higher is faster, lower is slower
    +	 *
     	 * @property animationSpeed
     	 * @type Number
    -	 */
    +	 * @default 1
    +	 */
     	this.animationSpeed = 1;
     
    -	/**
    +	/**
     	 * Whether or not the movie clip repeats after playing.
    +	 *
     	 * @property loop
     	 * @type Boolean
    -	 */
    +	 * @default true
    +	 */
     	this.loop = true;
     
    -	/**
    +	/**
     	 * Function to call when a MovieClip finishes playing
    +	 *
     	 * @property onComplete
     	 * @type Function
    -	 */
    +	 */
     	this.onComplete = null;
    -	
    -	/**
    -	 * [read only] indicates if the MovieClip is currently playing
    +
    +	/**
    +	 * [read-only] The index MovieClips current frame (this may not have to be a whole number)
    +	 *
    +	 * @property currentFrame
    +	 * @type Number
    +	 * @default 0
    +	 * @readOnly
    +	 */
    +	this.currentFrame = 0;
    +
    +	/**
    +	 * [read-only] Indicates if the MovieClip is currently playing
    +	 *
     	 * @property playing
     	 * @type Boolean
    -	 */
    -	this.playing;
    +	 * @readOnly
    +	 */
    +	this.playing = false;
     }
     
    -// constructor
    -PIXI.MovieClip.constructor = PIXI.MovieClip;
    +// constructor
     PIXI.MovieClip.prototype = Object.create( PIXI.Sprite.prototype );
    +PIXI.MovieClip.prototype.constructor = PIXI.MovieClip;
     
    -/**
    +/**
    +* [read-only] totalFrames is the total number of frames in the MovieClip. This is the same as number of textures
    +* assigned to the MovieClip.
    +*
    +* @property totalFrames
    +* @type Number
    +* @default 0
    +* @readOnly
    +*/
    +Object.defineProperty( PIXI.MovieClip.prototype, 'totalFrames', {
    +	get: function() {
    +
    +		return this.textures.length;
    +	}
    +});
    +
    +
    +/**
      * Stops the MovieClip
    + *
      * @method stop
    - */
    + */
     PIXI.MovieClip.prototype.stop = function()
     {
     	this.playing = false;
     }
     
    -/**
    +/**
      * Plays the MovieClip
    + *
      * @method play
    - */
    + */
     PIXI.MovieClip.prototype.play = function()
     {
     	this.playing = true;
     }
     
    -/**
    +/**
      * Stops the MovieClip and goes to a specific frame
    + *
      * @method gotoAndStop
      * @param frameNumber {Number} frame index to stop at
    - */
    + */
     PIXI.MovieClip.prototype.gotoAndStop = function(frameNumber)
     {
     	this.playing = false;
    @@ -239,25 +295,34 @@ PIXI.MovieClip.prototype.gotoAndStop = function(frameNumber)
     	this.setTexture(this.textures[round % this.textures.length]);
     }
     
    -/**
    +/**
      * Goes to a specific frame and begins playing the MovieClip
    + *
      * @method gotoAndPlay
      * @param frameNumber {Number} frame index to start at
    - */
    + */
     PIXI.MovieClip.prototype.gotoAndPlay = function(frameNumber)
     {
     	this.currentFrame = frameNumber;
     	this.playing = true;
     }
     
    +/*
    + * Updates the object transform for rendering
    + *
    + * @method updateTransform
    + * @private
    + */
     PIXI.MovieClip.prototype.updateTransform = function()
     {
     	PIXI.Sprite.prototype.updateTransform.call(this);
    -	
    +
     	if(!this.playing)return;
    -	
    +
     	this.currentFrame += this.animationSpeed;
    +
     	var round = (this.currentFrame + 0.5) | 0;
    +
     	if(this.loop || round < this.textures.length)
     	{
     		this.setTexture(this.textures[round % this.textures.length]);
    @@ -280,13 +345,13 @@ PIXI.MovieClip.prototype.updateTransform = function()
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_display_Sprite.js.html b/docs/files/src_pixi_display_Sprite.js.html index 48e9042..84f1dce 100644 --- a/docs/files/src_pixi_display_Sprite.js.html +++ b/docs/files/src_pixi_display_Sprite.js.html @@ -2,12 +2,12 @@ - src/pixi/display/Sprite.js - Pixi.JS - - - - - + src/pixi/display/Sprite.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,69 +166,78 @@
    -

    File: src/pixi/display/Sprite.js

    +

    File: src/pixi/display/Sprite.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
     PIXI.blendModes = {};
     PIXI.blendModes.NORMAL = 0;
     PIXI.blendModes.SCREEN = 1;
     
     
    -/**
    -@class Sprite
    -@extends DisplayObjectContainer
    -@constructor
    -@param texture {Texture}
    -@type String
    -*/
    +/**
    + * The SPrite object is the base for all textured objects that are rendered to the screen
    + *
    + * @class Sprite
    + * @extends DisplayObjectContainer
    + * @constructor
    + * @param texture {Texture} The texture for this sprite
    + * @type String
    + */
     PIXI.Sprite = function(texture)
     {
     	PIXI.DisplayObjectContainer.call( this );
    -	
    -	 /**
    +
    +	/**
     	 * The anchor sets the origin point of the texture.
     	 * The default is 0,0 this means the textures origin is the top left 
     	 * Setting than anchor to 0.5,0.5 means the textures origin is centered
     	 * Setting the anchor to 1,1 would mean the textures origin points will be the bottom right
    +	 *
          * @property anchor
          * @type Point
    -     */
    +     */
     	this.anchor = new PIXI.Point();
    -	
    -	/**
    +
    +	/**
     	 * The texture that the sprite is using
    +	 *
     	 * @property texture
     	 * @type Texture
    -	 */
    +	 */
     	this.texture = texture;
    -	
    -	/**
    +
    +	/**
     	 * The blend mode of sprite.
     	 * currently supports PIXI.blendModes.NORMAL and PIXI.blendModes.SCREEN
    +	 *
     	 * @property blendMode
    -	 * @type uint
    -	 */
    +	 * @type Number
    +	 */
     	this.blendMode = PIXI.blendModes.NORMAL;
    -	
    -	/**
    +
    +	/**
     	 * The width of the sprite (this is initially set by the texture)
    -	 * @property width
    -	 * @type #Number
    -	 */
    +	 *
    +	 * @property _width
    +	 * @type Number
    +	 * @private
    +	 */
     	this._width = 0;
    -	
    -	/**
    +
    +	/**
     	 * The height of the sprite (this is initially set by the texture)
    -	 * @property height
    -	 * @type #Number
    -	 */
    +	 *
    +	 * @property _height
    +	 * @type Number
    +	 * @private
    +	 */
     	this._height = 0;
    -	
    +
     	if(texture.baseTexture.hasLoaded)
     	{
     		this.updateFrame = true;
    @@ -214,81 +247,103 @@ PIXI.Sprite = function(texture)
     		this.onTextureUpdateBind = this.onTextureUpdate.bind(this);
     		this.texture.addEventListener( 'update', this.onTextureUpdateBind );
     	}
    -	
    +
     	this.renderable = true;
    -	
    -	// thi next bit is here for the docs...
    -	
    -	
     }
     
    -// constructor
    -PIXI.Sprite.constructor = PIXI.Sprite;
    +// constructor
     PIXI.Sprite.prototype = Object.create( PIXI.DisplayObjectContainer.prototype );
    +PIXI.Sprite.prototype.constructor = PIXI.Sprite;
     
    -// OOH! shiney new getters and setters for width and height
    -// The width and height now modify the scale (this is what flash does, nice and tidy!)
    +/**
    + * The width of the sprite, setting this will actually modify the scale to acheive the value set
    + *
    + * @property width
    + * @type Number
    + */
     Object.defineProperty(PIXI.Sprite.prototype, 'width', {
         get: function() {
             return this.scale.x * this.texture.frame.width;
         },
         set: function(value) {
    -    	this.scale.x = value / this.texture.frame.width
    +    	this.scale.x = value / this.texture.frame.width
             this._width = value;
         }
     });
     
    +/**
    + * The height of the sprite, setting this will actually modify the scale to acheive the value set
    + *
    + * @property height
    + * @type Number
    + */
     Object.defineProperty(PIXI.Sprite.prototype, 'height', {
         get: function() {
             return  this.scale.y * this.texture.frame.height;
         },
         set: function(value) {
    -    	this.scale.y = value / this.texture.frame.height
    +    	this.scale.y = value / this.texture.frame.height
             this._height = value;
         }
     });
    - 
    -/**
    -@method setTexture
    -@param texture {Texture} The PIXI texture that is displayed by the sprite
    -*/
    +
    +/**
    + * Sets the texture of the sprite
    + *
    + * @method setTexture
    + * @param texture {Texture} The PIXI texture that is displayed by the sprite
    + */
     PIXI.Sprite.prototype.setTexture = function(texture)
     {
    -	// stop current texture;
    +	// stop current texture;
     	if(this.texture.baseTexture != texture.baseTexture)
     	{
     		this.textureChange = true;	
    +		this.texture = texture;
    +		
    +		if(this.__renderGroup)
    +		{
    +			this.__renderGroup.updateTexture(this);
    +		}
    +	}
    +	else
    +	{
    +		this.texture = texture;
     	}
     	
    -	this.texture = texture;
     	this.updateFrame = true;
     }
     
    -/**
    +/**
    + * When the texture is updated, this event will fire to update the scale and frame
    + *
    + * @method onTextureUpdate
    + * @param event
      * @private
    - */
    + */
     PIXI.Sprite.prototype.onTextureUpdate = function(event)
     {
    -	//this.texture.removeEventListener( 'update', this.onTextureUpdateBind );
    +	//this.texture.removeEventListener( 'update', this.onTextureUpdateBind );
     	
    -	// so if _width is 0 then width was not set..
    -	if(this._width)this.scale.x = this._width / this.texture.frame.width;
    -	if(this._height)this.scale.y = this._height / this.texture.frame.height;
    +	// so if _width is 0 then width was not set..
    +	if(this._width)this.scale.x = this._width / this.texture.frame.width;
    +	if(this._height)this.scale.y = this._height / this.texture.frame.height;
     	
     	this.updateFrame = true;
     }
     
    -// some helper functions..
    +// some helper functions..
     
    -/**
    +/**
      * 
      * Helper function that creates a sprite that will contain a texture from the TextureCache based on the frameId
      * The frame ids are created when a Texture packer file has been loaded
    + *
      * @method fromFrame
      * @static
      * @param frameId {String} The frame Id of the texture in the cache
      * @return {Sprite} A new Sprite using a texture from the texture cache matching the frameId
    - */
    + */
     PIXI.Sprite.fromFrame = function(frameId)
     {
     	var texture = PIXI.TextureCache[frameId];
    @@ -296,22 +351,22 @@ PIXI.Sprite.fromFrame = function(frameId)
     	return new PIXI.Sprite(texture);
     }
     
    -/**
    +/**
      * 
      * Helper function that creates a sprite that will contain a texture based on an image url
      * If the image is not in the texture cache it will be loaded
    + *
      * @method fromImage
      * @static
    - * @param The image url of the texture
    + * @param imageId {String} The image url of the texture
      * @return {Sprite} A new Sprite using a texture from the texture cache matching the image id
    - */
    + */
     PIXI.Sprite.fromImage = function(imageId)
     {
     	var texture = PIXI.Texture.fromImage(imageId);
     	return new PIXI.Sprite(texture);
     }
     
    -
         
    @@ -321,13 +376,13 @@ PIXI.Sprite.fromImage = function(imageId)
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_display_Stage.js.html b/docs/files/src_pixi_display_Stage.js.html index 6c0dc32..7c8bc2b 100644 --- a/docs/files/src_pixi_display_Stage.js.html +++ b/docs/files/src_pixi_display_Stage.js.html @@ -2,12 +2,12 @@ - src/pixi/display/Stage.js - Pixi.JS - - - - - + src/pixi/display/Stage.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,58 +166,101 @@
    -

    File: src/pixi/display/Stage.js

    +

    File: src/pixi/display/Stage.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -/**
    -A Stage represents the root of the display tree. Everything connected to the stage is rendered
    -@class Stage
    -@extends DisplayObjectContainer
    -@constructor
    -@param backgroundColor {Number} the background color of the stage
    -@param interactive {Boolean} enable / disable interaction (default is false)
    -*/
    -PIXI.Stage = function(backgroundColor, interactive)
    +/**
    + * A Stage represents the root of the display tree. Everything connected to the stage is rendered
    + *
    + * @class Stage
    + * @extends DisplayObjectContainer
    + * @constructor
    + * @param backgroundColor {Number} the background color of the stage, easiest way to pass this in is in hex format
    + *		like: 0xFFFFFF for white
    + */
    +PIXI.Stage = function(backgroundColor)
     {
    -	
     	PIXI.DisplayObjectContainer.call( this );
    -	
    -	this.worldTransform = PIXI.mat3.create()
    +
    +	/**
    +	 * [read-only] Current transform of the object based on world (parent) factors
    +	 *
    +	 * @property worldTransform
    +	 * @type Mat3
    +	 * @readOnly
    +	 * @private
    +	 */
    +	this.worldTransform = PIXI.mat3.create();
    +
    +	/**
    +	 * Whether or not the stage is interactive
    +	 *
    +	 * @property interactive
    +	 * @type Boolean
    +	 */
    +	this.interactive = true;
    +
    +	/**
    +	 * The interaction manage for this stage, manages all interactive activity on the stage
    +	 *
    +	 * @property interactive
    +	 * @type InteractionManager
    +	 */
    +	this.interactionManager = new PIXI.InteractionManager(this);
    +
    +	/**
    +	 * Whether the stage is dirty and needs to have interactions updated
    +	 *
    +	 * @property dirty
    +	 * @type Boolean
    +	 * @private
    +	 */
    +	this.dirty = true;
    +
     	this.__childrenAdded = [];
     	this.__childrenRemoved = [];
    -	
    -	//this.childIndex = 0;
    +
    +	//the stage is it's own stage
     	this.stage = this;
    -	this.interactive = interactive;
    -	
    +
    +	//optimize hit detection a bit
     	this.stage.hitArea = new PIXI.Rectangle(0,0,100000, 100000);
    -	
    -	// interaction!
    -	// this.interactive = !!interactive;
    -	this.interactionManager = new PIXI.InteractionManager(this);
    -	
    +
     	this.setBackgroundColor(backgroundColor);
     	this.worldVisible = true;
    -	this.stage.dirty = true;
     }
     
    -// constructor
    -PIXI.Stage.constructor = PIXI.Stage;
    -
    +// constructor
     PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype );
    +PIXI.Stage.prototype.constructor = PIXI.Stage;
     
    -/**
    -@method updateTransform
    -@internal
    -*/
    +/**
    + * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element.
    + * This is useful for when you have other DOM elements ontop of the Canvas element.
    + *
    + * @method setInteractionDelegate
    + * @param domElement {DOMElement} This new domElement which will receive mouse/touch events
    + */
    +PIXI.Stage.prototype.setInteractionDelegate = function(domElement)
    +{
    +	this.interactionManager.setTargetDomElement( domElement );
    +}
    +
    +/*
    + * Updates the object transform for rendering
    + *
    + * @method updateTransform
    + * @private
    + */
     PIXI.Stage.prototype.updateTransform = function()
     {
     	this.worldAlpha = 1;		
    +	this.vcount = PIXI.visibleCount;
     	
     	for(var i=0,j=this.children.length; i<j; i++)
     	{
    @@ -203,17 +270,21 @@ PIXI.Stage.prototype.updateTransform = function()
     	if(this.dirty)
     	{
     		this.dirty = false;
    -		// update interactive!
    +		// update interactive!
     		this.interactionManager.dirty = true;
     	}
    -
    +	
    +	
     	if(this.interactive)this.interactionManager.update();
     }
     
    -/**
    +/**
    + * Sets the background color for the stage
    + *
      * @method setBackgroundColor
    - * @param backgroundColor {Number}
    - */
    + * @param backgroundColor {Number} the color of the background, easiest way to pass this in is in hex format
    + *		like: 0xFFFFFF for white
    + */
     PIXI.Stage.prototype.setBackgroundColor = function(backgroundColor)
     {
     	this.backgroundColor = backgroundColor || 0x000000;
    @@ -223,47 +294,16 @@ PIXI.Stage.prototype.setBackgroundColor = function(backgroundColor)
     	this.backgroundColorString = "#" + hex;
     }
     
    -/**
    +/**
      * This will return the point containing global coords of the mouse.
    + *
      * @method getMousePosition
      * @return {Point} The point containing the coords of the global InteractionData position.
    - */
    + */
     PIXI.Stage.prototype.getMousePosition = function()
     {
     	return this.interactionManager.mouse.global;
     }
    -/*
    -PIXI.Stage.prototype.__addChild = function(child)
    -{
    -	if(child.interactive)this.dirty = true;
    -	
    -	child.stage = this;
    -	
    -	if(child.children)
    -	{
    -		for (var i=0; i < child.children.length; i++) 
    -		{
    -		  	this.__addChild(child.children[i]);
    -		};
    -	}
    -	
    -}
    -
    -
    -PIXI.Stage.prototype.__removeChild = function(child)
    -{
    -	if(child.interactive)this.dirty = true;
    -	
    -	child.stage = undefined;
    -	
    -	if(child.children)
    -	{
    -		for(var i=0,j=child.children.length; i<j; i++)
    -		{
    -		  	this.__removeChild(child.children[i]);
    -		}
    -	}
    -}*/
     
         
    @@ -274,13 +314,13 @@ PIXI.Stage.prototype.__removeChild = function(child)
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_extras_CustomRenderable.js.html b/docs/files/src_pixi_extras_CustomRenderable.js.html index 83ef08c..8592913 100644 --- a/docs/files/src_pixi_extras_CustomRenderable.js.html +++ b/docs/files/src_pixi_extras_CustomRenderable.js.html @@ -2,12 +2,12 @@ - src/pixi/extras/CustomRenderable.js - Pixi.JS - - - - - + src/pixi/extras/CustomRenderable.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,47 +166,65 @@
    -

    File: src/pixi/extras/CustomRenderable.js

    +

    File: src/pixi/extras/CustomRenderable.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
     
    -/**
    - * Need to finalize this a bit more but works! Its in but will be working on this feature properly next..:)
    - * @class CustomRenderable 
    +/**
    + * This object is one that will allow you to specify custom rendering functions based on render type
    + *
    + * @class CustomRenderable
      * @extends DisplayObject
      * @constructor
    - */
    + */
     PIXI.CustomRenderable = function()
     {
     	PIXI.DisplayObject.call( this );
     	
    +	this.renderable = true;
     }
     
    -// constructor
    -PIXI.CustomRenderable.constructor = PIXI.CustomRenderable;
    +// constructor
     PIXI.CustomRenderable.prototype = Object.create( PIXI.DisplayObject.prototype );
    +PIXI.CustomRenderable.prototype.constructor = PIXI.CustomRenderable;
     
    +/**
    + * If this object is being rendered by a CanvasRenderer it will call this callback
    + *
    + * @method renderCanvas
    + * @param renderer {CanvasRenderer} The renderer instance
    + */
     PIXI.CustomRenderable.prototype.renderCanvas = function(renderer)
     {
    -	// override!
    +	// override!
     }
     
    -
    +/**
    + * If this object is being rendered by a WebGLRenderer it will call this callback to initialize
    + *
    + * @method initWebGL
    + * @param renderer {WebGLRenderer} The renderer instance
    + */
     PIXI.CustomRenderable.prototype.initWebGL = function(renderer)
     {
    -	// override!
    +	// override!
     }
     
    -
    +/**
    + * If this object is being rendered by a WebGLRenderer it will call this callback
    + *
    + * @method renderWebGL
    + * @param renderer {WebGLRenderer} The renderer instance
    + */
     PIXI.CustomRenderable.prototype.renderWebGL = function(renderGroup, projectionMatrix)
     {
    -	// not sure if both needed? but ya have for now!
    -	// override!
    +	// not sure if both needed? but ya have for now!
    +	// override!
     }
     
     
    @@ -195,13 +237,13 @@ PIXI.CustomRenderable.prototype.renderWebGL = function(renderGroup, projectionMa
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_extras_Rope.js.html b/docs/files/src_pixi_extras_Rope.js.html index 37a22e4..34c0cf3 100644 --- a/docs/files/src_pixi_extras_Rope.js.html +++ b/docs/files/src_pixi_extras_Rope.js.html @@ -2,12 +2,12 @@ - src/pixi/extras/Rope.js - Pixi.JS - - - - - + src/pixi/extras/Rope.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,20 +166,20 @@
    -

    File: src/pixi/extras/Rope.js

    +

    File: src/pixi/extras/Rope.js

    -/**
    - * @author Mat Groves http://matgroves.com/
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/
    + */
     
     
     PIXI.Rope = function(texture, points)
     {
     	PIXI.Strip.call( this, texture );
     	this.points = points;
    -	
    +
     	try
     	{
     		this.verticies = new Float32Array( points.length * 4);
    @@ -166,117 +190,117 @@ PIXI.Rope = function(texture, points)
     	catch(error)
     	{
     		this.verticies = verticies
    -		
    +
     		this.uvs = uvs
     		this.colors = colors
     		this.indices = indices
     	}
    -	
    +
     	this.refresh();
     }
     
     
    -// constructor
    -PIXI.Rope.constructor = PIXI.Rope;
    +// constructor
     PIXI.Rope.prototype = Object.create( PIXI.Strip.prototype );
    +PIXI.Rope.prototype.constructor = PIXI.Rope;
     
     PIXI.Rope.prototype.refresh = function()
     {
     	var points = this.points;
     	if(points.length < 1)return;
    -	
    +
     	var uvs = this.uvs
     	var indices = this.indices;
     	var colors = this.colors;
    -	
    +
     	var lastPoint = points[0];
     	var nextPoint;
     	var perp = {x:0, y:0};
     	var point = points[0];
    -	
    +
     	this.count-=0.2;
    -	
    -	
    +
    +
     	uvs[0] = 0
     	uvs[1] = 1
     	uvs[2] = 0
     	uvs[3] = 1
    -	
    +
     	colors[0] = 1;
     	colors[1] = 1;
    -	
    +
     	indices[0] = 0;
     	indices[1] = 1;
    -	
    +
     	var total = points.length;
    -		
    -	for (var i =  1; i < total; i++) 
    +
    +	for (var i =  1; i < total; i++)
     	{
    -		
    +
     		var point = points[i];
     		var index = i * 4;
    -		// time to do some smart drawing!
    -		var amount = i/(total-1)
    -		
    +		// time to do some smart drawing!
    +		var 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;
     	}
     }
     
     PIXI.Rope.prototype.updateTransform = function()
     {
    -	
    +
     	var points = this.points;
     	if(points.length < 1)return;
    -	
    -	var verticies = this.verticies 
    -	
    +
    +	var verticies = this.verticies
    +
     	var lastPoint = points[0];
     	var nextPoint;
     	var perp = {x:0, y:0};
     	var point = points[0];
    -	
    +
     	this.count-=0.2;
    -	
    -	verticies[0] = point.x + perp.x 
    -	verticies[1] = point.y + perp.y //+ 200
    -	verticies[2] = point.x - perp.x 
    -	verticies[3] = point.y - perp.y//+200
    -	// time to do some smart drawing!
    -	
    +
    +	verticies[0] = point.x + perp.x
    +	verticies[1] = point.y + perp.y //+ 200
    +	verticies[2] = point.x - perp.x
    +	verticies[3] = point.y - perp.y//+200
    +	// time to do some smart drawing!
    +
     	var total = points.length;
    -		
    -	for (var i =  1; i < total; i++) 
    +
    +	for (var i =  1; i < total; i++)
     	{
    -		
    +
     		var point = points[i];
     		var index = i * 4;
    -		
    +
     		if(i < points.length-1)
     		{
     			nextPoint = points[i+1];
    @@ -285,35 +309,35 @@ PIXI.Rope.prototype.updateTransform = function()
     		{
     			nextPoint = point
     		}
    -		
    +
     		perp.y = -(nextPoint.x - lastPoint.x);
     		perp.x = nextPoint.y - lastPoint.y;
    -		
    -		var ratio = (1 - (i / (total-1))) * 10;
    +
    +		var ratio = (1 - (i / (total-1))) * 10;
     				if(ratio > 1)ratio = 1;
    -				
    +
     		var perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y);
    -		var num = this.texture.height/2//(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio;
    -		perp.x /= perpLength;
    -		perp.y /= perpLength;
    -	
    +		var 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;
    -		
    -		verticies[index] = point.x + perp.x 
    +
    +		verticies[index] = point.x + perp.x
     		verticies[index+1] = point.y + perp.y
    -		verticies[index+2] = point.x - perp.x 
    +		verticies[index+2] = point.x - perp.x
     		verticies[index+3] = point.y - perp.y
     
     		lastPoint = point;
     	}
    -	
    +
     	PIXI.DisplayObjectContainer.prototype.updateTransform.call( this );
     }
     
     PIXI.Rope.prototype.setTexture = function(texture)
     {
    -	// stop current texture 
    +	// stop current texture
     	this.texture = texture;
     	this.updateFrame = true;
     }
    @@ -331,13 +355,13 @@ PIXI.Rope.prototype.setTexture = function(texture)
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_extras_Spine.js.html b/docs/files/src_pixi_extras_Spine.js.html index ba18005..b1df202 100644 --- a/docs/files/src_pixi_extras_Spine.js.html +++ b/docs/files/src_pixi_extras_Spine.js.html @@ -2,12 +2,12 @@ - src/pixi/extras/Spine.js - Pixi.JS - - - - - + src/pixi/extras/Spine.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,122 +166,141 @@
    -

    File: src/pixi/extras/Spine.js

    +

    File: src/pixi/extras/Spine.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi
    - * 
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi
    + *
      * Awesome JS run time provided by EsotericSoftware
    - * https://github.com/EsotericSoftware/spine-runtimes
    - * 
    - */
    + * https://github.com/EsotericSoftware/spine-runtimes
    + *
    + */
     
    -/**
    +/**
      * 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
    - * Also due to a clash of names  You will need to change the extension of the spine file from *.json to *.anim for it to load
    - * See example 12 (http://www.goodboydigital.com/pixijs/examples/12/) to see a working example and check out the source
    + * See example 12 (http://www.goodboydigital.com/pixijs/examples/12/) to see a working example and check out the source
    + *
      * @class Spine
    - * @constructor
      * @extends DisplayObjectContainer
    - * @param {String} url the url of the spine anim file to be used
    - */
    -PIXI.Spine = function(url)
    -{
    + * @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)
    -	{
    +
    +	if (!this.spineData) {
     		throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: " + url);
    -		return;
     	}
    -	
    -	this.count = 0;
    -	
    -	this.sprites = [];
    -	
    +
     	this.skeleton = new spine.Skeleton(this.spineData);
     	this.skeleton.updateWorldTransform();
     
    -	this.stateData = new spine.AnimationStateData(this.spineData);	
    +	this.stateData = new spine.AnimationStateData(this.spineData);
     	this.state = new spine.AnimationState(this.stateData);
    -	
    -	// add the sprites..
    -	for (var i = 0; i < this.skeleton.drawOrder.length; i++) {
    -		
    -		var attachmentName = this.skeleton.drawOrder[i].data.attachmentName;
    -		
    -		// kind of an assumtion here. that its a png
    -		if(!PIXI.TextureCache[attachmentName])
    -		{
    -			attachmentName += ".png";
    -		}
    -		
    -		
    -		var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(attachmentName));
    -		sprite.anchor.x = sprite.anchor.y = 0.5;
    -		this.addChild(sprite);
    -		this.sprites.push(sprite);
    -	};
    -}
     
    -PIXI.Spine.constructor = PIXI.Spine;
    -PIXI.Spine.prototype = Object.create( PIXI.DisplayObjectContainer.prototype );
    -PIXI.Spine.prototype.updateTransform = function()
    -{
    -	// TODO should make this time based really..
    -	this.state.update(1/60);
    +	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)) {
    +			continue;
    +		}
    +		var spriteName = attachment.rendererObject.name;
    +		var sprite = this.createSprite(slot, attachment.rendererObject);
    +		slot.currentSprite = sprite;
    +		slot.currentSpriteName = spriteName;
    +		slotContainer.addChild(sprite);
    +	}
    +};
    +
    +PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype);
    +PIXI.Spine.prototype.constructor = PIXI.Spine;
    +
    +/*
    + * Updates the object transform for rendering
    + *
    + * @method updateTransform
    + * @private
    + */
    +PIXI.Spine.prototype.updateTransform = function () {
    +	this.lastTime = this.lastTime || Date.now();
    +	var timeDelta = (Date.now() - this.lastTime) * 0.001;
    +	this.lastTime = Date.now();
    +	this.state.update(timeDelta);
     	this.state.apply(this.skeleton);
     	this.skeleton.updateWorldTransform();
     
    -	
    -	for (var i = 0; i < this.skeleton.drawOrder.length; i++) 
    -	{
    -		var slot = this.skeleton.drawOrder[i];
    +	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 instanceof spine.RegionAttachment)) {
    +			slotContainer.visible = false;
    +			continue;
    +		}
     
    -		var x = slot.bone.worldX + slot.attachment.x * slot.bone.m00 + slot.attachment.y * slot.bone.m01 + slot.attachment.width * 0.5;
    -		var y = slot.bone.worldY + slot.attachment.x * slot.bone.m10 + slot.attachment.y * slot.bone.m11 + slot.attachment.height * 0.5;
    -		//console.log(x + ' : ' + y);
    -		
    -		 
    -			//console.log(slot.attachment.name)
    -			if(slot.cacheName != slot.attachment.name)
    -			{
    -				var attachmentName = slot.attachment.name;
    -		
    -				if(!PIXI.TextureCache[attachmentName])
    -				{
    -					attachmentName += ".png";
    +		if (attachment.rendererObject) {
    +			if (!slot.currentSpriteName || slot.currentSpriteName != attachment.name) {
    +				var spriteName = attachment.rendererObject.name;
    +				if (slot.currentSprite !== undefined) {
    +					slot.currentSprite.visible = false;
     				}
    -				
    -				this.sprites[i].setTexture(PIXI.TextureCache[attachmentName]);
    -				
    -				slot.cacheName = slot.attachment.name;
    +				slot.sprites = slot.sprites || {};
    +				if (slot.sprites[spriteName] !== undefined) {
    +					slot.sprites[spriteName].visible = true;
    +				} else {
    +					var sprite = this.createSprite(slot, attachment.rendererObject);
    +					slotContainer.addChild(sprite);
    +				}
    +				slot.currentSprite = slot.sprites[spriteName];
    +				slot.currentSpriteName = spriteName;
     			}
    -		
    -		x += -((slot.attachment.width * (slot.bone.worldScaleX + slot.attachment.scaleX - 1))>>1);
    -		y += -((slot.attachment.height * (slot.bone.worldScaleY + slot.attachment.scaleY - 1))>>1);
    -		
    -		
    -		this.sprites[i].position.x = x;
    -		this.sprites[i].position.y = y;
    -		this.sprites[i].rotation = (-(slot.bone.worldRotation + slot.attachment.rotation)) * (Math.PI/180);
    -	}	
    -	
    -	PIXI.DisplayObjectContainer.prototype.updateTransform.call(this);
    -}
    +		}
    +		slotContainer.visible = true;
     
    -/*
    +		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 * Math.PI / 180);
    +	}
    +
    +	PIXI.DisplayObjectContainer.prototype.updateTransform.call(this);
    +};
    +
    +
    +PIXI.Spine.prototype.createSprite = function (slot, descriptor) {
    +	var name = PIXI.TextureCache[descriptor.name] ? descriptor.name : descriptor.name + ".png";
    +	var sprite = new PIXI.Sprite(PIXI.Texture.fromFrame(name));
    +	sprite.scale = descriptor.scale;
    +	sprite.rotation = descriptor.rotation;
    +	sprite.anchor.x = sprite.anchor.y = 0.5;
    +
    +	slot.sprites = slot.sprites || {};
    +	slot.sprites[descriptor.name] = sprite;
    +	return sprite;
    +};
    +
    +/*
      * Awesome JS run time provided by EsotericSoftware
    - * 
    - * https://github.com/EsotericSoftware/spine-runtimes
    - * 
    - */
    + *
    + * https://github.com/EsotericSoftware/spine-runtimes
    + *
    + */
     
     var spine = {};
     
    @@ -291,8 +334,8 @@ spine.Bone.prototype = {
     	x: 0, y: 0,
     	rotation: 0,
     	scaleX: 1, scaleY: 1,
    -	m00: 0, m01: 0, worldX: 0, // a b x
    -	m10: 0, m11: 0, worldY: 0, // c d y
    +	m00: 0, m01: 0, worldX: 0, // a b x
    +	m10: 0, m11: 0, worldY: 0, // c d y
     	worldRotation: 0,
     	worldScaleX: 1, worldScaleY: 1,
     	updateWorldTransform: function (flipX, flipY) {
    @@ -310,7 +353,7 @@ spine.Bone.prototype = {
     			this.worldScaleY = this.scaleY;
     			this.worldRotation = this.rotation;
     		}
    -		var radians = this.worldRotation * Math.PI / 180;
    +		var radians = this.worldRotation * Math.PI / 180;
     		var cos = Math.cos(radians);
     		var sin = Math.sin(radians);
     		this.m00 = cos * this.worldScaleX;
    @@ -366,7 +409,7 @@ spine.Slot.prototype = {
     		this.g = data.g;
     		this.b = data.b;
     		this.a = data.a;
    -		
    +
     		var slotDatas = this.skeleton.data.slots;
     		for (var i = 0, n = slotDatas.length; i < n; i++) {
     			if (slotDatas[i] == data) {
    @@ -424,7 +467,7 @@ spine.Animation.prototype = {
     
     spine.binarySearch = function (values, target, step) {
     	var low = 0;
    -	var high = Math.floor(values.length / step) - 2;
    +	var high = Math.floor(values.length / step) - 2;
     	if (high == 0) return step;
     	var current = high >>> 1;
     	while (true) {
    @@ -443,21 +486,21 @@ spine.linearSearch = function (values, target, step) {
     };
     
     spine.Curves = function (frameCount) {
    -	this.curves = []; // dfx, dfy, ddfx, ddfy, dddfx, dddfy, ...
    +	this.curves = []; // dfx, dfy, ddfx, ddfy, dddfx, dddfy, ...
     	this.curves.length = (frameCount - 1) * 6;
     };
     spine.Curves.prototype = {
     	setLinear: function (frameIndex) {
    -		this.curves[frameIndex * 6] = 0/*LINEAR*/;
    +		this.curves[frameIndex * 6] = 0/*LINEAR*/;
     	},
     	setStepped: function (frameIndex) {
    -		this.curves[frameIndex * 6] = -1/*STEPPED*/;
    +		this.curves[frameIndex * 6] = -1/*STEPPED*/;
     	},
    -	/** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next.
    +	/** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next.
     	 * cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of
    -	 * the difference between the keyframe's values. */
    +	 * the difference between the keyframe's values. */
     	setCurve: function (frameIndex, cx1, cy1, cx2, cy2) {
    -		var subdiv_step = 1 / 10/*BEZIER_SEGMENTS*/;
    +		var subdiv_step = 1 / 10/*BEZIER_SEGMENTS*/;
     		var subdiv_step2 = subdiv_step * subdiv_step;
     		var subdiv_step3 = subdiv_step2 * subdiv_step;
     		var pre1 = 3 * subdiv_step;
    @@ -482,20 +525,20 @@ spine.Curves.prototype = {
     		var curveIndex = frameIndex * 6;
     		var curves = this.curves;
     		var dfx = curves[curveIndex];
    -		if (!dfx/*LINEAR*/) return percent;
    -		if (dfx == -1/*STEPPED*/) return 0;
    +		if (!dfx/*LINEAR*/) return percent;
    +		if (dfx == -1/*STEPPED*/) return 0;
     		var dfy = curves[curveIndex + 1];
     		var ddfx = curves[curveIndex + 2];
     		var ddfy = curves[curveIndex + 3];
     		var dddfx = curves[curveIndex + 4];
     		var dddfy = curves[curveIndex + 5];
     		var x = dfx, y = dfy;
    -		var i = 10/*BEZIER_SEGMENTS*/ - 2;
    +		var i = 10/*BEZIER_SEGMENTS*/ - 2;
     		while (true) {
     			if (x >= percent) {
     				var lastX = x - dfx;
     				var lastY = y - dfy;
    -				return lastY + (y - lastY) * (percent - lastX) / (x - lastX);
    +				return lastY + (y - lastY) * (percent - lastX) / (x - lastX);
     			}
     			if (i == 0) break;
     			i--;
    @@ -506,19 +549,19 @@ spine.Curves.prototype = {
     			x += dfx;
     			y += dfy;
     		}
    -		return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1.
    +		return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1.
     	}
     };
     
     spine.RotateTimeline = function (frameCount) {
     	this.curves = new spine.Curves(frameCount);
    -	this.frames = []; // time, angle, ...
    +	this.frames = []; // time, angle, ...
     	this.frames.length = frameCount * 2;
     };
     spine.RotateTimeline.prototype = {
     	boneIndex: 0,
     	getFrameCount: function () {
    -		return this.frames.length / 2;
    +		return this.frames.length / 2;
     	},
     	setFrame: function (frameIndex, time, angle) {
     		frameIndex *= 2;
    @@ -527,11 +570,11 @@ spine.RotateTimeline.prototype = {
     	},
     	apply: function (skeleton, time, alpha) {
     		var frames = this.frames;
    -		if (time < frames[0]) return; // Time is before first frame.
    +		if (time < frames[0]) return; // Time is before first frame.
     
     		var bone = skeleton.bones[this.boneIndex];
     
    -		if (time >= frames[frames.length - 2]) { // Time is after last frame.
    +		if (time >= frames[frames.length - 2]) { // Time is after last frame.
     			var amount = bone.data.rotation + frames[frames.length - 1] - bone.rotation;
     			while (amount > 180)
     				amount -= 360;
    @@ -541,14 +584,14 @@ spine.RotateTimeline.prototype = {
     			return;
     		}
     
    -		// Interpolate between the last frame and the current frame.
    +		// Interpolate between the last frame and the current frame.
     		var frameIndex = spine.binarySearch(frames, time, 2);
     		var lastFrameValue = frames[frameIndex - 1];
     		var frameTime = frames[frameIndex];
    -		var percent = 1 - (time - frameTime) / (frames[frameIndex - 2/*LAST_FRAME_TIME*/] - frameTime);
    -		percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent);
    +		var percent = 1 - (time - frameTime) / (frames[frameIndex - 2/*LAST_FRAME_TIME*/] - frameTime);
    +		percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent);
     
    -		var amount = frames[frameIndex + 1/*FRAME_VALUE*/] - lastFrameValue;
    +		var amount = frames[frameIndex + 1/*FRAME_VALUE*/] - lastFrameValue;
     		while (amount > 180)
     			amount -= 360;
     		while (amount < -180)
    @@ -564,13 +607,13 @@ spine.RotateTimeline.prototype = {
     
     spine.TranslateTimeline = function (frameCount) {
     	this.curves = new spine.Curves(frameCount);
    -	this.frames = []; // time, x, y, ...
    +	this.frames = []; // time, x, y, ...
     	this.frames.length = frameCount * 3;
     };
     spine.TranslateTimeline.prototype = {
     	boneIndex: 0,
     	getFrameCount: function () {
    -		return this.frames.length / 3;
    +		return this.frames.length / 3;
     	},
     	setFrame: function (frameIndex, time, x, y) {
     		frameIndex *= 3;
    @@ -580,37 +623,38 @@ spine.TranslateTimeline.prototype = {
     	},
     	apply: function (skeleton, time, alpha) {
     		var frames = this.frames;
    -		if (time < frames[0]) return; // Time is before first frame.
    +		if (time < frames[0]) return; // Time is before first frame.
     
     		var bone = skeleton.bones[this.boneIndex];
     
    -		if (time >= frames[frames.length - 3]) { // Time is after last frame.
    +		if (time >= frames[frames.length - 3]) { // Time is after last frame.
     			bone.x += (bone.data.x + frames[frames.length - 2] - bone.x) * alpha;
     			bone.y += (bone.data.y + frames[frames.length - 1] - bone.y) * alpha;
     			return;
     		}
     
    -		// Interpolate between the last frame and the current frame.
    +		// Interpolate between the last frame and the current frame.
     		var frameIndex = spine.binarySearch(frames, time, 3);
     		var lastFrameX = frames[frameIndex - 2];
     		var lastFrameY = frames[frameIndex - 1];
     		var frameTime = frames[frameIndex];
    -		var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime);
    -		percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent);
    -		bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha;
    -		bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha;
    +		var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime);
    +		percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent);
    +
    +		bone.x += (bone.data.x + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.x) * alpha;
    +		bone.y += (bone.data.y + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.y) * alpha;
     	}
     };
     
     spine.ScaleTimeline = function (frameCount) {
     	this.curves = new spine.Curves(frameCount);
    -	this.frames = []; // time, x, y, ...
    +	this.frames = []; // time, x, y, ...
     	this.frames.length = frameCount * 3;
     };
     spine.ScaleTimeline.prototype = {
     	boneIndex: 0,
     	getFrameCount: function () {
    -		return this.frames.length / 3;
    +		return this.frames.length / 3;
     	},
     	setFrame: function (frameIndex, time, x, y) {
     		frameIndex *= 3;
    @@ -620,40 +664,38 @@ spine.ScaleTimeline.prototype = {
     	},
     	apply: function (skeleton, time, alpha) {
     		var frames = this.frames;
    -		if (time < frames[0]) return; // Time is before first frame.
    -		
    +		if (time < frames[0]) return; // Time is before first frame.
    +
     		var bone = skeleton.bones[this.boneIndex];
     
    -		if (time >= frames[frames.length - 3]) { // Time is after last frame.
    +		if (time >= frames[frames.length - 3]) { // Time is after last frame.
     			bone.scaleX += (bone.data.scaleX - 1 + frames[frames.length - 2] - bone.scaleX) * alpha;
     			bone.scaleY += (bone.data.scaleY - 1 + frames[frames.length - 1] - bone.scaleY) * alpha;
    -			
    -			
     			return;
     		}
     
    -		// Interpolate between the last frame and the current frame.
    +		// Interpolate between the last frame and the current frame.
     		var frameIndex = spine.binarySearch(frames, time, 3);
     		var lastFrameX = frames[frameIndex - 2];
     		var lastFrameY = frames[frameIndex - 1];
     		var frameTime = frames[frameIndex];
    -		var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime);
    -		percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent);
    +		var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*LAST_FRAME_TIME*/] - frameTime);
    +		percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent);
     
    -		bone.scaleX += (bone.data.scaleX - 1 + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.scaleX) * alpha;
    -		bone.scaleY += (bone.data.scaleY - 1 + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.scaleY) * alpha;
    +		bone.scaleX += (bone.data.scaleX - 1 + lastFrameX + (frames[frameIndex + 1/*FRAME_X*/] - lastFrameX) * percent - bone.scaleX) * alpha;
    +		bone.scaleY += (bone.data.scaleY - 1 + lastFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - lastFrameY) * percent - bone.scaleY) * alpha;
     	}
     };
     
     spine.ColorTimeline = function (frameCount) {
     	this.curves = new spine.Curves(frameCount);
    -	this.frames = []; // time, r, g, b, a, ...
    +	this.frames = []; // time, r, g, b, a, ...
     	this.frames.length = frameCount * 5;
     };
     spine.ColorTimeline.prototype = {
     	slotIndex: 0,
     	getFrameCount: function () {
    -		return this.frames.length / 2;
    +		return this.frames.length / 2;
     	},
     	setFrame: function (frameIndex, time, x, y) {
     		frameIndex *= 5;
    @@ -665,10 +707,11 @@ spine.ColorTimeline.prototype = {
     	},
     	apply: function (skeleton, time, alpha) {
     		var frames = this.frames;
    -		if (time < frames[0]) return; // Time is before first frame.
    +		if (time < frames[0]) return; // Time is before first frame.
    +
     		var slot = skeleton.slots[this.slotIndex];
     
    -		if (time >= frames[frames.length - 5]) { // Time is after last frame.
    +		if (time >= frames[frames.length - 5]) { // Time is after last frame.
     			var i = frames.length - 1;
     			slot.r = frames[i - 3];
     			slot.g = frames[i - 2];
    @@ -677,20 +720,20 @@ spine.ColorTimeline.prototype = {
     			return;
     		}
     
    -		// Interpolate between the last frame and the current frame.
    +		// Interpolate between the last frame and the current frame.
     		var frameIndex = spine.binarySearch(frames, time, 5);
     		var lastFrameR = frames[frameIndex - 4];
     		var lastFrameG = frames[frameIndex - 3];
     		var lastFrameB = frames[frameIndex - 2];
     		var lastFrameA = frames[frameIndex - 1];
     		var frameTime = frames[frameIndex];
    -		var percent = 1 - (time - frameTime) / (frames[frameIndex - 5/*LAST_FRAME_TIME*/] - frameTime);
    -		percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent);
    +		var percent = 1 - (time - frameTime) / (frames[frameIndex - 5/*LAST_FRAME_TIME*/] - frameTime);
    +		percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent);
     
    -		var r = lastFrameR + (frames[frameIndex + 1/*FRAME_R*/] - lastFrameR) * percent;
    -		var g = lastFrameG + (frames[frameIndex + 2/*FRAME_G*/] - lastFrameG) * percent;
    -		var b = lastFrameB + (frames[frameIndex + 3/*FRAME_B*/] - lastFrameB) * percent;
    -		var a = lastFrameA + (frames[frameIndex + 4/*FRAME_A*/] - lastFrameA) * percent;
    +		var r = lastFrameR + (frames[frameIndex + 1/*FRAME_R*/] - lastFrameR) * percent;
    +		var g = lastFrameG + (frames[frameIndex + 2/*FRAME_G*/] - lastFrameG) * percent;
    +		var b = lastFrameB + (frames[frameIndex + 3/*FRAME_B*/] - lastFrameB) * percent;
    +		var a = lastFrameA + (frames[frameIndex + 4/*FRAME_A*/] - lastFrameA) * percent;
     		if (alpha < 1) {
     			slot.r += (r - slot.r) * alpha;
     			slot.g += (g - slot.g) * alpha;
    @@ -707,15 +750,15 @@ spine.ColorTimeline.prototype = {
     
     spine.AttachmentTimeline = function (frameCount) {
     	this.curves = new spine.Curves(frameCount);
    -	this.frames = []; // time, ...
    +	this.frames = []; // time, ...
     	this.frames.length = frameCount;
    -	this.attachmentNames = []; // time, ...
    +	this.attachmentNames = []; // time, ...
     	this.attachmentNames.length = frameCount;
     };
     spine.AttachmentTimeline.prototype = {
     	slotIndex: 0,
     	getFrameCount: function () {
    -		return this.frames.length / 2;
    +            return this.frames.length;
     	},
     	setFrame: function (frameIndex, time, attachmentName) {
     		this.frames[frameIndex] = time;
    @@ -723,20 +766,15 @@ spine.AttachmentTimeline.prototype = {
     	},
     	apply: function (skeleton, time, alpha) {
     		var frames = this.frames;
    -		if (time < frames[0]) return; // Time is before first frame.
    +		if (time < frames[0]) return; // Time is before first frame.
     
     		var frameIndex;
    -		if (time >= frames[frames.length - 1]) // Time is after last frame.
    +		if (time >= frames[frames.length - 1]) // Time is after last frame.
     			frameIndex = frames.length - 1;
     		else
     			frameIndex = spine.binarySearch(frames, time, 1) - 1;
     
     		var attachmentName = this.attachmentNames[frameIndex];
    -		//console.log(skeleton.slots[this.slotIndex])
    -		
    -		// change the name!
    -	//	skeleton.slots[this.slotIndex].attachmentName = attachmentName;
    -		
     		skeleton.slots[this.slotIndex].setAttachment(!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName));
     	}
     };
    @@ -749,21 +787,21 @@ spine.SkeletonData = function () {
     };
     spine.SkeletonData.prototype = {
     	defaultSkin: null,
    -	/** @return May be null. */
    +	/** @return May be null. */
     	findBone: function (boneName) {
     		var bones = this.bones;
     		for (var i = 0, n = bones.length; i < n; i++)
     			if (bones[i].name == boneName) return bones[i];
     		return null;
     	},
    -	/** @return -1 if the bone was not found. */
    +	/** @return -1 if the bone was not found. */
     	findBoneIndex: function (boneName) {
     		var bones = this.bones;
     		for (var i = 0, n = bones.length; i < n; i++)
     			if (bones[i].name == boneName) return i;
     		return -1;
     	},
    -	/** @return May be null. */
    +	/** @return May be null. */
     	findSlot: function (slotName) {
     		var slots = this.slots;
     		for (var i = 0, n = slots.length; i < n; i++) {
    @@ -771,21 +809,21 @@ spine.SkeletonData.prototype = {
     		}
     		return null;
     	},
    -	/** @return -1 if the bone was not found. */
    +	/** @return -1 if the bone was not found. */
     	findSlotIndex: function (slotName) {
     		var slots = this.slots;
     		for (var i = 0, n = slots.length; i < n; i++)
     			if (slots[i].name == slotName) return i;
     		return -1;
     	},
    -	/** @return May be null. */
    +	/** @return May be null. */
     	findSkin: function (skinName) {
     		var skins = this.skins;
     		for (var i = 0, n = skins.length; i < n; i++)
     			if (skins[i].name == skinName) return skins[i];
     		return null;
     	},
    -	/** @return May be null. */
    +	/** @return May be null. */
     	findAnimation: function (animationName) {
     		var animations = this.animations;
     		for (var i = 0, n = animations.length; i < n; i++)
    @@ -820,7 +858,7 @@ spine.Skeleton.prototype = {
     	r: 1, g: 1, b: 1, a: 1,
     	time: 0,
     	flipX: false, flipY: false,
    -	/** Updates the world transform for each bone. */
    +	/** Updates the world transform for each bone. */
     	updateWorldTransform: function () {
     		var flipX = this.flipX;
     		var flipY = this.flipY;
    @@ -828,7 +866,7 @@ spine.Skeleton.prototype = {
     		for (var i = 0, n = bones.length; i < n; i++)
     			bones[i].updateWorldTransform(flipX, flipY);
     	},
    -	/** Sets the bones and slots to their setup pose values. */
    +	/** Sets the bones and slots to their setup pose values. */
     	setToSetupPose: function () {
     		this.setBonesToSetupPose();
     		this.setSlotsToSetupPose();
    @@ -843,32 +881,32 @@ spine.Skeleton.prototype = {
     		for (var i = 0, n = slots.length; i < n; i++)
     			slots[i].setToSetupPose(i);
     	},
    -	/** @return May return null. */
    +	/** @return May return null. */
     	getRootBone: function () {
     		return this.bones.length == 0 ? null : this.bones[0];
     	},
    -	/** @return May be null. */
    +	/** @return May be null. */
     	findBone: function (boneName) {
     		var bones = this.bones;
     		for (var i = 0, n = bones.length; i < n; i++)
     			if (bones[i].data.name == boneName) return bones[i];
     		return null;
     	},
    -	/** @return -1 if the bone was not found. */
    +	/** @return -1 if the bone was not found. */
     	findBoneIndex: function (boneName) {
     		var bones = this.bones;
     		for (var i = 0, n = bones.length; i < n; i++)
     			if (bones[i].data.name == boneName) return i;
     		return -1;
     	},
    -	/** @return May be null. */
    +	/** @return May be null. */
     	findSlot: function (slotName) {
     		var slots = this.slots;
     		for (var i = 0, n = slots.length; i < n; i++)
     			if (slots[i].data.name == slotName) return slots[i];
     		return null;
     	},
    -	/** @return -1 if the bone was not found. */
    +	/** @return -1 if the bone was not found. */
     	findSlotIndex: function (slotName) {
     		var slots = this.slots;
     		for (var i = 0, n = slots.length; i < n; i++)
    @@ -880,18 +918,18 @@ spine.Skeleton.prototype = {
     		if (!skin) throw "Skin not found: " + skinName;
     		this.setSkin(skin);
     	},
    -	/** Sets the skin used to look up attachments not found in the {@link SkeletonData#getDefaultSkin() default skin}. Attachments
    +	/** Sets the skin used to look up attachments not found in the {@link SkeletonData#getDefaultSkin() default skin}. Attachments
     	 * from the new skin are attached if the corresponding attachment from the old skin was attached.
    -	 * @param newSkin May be null. */
    +	 * @param newSkin May be null. */
     	setSkin: function (newSkin) {
     		if (this.skin && newSkin) newSkin._attachAll(this, this.skin);
     		this.skin = newSkin;
     	},
    -	/** @return May be null. */
    +	/** @return May be null. */
     	getAttachmentBySlotName: function (slotName, attachmentName) {
     		return this.getAttachmentBySlotIndex(this.data.findSlotIndex(slotName), attachmentName);
     	},
    -	/** @return May be null. */
    +	/** @return May be null. */
     	getAttachmentBySlotIndex: function (slotIndex, attachmentName) {
     		if (this.skin) {
     			var attachment = this.skin.getAttachment(slotIndex, attachmentName);
    @@ -900,7 +938,7 @@ spine.Skeleton.prototype = {
     		if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName);
     		return null;
     	},
    -	/** @param attachmentName May be null. */
    +	/** @param attachmentName May be null. */
     	setAttachment: function (slotName, attachmentName) {
     		var slots = this.slots;
     		for (var i = 0, n = slots.size; i < n; i++) {
    @@ -908,11 +946,9 @@ spine.Skeleton.prototype = {
     			if (slot.data.name == slotName) {
     				var attachment = null;
     				if (attachmentName) {
    -					
     					attachment = this.getAttachment(i, attachmentName);
     					if (attachment == null) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName;
     				}
    -				
     				slot.setAttachment(attachment);
     				return;
     			}
    @@ -946,33 +982,33 @@ spine.RegionAttachment.prototype = {
     	setUVs: function (u, v, u2, v2, rotate) {
     		var uvs = this.uvs;
     		if (rotate) {
    -			uvs[2/*X2*/] = u;
    -			uvs[3/*Y2*/] = v2;
    -			uvs[4/*X3*/] = u;
    -			uvs[5/*Y3*/] = v;
    -			uvs[6/*X4*/] = u2;
    -			uvs[7/*Y4*/] = v;
    -			uvs[0/*X1*/] = u2;
    -			uvs[1/*Y1*/] = v2;
    +			uvs[2/*X2*/] = u;
    +			uvs[3/*Y2*/] = v2;
    +			uvs[4/*X3*/] = u;
    +			uvs[5/*Y3*/] = v;
    +			uvs[6/*X4*/] = u2;
    +			uvs[7/*Y4*/] = v;
    +			uvs[0/*X1*/] = u2;
    +			uvs[1/*Y1*/] = v2;
     		} else {
    -			uvs[0/*X1*/] = u;
    -			uvs[1/*Y1*/] = v2;
    -			uvs[2/*X2*/] = u;
    -			uvs[3/*Y2*/] = v;
    -			uvs[4/*X3*/] = u2;
    -			uvs[5/*Y3*/] = v;
    -			uvs[6/*X4*/] = u2;
    -			uvs[7/*Y4*/] = v2;
    +			uvs[0/*X1*/] = u;
    +			uvs[1/*Y1*/] = v2;
    +			uvs[2/*X2*/] = u;
    +			uvs[3/*Y2*/] = v;
    +			uvs[4/*X3*/] = u2;
    +			uvs[5/*Y3*/] = v;
    +			uvs[6/*X4*/] = u2;
    +			uvs[7/*Y4*/] = v2;
     		}
     	},
     	updateOffset: function () {
    -		var regionScaleX = this.width / this.regionOriginalWidth * this.scaleX;
    -		var regionScaleY = this.height / this.regionOriginalHeight * this.scaleY;
    -		var localX = -this.width / 2 * this.scaleX + this.regionOffsetX * regionScaleX;
    -		var localY = -this.height / 2 * this.scaleY + this.regionOffsetY * regionScaleY;
    +		var regionScaleX = this.width / this.regionOriginalWidth * this.scaleX;
    +		var regionScaleY = this.height / this.regionOriginalHeight * this.scaleY;
    +		var localX = -this.width / 2 * this.scaleX + this.regionOffsetX * regionScaleX;
    +		var localY = -this.height / 2 * this.scaleY + this.regionOffsetY * regionScaleY;
     		var localX2 = localX + this.regionWidth * regionScaleX;
     		var localY2 = localY + this.regionHeight * regionScaleY;
    -		var radians = this.rotation * Math.PI / 180;
    +		var radians = this.rotation * Math.PI / 180;
     		var cos = Math.cos(radians);
     		var sin = Math.sin(radians);
     		var localXCos = localX * cos + this.x;
    @@ -984,17 +1020,16 @@ spine.RegionAttachment.prototype = {
     		var localY2Cos = localY2 * cos + this.y;
     		var localY2Sin = localY2 * sin;
     		var offset = this.offset;
    -		offset[0/*X1*/] = localXCos - localYSin;
    -		offset[1/*Y1*/] = localYCos + localXSin;
    -		offset[2/*X2*/] = localXCos - localY2Sin;
    -		offset[3/*Y2*/] = localY2Cos + localXSin;
    -		offset[4/*X3*/] = localX2Cos - localY2Sin;
    -		offset[5/*Y3*/] = localY2Cos + localX2Sin;
    -		offset[6/*X4*/] = localX2Cos - localYSin;
    -		offset[7/*Y4*/] = localYCos + localX2Sin;
    +		offset[0/*X1*/] = localXCos - localYSin;
    +		offset[1/*Y1*/] = localYCos + localXSin;
    +		offset[2/*X2*/] = localXCos - localY2Sin;
    +		offset[3/*Y2*/] = localY2Cos + localXSin;
    +		offset[4/*X3*/] = localX2Cos - localY2Sin;
    +		offset[5/*Y3*/] = localY2Cos + localX2Sin;
    +		offset[6/*X4*/] = localX2Cos - localYSin;
    +		offset[7/*Y4*/] = localYCos + localX2Sin;
     	},
     	computeVertices: function (x, y, bone, vertices) {
    -		
     		x += bone.worldX;
     		y += bone.worldY;
     		var m00 = bone.m00;
    @@ -1002,14 +1037,14 @@ spine.RegionAttachment.prototype = {
     		var m10 = bone.m10;
     		var m11 = bone.m11;
     		var offset = this.offset;
    -		vertices[0/*X1*/] = offset[0/*X1*/] * m00 + offset[1/*Y1*/] * m01 + x;
    -		vertices[1/*Y1*/] = offset[0/*X1*/] * m10 + offset[1/*Y1*/] * m11 + y;
    -		vertices[2/*X2*/] = offset[2/*X2*/] * m00 + offset[3/*Y2*/] * m01 + x;
    -		vertices[3/*Y2*/] = offset[2/*X2*/] * m10 + offset[3/*Y2*/] * m11 + y;
    -		vertices[4/*X3*/] = offset[4/*X3*/] * m00 + offset[5/*X3*/] * m01 + x;
    -		vertices[5/*X3*/] = offset[4/*X3*/] * m10 + offset[5/*X3*/] * m11 + y;
    -		vertices[6/*X4*/] = offset[6/*X4*/] * m00 + offset[7/*Y4*/] * m01 + x;
    -		vertices[7/*Y4*/] = offset[6/*X4*/] * m10 + offset[7/*Y4*/] * m11 + y;
    +		vertices[0/*X1*/] = offset[0/*X1*/] * m00 + offset[1/*Y1*/] * m01 + x;
    +		vertices[1/*Y1*/] = offset[0/*X1*/] * m10 + offset[1/*Y1*/] * m11 + y;
    +		vertices[2/*X2*/] = offset[2/*X2*/] * m00 + offset[3/*Y2*/] * m01 + x;
    +		vertices[3/*Y2*/] = offset[2/*X2*/] * m10 + offset[3/*Y2*/] * m11 + y;
    +		vertices[4/*X3*/] = offset[4/*X3*/] * m00 + offset[5/*X3*/] * m01 + x;
    +		vertices[5/*X3*/] = offset[4/*X3*/] * m10 + offset[5/*X3*/] * m11 + y;
    +		vertices[6/*X4*/] = offset[6/*X4*/] * m00 + offset[7/*Y4*/] * m01 + x;
    +		vertices[7/*Y4*/] = offset[6/*X4*/] * m10 + offset[7/*Y4*/] * m11 + y;
     	}
     }
     
    @@ -1018,6 +1053,7 @@ spine.AnimationStateData = function (skeletonData) {
     	this.animationToMixTime = {};
     };
     spine.AnimationStateData.prototype = {
    +        defaultMix: 0,
     	setMixByName: function (fromName, toName, duration) {
     		var from = this.skeletonData.findAnimation(fromName);
     		if (!from) throw "Animation not found: " + fromName;
    @@ -1030,7 +1066,7 @@ spine.AnimationStateData.prototype = {
     	},
     	getMix: function (from, to) {
     		var time = this.animationToMixTime[from.name + ":" + to.name];
    -		return time ? time : 0;
    +            return time ? time : this.defaultMix;
     	}
     };
     
    @@ -1064,13 +1100,13 @@ spine.AnimationState.prototype = {
     		if (!this.current) return;
     		if (this.previous) {
     			this.previous.apply(skeleton, this.previousTime, this.previousLoop);
    -			var alpha = this.mixTime / this.mixDuration;
    +			var alpha = this.mixTime / this.mixDuration;
     			if (alpha >= 1) {
     				alpha = 1;
     				this.previous = null;
     			}
     			this.current.mix(skeleton, this.currentTime, this.currentLoop, alpha);
    -		} else 
    +		} else
     			this.current.apply(skeleton, this.currentTime, this.currentLoop);
     	},
     	clearAnimation: function () {
    @@ -1093,26 +1129,26 @@ spine.AnimationState.prototype = {
     		this.currentLoop = loop;
     		this.currentTime = 0;
     	},
    -	/** @see #setAnimation(Animation, Boolean) */
    +	/** @see #setAnimation(Animation, Boolean) */
     	setAnimationByName: function (animationName, loop) {
     		var animation = this.data.skeletonData.findAnimation(animationName);
     		if (!animation) throw "Animation not found: " + animationName;
     		this.setAnimation(animation, loop);
     	},
    -	/** Set the current animation. Any queued animations are cleared and the current animation time is set to 0.
    -	 * @param animation May be null. */
    +	/** Set the current animation. Any queued animations are cleared and the current animation time is set to 0.
    +	 * @param animation May be null. */
     	setAnimation: function (animation, loop) {
     		this.queue.length = 0;
     		this._setAnimation(animation, loop);
     	},
    -	/** @see #addAnimation(Animation, Boolean, Number) */
    +	/** @see #addAnimation(Animation, Boolean, Number) */
     	addAnimationByName: function (animationName, loop, delay) {
     		var animation = this.data.skeletonData.findAnimation(animationName);
     		if (!animation) throw "Animation not found: " + animationName;
     		this.addAnimation(animation, loop, delay);
     	},
    -	/** Adds an animation to be played delay seconds after the current or last queued animation.
    -	 * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */
    +	/** Adds an animation to be played delay seconds after the current or last queued animation.
    +	 * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */
     	addAnimation: function (animation, loop, delay) {
     		var entry = {};
     		entry.animation = animation;
    @@ -1129,7 +1165,7 @@ spine.AnimationState.prototype = {
     
     		this.queue.push(entry);
     	},
    -	/** Returns true if no animation is set or if the current time is greater than the animation duration, regardless of looping. */
    +	/** Returns true if no animation is set or if the current time is greater than the animation duration, regardless of looping. */
     	isComplete: function () {
     		return !this.current || this.currentTime >= this.current.duration;
     	}
    @@ -1143,7 +1179,7 @@ spine.SkeletonJson.prototype = {
     	readSkeletonData: function (root) {
     		var skeletonData = new spine.SkeletonData();
     
    -		// Bones.
    +		// Bones.
     		var bones = root["bones"];
     		for (var i = 0, n = bones.length; i < n; i++) {
     			var boneMap = bones[i];
    @@ -1162,7 +1198,7 @@ spine.SkeletonJson.prototype = {
     			skeletonData.bones.push(boneData);
     		}
     
    -		// Slots.
    +		// Slots.
     		var slots = root["slots"];
     		for (var i = 0, n = slots.length; i < n; i++) {
     			var slotMap = slots[i];
    @@ -1183,7 +1219,7 @@ spine.SkeletonJson.prototype = {
     			skeletonData.slots.push(slotData);
     		}
     
    -		// Skins.
    +		// Skins.
     		var skins = root["skins"];
     		for (var skinName in skins) {
     			if (!skins.hasOwnProperty(skinName)) continue;
    @@ -1203,7 +1239,7 @@ spine.SkeletonJson.prototype = {
     			if (skin.name == "default") skeletonData.defaultSkin = skin;
     		}
     
    -		// Animations.
    +		// Animations.
     		var animations = root["animations"];
     		for (var animationName in animations) {
     			if (!animations.hasOwnProperty(animationName)) continue;
    @@ -1216,16 +1252,9 @@ spine.SkeletonJson.prototype = {
     		name = map["name"] || name;
     
     		var type = spine.AttachmentType[map["type"] || "region"];
    -		
    -		// @ekelokorpi
    -		// var attachment = this.attachmentLoader.newAttachment(skin, type, name);
    -		var attachment = new spine.RegionAttachment();
    -		
    -		// @Doormat23
    -		// add the name of the attachment
    -		attachment.name = name;
    -		
    +
     		if (type == spine.AttachmentType.region) {
    +			var attachment = new spine.RegionAttachment();
     			attachment.x = (map["x"] || 0) * this.scale;
     			attachment.y = (map["y"] || 0) * this.scale;
     			attachment.scaleX = map["scaleX"] || 1;
    @@ -1234,10 +1263,19 @@ spine.SkeletonJson.prototype = {
     			attachment.width = (map["width"] || 32) * this.scale;
     			attachment.height = (map["height"] || 32) * this.scale;
     			attachment.updateOffset();
    +
    +			attachment.rendererObject = {};
    +			attachment.rendererObject.name = name;
    +			attachment.rendererObject.scale = {};
    +			attachment.rendererObject.scale.x = attachment.scaleX;
    +			attachment.rendererObject.scale.y = attachment.scaleY;
    +			attachment.rendererObject.rotation = -attachment.rotation * Math.PI / 180;
    +			return attachment;
     		}
     
    -		return attachment;
    +            throw "Unknown attachment type: " + type;
     	},
    +
     	readAnimation: function (name, map, skeletonData) {
     		var timelines = [];
     		var duration = 0;
    @@ -1288,7 +1326,7 @@ spine.SkeletonJson.prototype = {
     					}
     					timelines.push(timeline);
     					duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]);
    -					
    +
     				} else
     					throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")";
     			}
    @@ -1331,8 +1369,8 @@ spine.SkeletonJson.prototype = {
     						timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]);
     					}
     					timelines.push(timeline);
    -					// PIXI FIX
    -					duration = Math.max(duration, timeline.frames[Math.floor(timeline.getFrameCount()) - 1]);
    +                        duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);
    +
     				} else
     					throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")";
     			}
    @@ -1350,7 +1388,7 @@ spine.SkeletonJson.readCurve = function (timeline, frameIndex, valueMap) {
     };
     spine.SkeletonJson.toColor = function (hexString, colorIndex) {
     	if (hexString.length != 8) throw "Color hexidecimal length must be 8, recieved: " + hexString;
    -	return parseInt(hexString.substring(colorIndex * 2, 2), 16) / 255;
    +	return parseInt(hexString.substring(colorIndex * 2, 2), 16) / 255;
     };
     
     spine.Atlas = function (atlasText, textureLoader) {
    @@ -1407,24 +1445,24 @@ spine.Atlas = function (atlasText, textureLoader) {
     			var width = parseInt(tuple[0]);
     			var height = parseInt(tuple[1]);
     
    -			region.u = x / page.width;
    -			region.v = y / page.height;
    +			region.u = x / page.width;
    +			region.v = y / page.height;
     			if (region.rotate) {
    -				region.u2 = (x + height) / page.width;
    -				region.v2 = (y + width) / page.height;
    +				region.u2 = (x + height) / page.width;
    +				region.v2 = (y + width) / page.height;
     			} else {
    -				region.u2 = (x + width) / page.width;
    -				region.v2 = (y + height) / page.height;
    +				region.u2 = (x + width) / page.width;
    +				region.v2 = (y + height) / page.height;
     			}
     			region.x = x;
     			region.y = y;
     			region.width = Math.abs(width);
     			region.height = Math.abs(height);
     
    -			if (reader.readTuple(tuple) == 4) { // split is optional
    +			if (reader.readTuple(tuple) == 4) { // split is optional
     				region.splits = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])];
     
    -				if (reader.readTuple(tuple) == 4) { // pad is optional, but only present with splits
    +				if (reader.readTuple(tuple) == 4) { // pad is optional, but only present with splits
     					region.pads = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])];
     
     					reader.readTuple(tuple);
    @@ -1461,14 +1499,14 @@ spine.Atlas.prototype = {
     		for (var i = 0, n = regions.length; i < n; i++) {
     			var region = regions[i];
     			if (region.page != page) continue;
    -			region.u = region.x / page.width;
    -			region.v = region.y / page.height;
    +			region.u = region.x / page.width;
    +			region.v = region.y / page.height;
     			if (region.rotate) {
    -				region.u2 = (region.x + region.height) / page.width;
    -				region.v2 = (region.y + region.width) / page.height;
    +				region.u2 = (region.x + region.height) / page.width;
    +				region.v2 = (region.y + region.width) / page.height;
     			} else {
    -				region.u2 = (region.x + region.width) / page.width;
    -				region.v2 = (region.y + region.height) / page.height;
    +				region.u2 = (region.x + region.width) / page.width;
    +				region.v2 = (region.y + region.height) / page.height;
     			}
     		}
     	}
    @@ -1529,12 +1567,12 @@ spine.AtlasRegion.prototype = {
     };
     
     spine.AtlasReader = function (text) {
    -	this.lines = text.split(/\r\n|\r|\n/);
    +	this.lines = text.split(/\r\n|\r|\n/);
     };
     spine.AtlasReader.prototype = {
     	index: 0,
     	trim: function (value) {
    -		return value.replace(/^\s+|\s+$/g, "");
    +		return value.replace(/^\s+|\s+$/g, "");
     	},
     	readLine: function () {
     		if (this.index >= this.lines.length) return null;
    @@ -1546,7 +1584,7 @@ spine.AtlasReader.prototype = {
     		if (colon == -1) throw "Invalid line: " + line;
     		return this.trim(line.substring(colon + 1));
     	},
    -	/** Returns the number of tuple values read (2 or 4). */
    +	/** Returns the number of tuple values read (2 or 4). */
     	readTuple: function (tuple) {
     		var line = this.readLine();
     		var colon = line.indexOf(":");
    @@ -1602,13 +1640,13 @@ spine.Bone.yDown = true;
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_extras_Strip.js.html b/docs/files/src_pixi_extras_Strip.js.html index 1d6a08d..797626b 100644 --- a/docs/files/src_pixi_extras_Strip.js.html +++ b/docs/files/src_pixi_extras_Strip.js.html @@ -2,12 +2,12 @@ - src/pixi/extras/Strip.js - Pixi.JS - - - - - + src/pixi/extras/Strip.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,33 +166,33 @@
    -

    File: src/pixi/extras/Strip.js

    +

    File: src/pixi/extras/Strip.js

    -/**
    - * @author Mat Groves http://matgroves.com/
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/
    + */
     
     PIXI.Strip = function(texture, width, height)
     {
     	PIXI.DisplayObjectContainer.call( this );
     	this.texture = texture;
     	this.blendMode = PIXI.blendModes.NORMAL;
    -	
    +
     	try
     	{
     		this.uvs = new Float32Array([0, 1,
     				1, 1,
     				1, 0, 0,1]);
    -	
    +
     		this.verticies = new Float32Array([0, 0,
     						  0,0,
     						  0,0, 0,
     						  0, 0]);
    -						  
    +
     		this.colors = new Float32Array([1, 1, 1, 1]);
    -		
    +
     		this.indices = new Uint16Array([0, 1, 2, 3]);
     	}
     	catch(error)
    @@ -176,28 +200,28 @@ PIXI.Strip = function(texture, width, height)
     		this.uvs = [0, 1,
     				1, 1,
     				1, 0, 0,1];
    -	
    +
     		this.verticies = [0, 0,
     						  0,0,
     						  0,0, 0,
     						  0, 0];
    -						  
    +
     		this.colors = [1, 1, 1, 1];
    -		
    +
     		this.indices = [0, 1, 2, 3];
     	}
    -	
    -	
    -	/*
    +
    +
    +	/*
     	this.uvs = new Float32Array()
     	this.verticies = new Float32Array()
     	this.colors = new Float32Array()
     	this.indices = new Uint16Array()
    -*/
    +*/
     	this.width = width;
     	this.height = height;
    -	
    -	// load the texture!
    +
    +	// load the texture!
     	if(texture.baseTexture.hasLoaded)
     	{
     		this.width   = this.texture.frame.width;
    @@ -209,20 +233,20 @@ PIXI.Strip = function(texture, width, height)
     		this.onTextureUpdateBind = this.onTextureUpdate.bind(this);
     		this.texture.addEventListener( 'update', this.onTextureUpdateBind );
     	}
    -	
    +
     	this.renderable = true;
     }
     
    -// constructor
    -PIXI.Strip.constructor = PIXI.Strip;
    +// constructor
     PIXI.Strip.prototype = Object.create( PIXI.DisplayObjectContainer.prototype );
    +PIXI.Strip.prototype.constructor = PIXI.Strip;
     
     PIXI.Strip.prototype.setTexture = function(texture)
     {
    -	//TODO SET THE TEXTURES
    -	//TODO VISIBILITY
    -	
    -	// stop current texture 
    +	//TODO SET THE TEXTURES
    +	//TODO VISIBILITY
    +
    +	// stop current texture
     	this.texture = texture;
     	this.width   = texture.frame.width;
     	this.height  = texture.frame.height;
    @@ -233,7 +257,7 @@ PIXI.Strip.prototype.onTextureUpdate = function(event)
     {
     	this.updateFrame = true;
     }
    -// some helper functions..
    +// some helper functions..
     
     
         
    @@ -245,13 +269,13 @@ PIXI.Strip.prototype.onTextureUpdate = function(event)
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_extras_TilingSprite.js.html b/docs/files/src_pixi_extras_TilingSprite.js.html index e840d1d..29d6e4c 100644 --- a/docs/files/src_pixi_extras_TilingSprite.js.html +++ b/docs/files/src_pixi_extras_TilingSprite.js.html @@ -2,12 +2,12 @@ - src/pixi/extras/TilingSprite.js - Pixi.JS - - - - - + src/pixi/extras/TilingSprite.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,61 +166,100 @@
    -

    File: src/pixi/extras/TilingSprite.js

    +

    File: src/pixi/extras/TilingSprite.js

    -/**
    - * @author Mat Groves http://matgroves.com/
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/
    + */
     
    -/**
    +/**
      * A tiling sprite is a fast way of rendering a tiling image
    + *
      * @class TilingSprite
      * @extends DisplayObjectContainer
      * @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.DisplayObjectContainer.call( this );
    -	
    +
    +	/**
    +	 * The texture that the sprite is using
    +	 *
    +	 * @property texture
    +	 * @type Texture
    +	 */
     	this.texture = texture;
    +
    +	/**
    +	 * The width of the tiling sprite
    +	 *
    +	 * @property width
    +	 * @type Number
    +	 */
     	this.width = width;
    +
    +	/**
    +	 * The height of the tiling sprite
    +	 *
    +	 * @property height
    +	 * @type Number
    +	 */
     	this.height = height;
    -	this.renderable = true;
    -	/**
    +
    +	/**
     	 * The scaling of the image that is being tiled
    +	 *
     	 * @property tileScale
     	 * @type Point
    -	 */	
    +	 */
     	this.tileScale = 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);
    -	
    +
    +	this.renderable = true;
    +
     	this.blendMode = PIXI.blendModes.NORMAL
     }
     
    -// constructor
    -PIXI.TilingSprite.constructor = PIXI.TilingSprite;
    +// constructor
     PIXI.TilingSprite.prototype = Object.create( PIXI.DisplayObjectContainer.prototype );
    +PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite;
     
    +/**
    + * Sets the texture of the tiling sprite
    + *
    + * @method setTexture
    + * @param texture {Texture} The PIXI texture that is displayed by the sprite
    + */
     PIXI.TilingSprite.prototype.setTexture = function(texture)
     {
    -	//TODO SET THE TEXTURES
    -	//TODO VISIBILITY
    -	
    -	// stop current texture 
    +	//TODO SET THE TEXTURES
    +	//TODO VISIBILITY
    +
    +	// stop current texture
     	this.texture = texture;
     	this.updateFrame = true;
     }
     
    +/**
    + * When the texture is updated, this event will fire to update the frame
    + *
    + * @method onTextureUpdate
    + * @param event
    + * @private
    + */
     PIXI.TilingSprite.prototype.onTextureUpdate = function(event)
     {
     	this.updateFrame = true;
    @@ -212,13 +275,13 @@ PIXI.TilingSprite.prototype.onTextureUpdate = function(event)
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_filters_AbstractFilter.js.html b/docs/files/src_pixi_filters_AbstractFilter.js.html new file mode 100644 index 0000000..df61c41 --- /dev/null +++ b/docs/files/src_pixi_filters_AbstractFilter.js.html @@ -0,0 +1,229 @@ + + + + + src/pixi/filters/AbstractFilter.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/filters/AbstractFilter.js

    + +
    +
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +
    +/**
    + * This is the base class for  creating a pixi.js filter. Currently only webGL supports filters.
    + * If you want to make a custom filter this should be your base class.
    + * @class AbstractFilter
    + * @constructor
    + * @param fragmentSrc
    + * @param unifroms  
    + */
    +PIXI.AbstractFilter = function(fragmentSrc, unifroms)
    +{
    +	/**
    +	* An array of passes - some filters contain a few steps this array simply stores the steps in a liniear fashion.
    +	* For example the blur filter has two passes blurX and blurY.
    +	* @property passes
    +	* @type Array an array of filter objects
    +	* @private
    +	*/
    +	this.passes = [this];
    +
    +
    +	this.dirty = true;
    +	this.padding = 0;
    +
    +	/**
    +	@property uniforms
    +	@private
    +	*/
    +	this.uniforms = unifroms || {};
    +	
    +	this.fragmentSrc = fragmentSrc || [];
    +}
    +
    +
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_filters_BlurFilter.js.html b/docs/files/src_pixi_filters_BlurFilter.js.html new file mode 100644 index 0000000..d0ce50e --- /dev/null +++ b/docs/files/src_pixi_filters_BlurFilter.js.html @@ -0,0 +1,262 @@ + + + + + src/pixi/filters/BlurFilter.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/filters/BlurFilter.js

    + +
    +
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +
    +/**
    + * 
    + * The BlurFilter applies a Gaussian blur to an object. 
    + * The strength of the blur can be set for x- and y-axis separately (always relative to the stage).
    + *
    + * @class BlurFilter
    + * @contructor
    + */
    +PIXI.BlurFilter = function()
    +{
    +    
    +	this.blurXFilter = new PIXI.BlurXFilter();
    +	this.blurYFilter = new PIXI.BlurYFilter();
    +
    +	this.passes =[this.blurXFilter, this.blurYFilter];
    +	
    +}
    +
    +/**
    + * Sets the strength of both the blurX and blurY properties simultaneously
    + *
    + * @property blur
    + * @type Number the strength of the blur
    + * @default 2
    + */
    +Object.defineProperty(PIXI.BlurFilter.prototype, 'blur', {
    +    get: function() {
    +        return this.blurX.blur;
    +    },
    +    set: function(value) {
    +  		this.blurXFilter.blur = this.blurYFilter.blur = value;
    +    }
    +});
    +
    +/**
    + * Sets the strength of the blurX property simultaneously
    + *
    + * @property blurX
    + * @type Number the strength of the blurX
    + * @default 2
    + */
    +Object.defineProperty(PIXI.BlurFilter.prototype, 'blurX', {
    +    get: function() {
    +        return this.blurXFilter.blur;
    +    },
    +    set: function(value) {
    +    	this.blurXFilter.blur = value;
    +    }
    +});
    +
    +/**
    + * Sets the strength of the blurX property simultaneously
    + *
    + * @property blurY
    + * @type Number the strength of the blurY
    + * @default 2
    + */
    +Object.defineProperty(PIXI.BlurFilter.prototype, 'blurY', {
    +    get: function() {
    +        return this.blurYFilter.blur;
    +    },
    +    set: function(value) {
    +    	this.blurYFilter.blur = value;
    +    }
    +});
    +
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_filters_BlurXFilter.js.html b/docs/files/src_pixi_filters_BlurXFilter.js.html new file mode 100644 index 0000000..52ea9a5 --- /dev/null +++ b/docs/files/src_pixi_filters_BlurXFilter.js.html @@ -0,0 +1,248 @@ + + + + + src/pixi/filters/BlurXFilter.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/filters/BlurXFilter.js

    + +
    +
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +
    +
    +PIXI.BlurXFilter = function()
    +{
    +	PIXI.AbstractFilter.call( this );
    +	
    +	this.passes = [this];
    +	
    +	// set the uniforms
    +	this.uniforms = {
    +		blur: {type: 'f', value: 1/512},
    +	};
    +	
    +	this.fragmentSrc = [
    +	  "precision mediump float;",
    +	  "varying vec2 vTextureCoord;",
    +	  "varying float vColor;",
    +	  "uniform float blur;",
    +	  "uniform sampler2D uSampler;",
    +	    "void main(void) {",
    +	  	"vec4 sum = vec4(0.0);",
    +
    +	  	"sum += texture2D(uSampler, vec2(vTextureCoord.x - 4.0*blur, vTextureCoord.y)) * 0.05;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x - 3.0*blur, vTextureCoord.y)) * 0.09;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x - 2.0*blur, vTextureCoord.y)) * 0.12;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x - blur, vTextureCoord.y)) * 0.15;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y)) * 0.16;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x + blur, vTextureCoord.y)) * 0.15;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x + 2.0*blur, vTextureCoord.y)) * 0.12;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x + 3.0*blur, vTextureCoord.y)) * 0.09;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x + 4.0*blur, vTextureCoord.y)) * 0.05;",
    +	 
    +		"gl_FragColor = sum;",
    +
    +	  "}"
    +	];
    +}
    +
    +PIXI.BlurXFilter.prototype = Object.create( PIXI.AbstractFilter.prototype );
    +PIXI.BlurXFilter.prototype.constructor = PIXI.BlurXFilter;
    +
    +
    +Object.defineProperty(PIXI.BlurXFilter.prototype, 'blur', {
    +    get: function() {
    +        return this.uniforms.blur.value / (1/7000);
    +    },
    +    set: function(value) {
    +    
    +    	this.dirty = true;
    +    	this.uniforms.blur.value = (1/7000) * value;
    +    }
    +});
    +
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_filters_BlurYFilter.js.html b/docs/files/src_pixi_filters_BlurYFilter.js.html new file mode 100644 index 0000000..3d09e8c --- /dev/null +++ b/docs/files/src_pixi_filters_BlurYFilter.js.html @@ -0,0 +1,246 @@ + + + + + src/pixi/filters/BlurYFilter.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/filters/BlurYFilter.js

    + +
    +
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +
    +
    +PIXI.BlurYFilter = function()
    +{
    +	PIXI.AbstractFilter.call( this );
    +	
    +	this.passes = [this];
    +	
    +	// set the uniforms
    +	this.uniforms = {
    +		blur: {type: 'f', value: 1/512},
    +	};
    +	
    +	this.fragmentSrc = [
    +	  "precision mediump float;",
    +	  "varying vec2 vTextureCoord;",
    +	  "varying float vColor;",
    +	  "uniform float blur;",
    +	  "uniform sampler2D uSampler;",
    +	    "void main(void) {",
    +	  	"vec4 sum = vec4(0.0);",
    +
    +	  	"sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y - 4.0*blur)) * 0.05;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y - 3.0*blur)) * 0.09;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y - 2.0*blur)) * 0.12;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y - blur)) * 0.15;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y)) * 0.16;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y + blur)) * 0.15;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y + 2.0*blur)) * 0.12;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y + 3.0*blur)) * 0.09;",
    +	    "sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y + 4.0*blur)) * 0.05;",
    +	 
    +		"gl_FragColor = sum;",
    +
    +	  "}"
    +	];
    +}
    +
    +PIXI.BlurYFilter.prototype = Object.create( PIXI.AbstractFilter.prototype );
    +PIXI.BlurYFilter.prototype.constructor = PIXI.BlurYFilter;
    +
    +Object.defineProperty(PIXI.BlurYFilter.prototype, 'blur', {
    +    get: function() {
    +        return this.uniforms.blur.value / (1/7000);
    +    },
    +    set: function(value) {
    +    	//this.padding = value;
    +    	this.uniforms.blur.value = (1/7000) * value;
    +    }
    +});
    +
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_filters_ColorMatrixFilter.js.html b/docs/files/src_pixi_filters_ColorMatrixFilter.js.html new file mode 100644 index 0000000..8156285 --- /dev/null +++ b/docs/files/src_pixi_filters_ColorMatrixFilter.js.html @@ -0,0 +1,250 @@ + + + + + src/pixi/filters/ColorMatrixFilter.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/filters/ColorMatrixFilter.js

    + +
    +
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +/**
    + * 
    + * The ColorMatrixFilter class lets you apply a 4x4 matrix transformation on the RGBA 
    + * color and alpha values of every pixel on your displayObject to produce a result 
    + * with a new set of RGBA color and alpha values. Its pretty powerful!
    + * @class ColorMatrixFilter
    + * @contructor
    + */
    +PIXI.ColorMatrixFilter = function()
    +{
    +	PIXI.AbstractFilter.call( this );
    +	
    +	this.passes = [this];
    +	
    +	// set the uniforms
    +	this.uniforms = {
    +		matrix: {type: 'mat4', value: [1,0,0,0,
    +									   0,1,0,0,
    +									   0,0,1,0,
    +									   0,0,0,1]},
    +	};
    +	
    +	this.fragmentSrc = [
    +	  "precision mediump float;",
    +	  "varying vec2 vTextureCoord;",
    +	  "varying float vColor;",
    +	  "uniform float invert;",
    +	  "uniform mat4 matrix;",
    +	  "uniform sampler2D uSampler;",
    +	  "void main(void) {",
    +	    "gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;",
    +	    "gl_FragColor = gl_FragColor * vColor;",
    +	  "}"
    +	];
    +	
    +}
    +
    +PIXI.ColorMatrixFilter.prototype = Object.create( PIXI.AbstractFilter.prototype );
    +PIXI.ColorMatrixFilter.prototype.constructor = PIXI.ColorMatrixFilter;
    +
    +/**
    + * Sets the matrix of the color matrix filter
    + *
    + * @property matrix
    + * @type Array and array of 26 numbers
    + * @default [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]
    + */
    +Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', {
    +    get: function() {
    +        return this.uniforms.matrix.value;
    +    },
    +    set: function(value) {
    +    	this.uniforms.matrix.value = value;
    +    }
    +});
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_filters_DisplacementFilter.js.html b/docs/files/src_pixi_filters_DisplacementFilter.js.html new file mode 100644 index 0000000..91d269c --- /dev/null +++ b/docs/files/src_pixi_filters_DisplacementFilter.js.html @@ -0,0 +1,326 @@ + + + + + src/pixi/filters/DisplacementFilter.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/filters/DisplacementFilter.js

    + +
    +
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +
    +/**
    + * 
    + * The DisplacementFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object. 
    + * You can use this filter to apply all manor of crazy warping effects
    + * Currently the r property of the texture is used offset the x and the g propery of the texture is used to offset the y.
    + * @class DisplacementFilter
    + * @contructor
    + * @param texture {Texture} The texture used for the displacemtent map * must be power of 2 texture at the moment
    + */
    +PIXI.DisplacementFilter = function(texture)
    +{
    +	PIXI.AbstractFilter.call( this );
    +	
    +	this.passes = [this];
    +	texture.baseTexture._powerOf2 = true;
    +
    +	// set the uniforms
    +	//console.log()
    +	this.uniforms = {
    +		displacementMap: {type: 'sampler2D', value:texture},
    +		scale:			 {type: 'f2', value:{x:30, y:30}},
    +		offset:			 {type: 'f2', value:{x:0, y:0}},
    +		mapDimensions:   {type: 'f2', value:{x:1, y:5112}},
    +		dimensions:   {type: 'f4', value:[0,0,0,0]}
    +	};
    +	
    +
    +	if(texture.baseTexture.hasLoaded)
    +	{
    +		this.uniforms.mapDimensions.value.x = texture.width;
    +		this.uniforms.mapDimensions.value.y = texture.height;
    +	}
    +	else
    +	{
    +		this.boundLoadedFunction = this.onTextureLoaded.bind(this);
    +
    +		texture.baseTexture.on("loaded", this.boundLoadedFunction);
    +	}
    +
    +	this.fragmentSrc = [
    +	  "precision mediump float;",
    +	  "varying vec2 vTextureCoord;",
    +	  "varying float vColor;",
    +	  "uniform sampler2D displacementMap;",
    +	  "uniform sampler2D uSampler;",
    +	  "uniform vec2 scale;",
    +	  "uniform vec2 offset;",
    +	  "uniform vec4 dimensions;",
    +	  "uniform vec2 mapDimensions;",// = vec2(256.0, 256.0);",
    +	 // "const vec2 textureDimensions = vec2(750.0, 750.0);",
    +	  
    +	  "void main(void) {",
    +	  	"vec2 mapCords = vTextureCoord.xy;",
    +//	  	"mapCords -= ;",
    +	 	"mapCords += (dimensions.zw + offset)/ dimensions.xy ;",
    +	 	"mapCords.y *= -1.0;",
    +	 	"mapCords.y += 1.0;",
    +	  	"vec2 matSample = texture2D(displacementMap, mapCords).xy;",
    +		"matSample -= 0.5;",	  
    +	 	"matSample *= scale;",
    +	 	"matSample /= mapDimensions;",
    +	    "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x + matSample.x, vTextureCoord.y + matSample.y));",
    +		"gl_FragColor.rgb = mix( gl_FragColor.rgb, gl_FragColor.rgb, 1.0);",
    +		"vec2 cord = vTextureCoord;",
    +		
    +		//"gl_FragColor =  texture2D(displacementMap, cord);",
    +	    "gl_FragColor = gl_FragColor * vColor;",
    +	    
    +	  "}"
    +	];
    +	
    +}
    +
    +PIXI.DisplacementFilter.prototype = Object.create( PIXI.AbstractFilter.prototype );
    +PIXI.DisplacementFilter.prototype.constructor = PIXI.DisplacementFilter;
    +
    +PIXI.DisplacementFilter.prototype.onTextureLoaded = function()
    +{
    +	
    +	this.uniforms.mapDimensions.value.x = this.uniforms.displacementMap.value.width;
    +	this.uniforms.mapDimensions.value.y = this.uniforms.displacementMap.value.height;
    +
    +	this.uniforms.displacementMap.value.baseTexture.off("loaded", this.boundLoadedFunction)
    +
    +}
    +
    +/**
    + * The texture used for the displacemtent map * must be power of 2 texture at the moment
    + *
    + * @property map
    + * @type Texture
    + */
    +Object.defineProperty(PIXI.DisplacementFilter.prototype, 'map', {
    +    get: function() {
    +        return this.uniforms.displacementMap.value;
    +    },
    +    set: function(value) {
    +    	this.uniforms.displacementMap.value = value;
    +    }
    +});
    +
    +/**
    + * The multiplier used to scale the displacement result from the map calculation.
    + *
    + * @property scale
    + * @type Point
    + */
    +Object.defineProperty(PIXI.DisplacementFilter.prototype, 'scale', {
    +    get: function() {
    +        return this.uniforms.scale.value;
    +    },
    +    set: function(value) {
    +    	this.uniforms.scale.value = value;
    +    }
    +});
    +
    +/**
    + * The offset used to move the displacement map.
    + *
    + * @property offset
    + * @type Point
    + */
    +Object.defineProperty(PIXI.DisplacementFilter.prototype, 'offset', {
    +    get: function() {
    +        return this.uniforms.offset.value;
    +    },
    +    set: function(value) {
    +    	this.uniforms.offset.value = value;
    +    }
    +});
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_filters_FilterBlock.js.html b/docs/files/src_pixi_filters_FilterBlock.js.html index 080a44f..3491921 100644 --- a/docs/files/src_pixi_filters_FilterBlock.js.html +++ b/docs/files/src_pixi_filters_FilterBlock.js.html @@ -2,12 +2,12 @@ - src/pixi/filters/FilterBlock.js - Pixi.JS - - - - - + src/pixi/filters/FilterBlock.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,24 +166,21 @@
    -

    File: src/pixi/filters/FilterBlock.js

    +

    File: src/pixi/filters/FilterBlock.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
     
     
    -PIXI.FilterBlock = function(mask)
    +PIXI.FilterBlock = function()
     {
    -	this.graphics = mask
     	this.visible = true;
     	this.renderable = true;
     }
    -
    -
         
    @@ -169,13 +190,13 @@ PIXI.FilterBlock = function(mask)
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_filters_GreyFilter.js.html b/docs/files/src_pixi_filters_GreyFilter.js.html new file mode 100644 index 0000000..45eae1e --- /dev/null +++ b/docs/files/src_pixi_filters_GreyFilter.js.html @@ -0,0 +1,243 @@ + + + + + src/pixi/filters/GreyFilter.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/filters/GreyFilter.js

    + +
    +
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +
    +/**
    + * 
    + * This turns your displayObjects to black and white.
    + * @class GreyFilter
    + * @contructor
    + */
    +PIXI.GreyFilter = function()
    +{
    +	PIXI.AbstractFilter.call( this );
    +	
    +	this.passes = [this];
    +	
    +	// set the uniforms
    +	this.uniforms = {
    +		grey: {type: 'f', value: 1},
    +	};
    +	
    +	this.fragmentSrc = [
    +	  "precision mediump float;",
    +	  "varying vec2 vTextureCoord;",
    +	  "varying float vColor;",
    +	  "uniform sampler2D uSampler;",
    +	  "uniform float grey;",
    +	  "void main(void) {",
    +	    "gl_FragColor = texture2D(uSampler, vTextureCoord);",
    +		"gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), grey);",
    +	    "gl_FragColor = gl_FragColor * vColor;",
    +	  "}"
    +	];
    +}
    +
    +PIXI.GreyFilter.prototype = Object.create( PIXI.AbstractFilter.prototype );
    +PIXI.GreyFilter.prototype.constructor = PIXI.GreyFilter;
    +
    +/**
    +The strength of the grey. 1 will make the object black and white, 0 will make the object its normal color
    +@property grey
    +*/
    +Object.defineProperty(PIXI.GreyFilter.prototype, 'grey', {
    +    get: function() {
    +        return this.uniforms.grey.value;
    +    },
    +    set: function(value) {
    +    	this.uniforms.grey.value = value;
    +    }
    +});
    +
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_filters_InvertFilter.js.html b/docs/files/src_pixi_filters_InvertFilter.js.html new file mode 100644 index 0000000..a9b6382 --- /dev/null +++ b/docs/files/src_pixi_filters_InvertFilter.js.html @@ -0,0 +1,243 @@ + + + + + src/pixi/filters/InvertFilter.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/filters/InvertFilter.js

    + +
    +
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +/**
    + * 
    + * This inverts your displayObjects colors.
    + * @class InvertFilter
    + * @contructor
    + */
    +PIXI.InvertFilter = function()
    +{
    +	PIXI.AbstractFilter.call( this );
    +	
    +	this.passes = [this];
    +	
    +	// set the uniforms
    +	this.uniforms = {
    +		invert: {type: 'f', value: 0},
    +	};
    +	
    +	this.fragmentSrc = [
    +	  "precision mediump float;",
    +	  "varying vec2 vTextureCoord;",
    +	  "varying float vColor;",
    +	  "uniform float invert;",
    +	  "uniform sampler2D uSampler;",
    +	  "void main(void) {",
    +	    "gl_FragColor = texture2D(uSampler, vTextureCoord);",
    +		"gl_FragColor.rgb = mix( (vec3(1)-gl_FragColor.rgb) * gl_FragColor.a, gl_FragColor.rgb, invert);",
    +		//"gl_FragColor.rgb = gl_FragColor.rgb  * gl_FragColor.a;",
    +	    "gl_FragColor = gl_FragColor * vColor;",
    +	  "}"
    +	];
    +	
    +}
    +
    +PIXI.InvertFilter.prototype = Object.create( PIXI.AbstractFilter.prototype );
    +PIXI.InvertFilter.prototype.constructor = PIXI.InvertFilter;
    +
    +/**
    +The strength of the invert. 1 will fully invert the colors, 0 will make the object its normal color
    +@property invert
    +*/
    +Object.defineProperty(PIXI.InvertFilter.prototype, 'invert', {
    +    get: function() {
    +        return this.uniforms.invert.value;
    +    },
    +    set: function(value) {
    +    	this.uniforms.invert.value = value;
    +    }
    +});
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_filters_MaskFilter.js.html b/docs/files/src_pixi_filters_MaskFilter.js.html deleted file mode 100644 index 0df8008..0000000 --- a/docs/files/src_pixi_filters_MaskFilter.js.html +++ /dev/null @@ -1,180 +0,0 @@ - - - - - src/pixi/filters/MaskFilter.js - Pixi.JS - - - - - - - - -
    -
    -
    - -

    - -
    -
    - API Docs for: 1.3.0 -
    -
    -
    - - -
    -
    - Show: - - - - - - - -
    - - -
    -
    -
    -

    File: src/pixi/filters/MaskFilter.js

    - -
    -
    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    -
    -
    -
    -PIXI.MaskFilter = function(graphics)
    -{
    -	// the graphics data that will be used for filtering
    -	this.graphics;
    -}
    -
    -
    -    
    -
    - -
    -
    -
    -
    -
    -
    - - - - - - - - - - diff --git a/docs/files/src_pixi_filters_PixelateFilter.js.html b/docs/files/src_pixi_filters_PixelateFilter.js.html new file mode 100644 index 0000000..84a51c4 --- /dev/null +++ b/docs/files/src_pixi_filters_PixelateFilter.js.html @@ -0,0 +1,255 @@ + + + + + src/pixi/filters/PixelateFilter.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/filters/PixelateFilter.js

    + +
    +
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +/**
    + * 
    + * This filter applies a pixlate effect making display objects appear "blocky"
    + * @class PixelateFilter
    + * @contructor
    + */
    +PIXI.PixelateFilter = function()
    +{
    +	PIXI.AbstractFilter.call( this );
    +
    +	this.passes = [this];
    +	
    +	// set the uniforms
    +	this.uniforms = {
    +		invert: {type: 'f', value: 0},
    +		dimensions: {type: 'f4', value:new Float32Array([10000, 100, 10, 10])},
    +		pixelSize: {type: 'f2', value:{x:10, y:10}},
    +	};
    +
    +	this.fragmentSrc = [
    +	  "precision mediump float;",
    +	  "varying vec2 vTextureCoord;",
    +	  "varying float vColor;",
    +	  "uniform vec2 testDim;",
    +	  "uniform vec4 dimensions;",
    +	  "uniform vec2 pixelSize;",
    +	  "uniform sampler2D uSampler;",
    +	  "void main(void) {",
    +	 	"vec2 coord = vTextureCoord;",
    +
    +	 //	"vec2 dim = testDim;",
    +	 	"vec2 size = dimensions.xy/pixelSize;",
    +
    +	 	"vec2 color = floor( ( vTextureCoord * size ) ) / size + pixelSize/dimensions.xy * 0.5;",
    +	// 	"color += (mod(dimensions.xy, size)/dimensions.zw;",
    +	    "gl_FragColor = texture2D(uSampler, color);",
    +	  "}"
    +	];
    +	
    +
    +}
    +
    +PIXI.PixelateFilter.prototype = Object.create( PIXI.AbstractFilter.prototype );
    +PIXI.PixelateFilter.prototype.constructor = PIXI.PixelateFilter;
    +
    +/**
    + * 
    + * This a point that describes the size of the blocs. x is the width of the block and y is the the height
    + * @property size
    + * @type Point
    + */
    +Object.defineProperty(PIXI.PixelateFilter.prototype, 'size', {
    +    get: function() {
    +        return this.uniforms.pixelSize.value;
    +    },
    +    set: function(value) {
    +    	this.dirty = true;
    +    	this.uniforms.pixelSize.value = value;
    +    }
    +});
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_filters_SepiaFilter.js.html b/docs/files/src_pixi_filters_SepiaFilter.js.html new file mode 100644 index 0000000..3571a8c --- /dev/null +++ b/docs/files/src_pixi_filters_SepiaFilter.js.html @@ -0,0 +1,247 @@ + + + + + src/pixi/filters/SepiaFilter.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/filters/SepiaFilter.js

    + +
    +
    +/**
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +
    +/**
    + * 
    + * This applies a sepia effect to your displayObjects.
    + * @class SepiaFilter
    + * @contructor
    + */
    +PIXI.SepiaFilter = function()
    +{
    +	PIXI.AbstractFilter.call( this );
    +	
    +	this.passes = [this];
    +	
    +	// set the uniforms
    +	this.uniforms = {
    +		sepia: {type: 'f', value: 1},
    +	};
    +	
    +	this.fragmentSrc = [
    +	  "precision mediump float;",
    +	  "varying vec2 vTextureCoord;",
    +	  "varying float vColor;",
    +	  "uniform float sepia;",
    +	  "uniform sampler2D uSampler;",
    +	 	   
    +	  "const mat3 sepiaMatrix = mat3(0.3588, 0.7044, 0.1368, 0.2990, 0.5870, 0.1140, 0.2392, 0.4696, 0.0912);",
    +	  "void main(void) {",
    +	    "gl_FragColor = texture2D(uSampler, vTextureCoord);",
    +		"gl_FragColor.rgb = mix( gl_FragColor.rgb, gl_FragColor.rgb * sepiaMatrix, sepia);",
    +	    "gl_FragColor = gl_FragColor * vColor;",
    +	  "}"
    +	];
    +	
    +}
    +
    +PIXI.SepiaFilter.prototype = Object.create( PIXI.AbstractFilter.prototype );
    +PIXI.SepiaFilter.prototype.constructor = PIXI.SepiaFilter;
    +
    +/**
    +The strength of the sepia. 1 will apply the full sepia effect, 0 will make the object its normal color
    +@property sepia
    +*/
    +Object.defineProperty(PIXI.SepiaFilter.prototype, 'sepia', {
    +    get: function() {
    +        return this.uniforms.sepia.value;
    +    },
    +    set: function(value) {
    +    	this.uniforms.sepia.value = value;
    +    }
    +});
    +
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_filters_SmartBlurFilter.js.html b/docs/files/src_pixi_filters_SmartBlurFilter.js.html new file mode 100644 index 0000000..80af498 --- /dev/null +++ b/docs/files/src_pixi_filters_SmartBlurFilter.js.html @@ -0,0 +1,256 @@ + + + + + src/pixi/filters/SmartBlurFilter.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/filters/SmartBlurFilter.js

    + +
    +
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +
    +
    +PIXI.SmartBlurFilter = function()
    +{
    +	PIXI.AbstractFilter.call( this );
    +	
    +	this.passes = [this];
    +	
    +	// set the uniforms
    +	this.uniforms = {
    +		blur: {type: 'f', value: 1/512},
    +	};
    +	
    +	this.fragmentSrc = [
    +	  "precision mediump float;",
    + 	  "varying vec2 vTextureCoord;",
    +  	  "uniform sampler2D uSampler;",
    +    //  "uniform vec2 delta;",
    +      "const vec2 delta = vec2(1.0/10.0, 0.0);",
    +     // "uniform float darkness;",
    +	  
    +	  "float random(vec3 scale, float seed) {",
    +	        "return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);",
    +	   "}",
    +	   
    +	   
    +	  "void main(void) {",
    +	 
    +	  "vec4 color = vec4(0.0);",
    +	  "float total = 0.0;",
    +	  
    +	  "float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);",
    +	            
    +	  "for (float t = -30.0; t <= 30.0; t++) {",
    +	           "float percent = (t + offset - 0.5) / 30.0;",
    +	                "float weight = 1.0 - abs(percent);",
    +	                "vec4 sample = texture2D(uSampler, vTextureCoord + delta * percent);",
    +	                "sample.rgb *= sample.a;",
    +	                "color += sample * weight;",
    +	                "total += weight;",
    +	            "}",
    +	            
    +	            "gl_FragColor = color / total;",
    +	            "gl_FragColor.rgb /= gl_FragColor.a + 0.00001;",
    +	          //  "gl_FragColor.rgb *= darkness;",
    +	  "}"
    +	];
    +}
    +
    +PIXI.SmartBlurFilter.prototype = Object.create( PIXI.AbstractFilter.prototype );
    +PIXI.SmartBlurFilter.prototype.constructor = PIXI.SmartBlurFilter;
    +
    +Object.defineProperty(PIXI.SmartBlurFilter.prototype, 'blur', {
    +    get: function() {
    +        return this.uniforms.blur.value;
    +    },
    +    set: function(value) {
    +    	this.uniforms.blur.value = value;
    +    }
    +});
    +
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_loaders_AssetLoader.js.html b/docs/files/src_pixi_loaders_AssetLoader.js.html index a752143..c7cbe8c 100644 --- a/docs/files/src_pixi_loaders_AssetLoader.js.html +++ b/docs/files/src_pixi_loaders_AssetLoader.js.html @@ -2,12 +2,12 @@ - src/pixi/loaders/AssetLoader.js - Pixi.JS - - - - - + src/pixi/loaders/AssetLoader.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,36 +166,56 @@
    -

    File: src/pixi/loaders/AssetLoader.js

    +

    File: src/pixi/loaders/AssetLoader.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -/**
    - * A Class that loads a bunch of images / sprite sheet / bitmap font files. Once the assets have been loaded they are added to the PIXI Texture cache and can be accessed easily through PIXI.Texture.fromImage() and PIXI.Sprite.fromImage()
    +/**
    + * A Class that loads a bunch of images / sprite sheet / bitmap font files. Once the
    + * assets have been loaded they are added to the PIXI Texture cache and can be accessed
    + * easily through PIXI.Texture.fromImage() and PIXI.Sprite.fromImage()
      * When all items have been loaded this class will dispatch a "onLoaded" event
      * As each individual item is loaded this class will dispatch a "onProgress" event
    + *
      * @class AssetLoader
      * @constructor
    - * @extends EventTarget
    - * @param {Array} assetURLs an array of image/sprite sheet urls that you would like loaded supported. Supported image formats include "jpeg", "jpg", "png", "gif". Supported sprite sheet data formats only include "JSON" at this time. Supported bitmap font data formats include "xml" and "fnt".
    - */
    -PIXI.AssetLoader = function(assetURLs)
    + * @uses EventTarget
    + * @param {Array<String>} assetURLs an array of image/sprite sheet urls that you would like loaded
    + *      supported. Supported image formats include "jpeg", "jpg", "png", "gif". Supported
    + *      sprite sheet data formats only include "JSON" at this time. Supported bitmap font
    + *      data formats include "xml" and "fnt".
    + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin
    + */
    +PIXI.AssetLoader = function(assetURLs, crossorigin)
     {
     	PIXI.EventTarget.call(this);
    -	
    -	/**
    +
    +	/**
     	 * The array of asset URLs that are going to be loaded
    +     *
     	 * @property assetURLs
    -	 * @type Array
    -	 */
    +	 * @type Array<String>
    +	 */
     	this.assetURLs = assetURLs;
     
    -	this.crossorigin = false;
    +    /**
    +     * Whether the requests should be treated as cross origin
    +     *
    +     * @property crossorigin
    +     * @type Boolean
    +     */
    +	this.crossorigin = crossorigin;
     
    +    /**
    +     * Maps file extension to loader types
    +     *
    +     * @property loadersByType
    +     * @type Object
    +     */
         this.loadersByType = {
             "jpg":  PIXI.ImageLoader,
             "jpeg": PIXI.ImageLoader,
    @@ -182,26 +226,28 @@ PIXI.AssetLoader = function(assetURLs)
             "xml":  PIXI.BitmapFontLoader,
             "fnt":  PIXI.BitmapFontLoader
         };
    -    
    -    
    +
    +
     };
     
    -/**
    -Fired when an item has loaded
    -@event onProgress
    -**/
    +/**
    + * Fired when an item has loaded
    + * @event onProgress
    + */
     
    -/**
    -Fired when all the assets have loaded
    -@event onComplete 
    -**/
    +/**
    + * Fired when all the assets have loaded
    + * @event onComplete
    + */
     
    -// constructor
    -PIXI.AssetLoader.constructor = PIXI.AssetLoader;
    +// constructor
    +PIXI.AssetLoader.prototype.constructor = PIXI.AssetLoader;
     
    -/**
    - * This will begin loading the assets sequentially
    - */
    +/**
    + * Starts loading the assets sequentially
    + *
    + * @method load
    + */
     PIXI.AssetLoader.prototype.load = function()
     {
         var scope = this;
    @@ -227,16 +273,18 @@ PIXI.AssetLoader.prototype.load = function()
     	}
     };
     
    -/**
    +/**
      * Invoked after each file is loaded
    + *
    + * @method onAssetLoaded
      * @private
    - */
    + */
     PIXI.AssetLoader.prototype.onAssetLoaded = function()
     {
         this.loadCount--;
     	this.dispatchEvent({type: "onProgress", content: this});
     	if(this.onProgress) this.onProgress();
    -	
    +
     	if(this.loadCount == 0)
     	{
     		this.dispatchEvent({type: "onComplete", content: this});
    @@ -254,13 +302,13 @@ PIXI.AssetLoader.prototype.onAssetLoaded = function()
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_loaders_BitmapFontLoader.js.html b/docs/files/src_pixi_loaders_BitmapFontLoader.js.html index 0bc6eef..5e9e825 100644 --- a/docs/files/src_pixi_loaders_BitmapFontLoader.js.html +++ b/docs/files/src_pixi_loaders_BitmapFontLoader.js.html @@ -2,12 +2,12 @@ - src/pixi/loaders/BitmapFontLoader.js - Pixi.JS - - - - - + src/pixi/loaders/BitmapFontLoader.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,46 +166,77 @@
    -

    File: src/pixi/loaders/BitmapFontLoader.js

    +

    File: src/pixi/loaders/BitmapFontLoader.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -/**
    +/**
      * The xml loader is used to load in XML bitmap font data ("xml" or "fnt")
    - * To generate the data you can use http://www.angelcode.com/products/bmfont/
    + * To generate the data you can use http://www.angelcode.com/products/bmfont/
      * This loader will also load the image file as the data.
      * When loaded this class will dispatch a "loaded" event
    + *
      * @class BitmapFontLoader
    - * @extends EventTarget
    + * @uses EventTarget
      * @constructor
    - * @param {String} url the url of the sprite sheet JSON file
    - * @param {Boolean} crossorigin
    - */
    -
    + * @param url {String} The url of the sprite sheet JSON file
    + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin
    + */
     PIXI.BitmapFontLoader = function(url, crossorigin)
     {
    -    /*
    +    /*
          * i use texture packer to load the assets..
    -     * http://www.codeandweb.com/texturepacker
    +     * http://www.codeandweb.com/texturepacker
          * make sure to set the format as "JSON"
    -     */
    +     */
         PIXI.EventTarget.call(this);
    +
    +    /**
    +     * The url of the bitmap font data
    +     *
    +     * @property url
    +     * @type String
    +     */
         this.url = url;
    -    this.baseUrl = url.replace(/[^\/]*$/, "");
    -    this.texture = null;
    +
    +    /**
    +     * Whether the requests should be treated as cross origin
    +     *
    +     * @property crossorigin
    +     * @type Boolean
    +     */
         this.crossorigin = crossorigin;
    +
    +    /**
    +     * [read-only] The base url of the bitmap font data
    +     *
    +     * @property baseUrl
    +     * @type String
    +     * @readOnly
    +     */
    +    this.baseUrl = url.replace(/[^\/]*$/, "");
    +
    +    /**
    +     * [read-only] The texture of the bitmap font
    +     *
    +     * @property baseUrl
    +     * @type String
    +     */
    +    this.texture = null;
     };
     
    -// constructor
    -PIXI.BitmapFontLoader.constructor = PIXI.BitmapFontLoader;
    +// constructor
    +PIXI.BitmapFontLoader.prototype.constructor = PIXI.BitmapFontLoader;
     
    -/**
    - * This will begin loading the JSON file
    - */
    +/**
    + * Loads the XML font data
    + *
    + * @method load
    + */
     PIXI.BitmapFontLoader.prototype.load = function()
     {
         this.ajaxRequest = new XMLHttpRequest();
    @@ -192,14 +247,16 @@ PIXI.BitmapFontLoader.prototype.load = function()
         };
     
         this.ajaxRequest.open("GET", this.url, true);
    -    if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/xml");
    +    if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/xml");
         this.ajaxRequest.send(null)
     };
     
    -/**
    - * Invoked when XML file is loaded
    +/**
    + * Invoked when XML file is loaded, parses the data
    + *
    + * @method onXMLLoaded
      * @private
    - */
    + */
     PIXI.BitmapFontLoader.prototype.onXMLLoaded = function()
     {
         if (this.ajaxRequest.readyState == 4)
    @@ -218,32 +275,31 @@ PIXI.BitmapFontLoader.prototype.onXMLLoaded = function()
                 data.lineHeight = parseInt(common.attributes.getNamedItem("lineHeight").nodeValue, 10);
                 data.chars = {};
     
    -            //parse letters
    +            //parse letters
                 var letters = this.ajaxRequest.responseXML.getElementsByTagName("char");
     
                 for (var i = 0; i < letters.length; i++)
                 {
                     var charCode = parseInt(letters[i].attributes.getNamedItem("id").nodeValue, 10);
     
    -                var textureRect = {
    -                    x: parseInt(letters[i].attributes.getNamedItem("x").nodeValue, 10),
    -                    y: parseInt(letters[i].attributes.getNamedItem("y").nodeValue, 10),
    -                    width: parseInt(letters[i].attributes.getNamedItem("width").nodeValue, 10),
    -                    height: parseInt(letters[i].attributes.getNamedItem("height").nodeValue, 10)
    -                };
    -                PIXI.TextureCache[charCode] = new PIXI.Texture(this.texture, textureRect);
    +                var textureRect = new PIXI.Rectangle(
    +                    parseInt(letters[i].attributes.getNamedItem("x").nodeValue, 10),
    +                    parseInt(letters[i].attributes.getNamedItem("y").nodeValue, 10),
    +                    parseInt(letters[i].attributes.getNamedItem("width").nodeValue, 10),
    +                    parseInt(letters[i].attributes.getNamedItem("height").nodeValue, 10)
    +                );
     
                     data.chars[charCode] = {
                         xOffset: parseInt(letters[i].attributes.getNamedItem("xoffset").nodeValue, 10),
                         yOffset: parseInt(letters[i].attributes.getNamedItem("yoffset").nodeValue, 10),
                         xAdvance: parseInt(letters[i].attributes.getNamedItem("xadvance").nodeValue, 10),
                         kerning: {},
    -                    texture:new PIXI.Texture(this.texture, textureRect)
    +                    texture: PIXI.TextureCache[charCode] = new PIXI.Texture(this.texture, textureRect)
     
                     };
                 }
     
    -            //parse kernings
    +            //parse kernings
                 var kernings = this.ajaxRequest.responseXML.getElementsByTagName("kerning");
                 for (i = 0; i < kernings.length; i++)
                 {
    @@ -266,10 +322,12 @@ PIXI.BitmapFontLoader.prototype.onXMLLoaded = function()
         }
     };
     
    -/**
    - * Invoked when all files are loaded (xml/fnt and texture)
    +/**
    + * Invoked when all files are loaded (xml/fnt and texture)
    + *
    + * @method onLoaded
      * @private
    - */
    + */
     PIXI.BitmapFontLoader.prototype.onLoaded = function()
     {
         this.dispatchEvent({type: "loaded", content: this});
    @@ -284,13 +342,13 @@ PIXI.BitmapFontLoader.prototype.onLoaded = function()
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_loaders_ImageLoader.js.html b/docs/files/src_pixi_loaders_ImageLoader.js.html index 5a0c7d4..d7744fc 100644 --- a/docs/files/src_pixi_loaders_ImageLoader.js.html +++ b/docs/files/src_pixi_loaders_ImageLoader.js.html @@ -2,12 +2,12 @@ - src/pixi/loaders/ImageLoader.js - Pixi.JS - - - - - + src/pixi/loaders/ImageLoader.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,36 +166,53 @@
    -

    File: src/pixi/loaders/ImageLoader.js

    +

    File: src/pixi/loaders/ImageLoader.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -/**
    +/**
      * The image loader class is responsible for loading images file formats ("jpeg", "jpg", "png" and "gif")
      * Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId()
      * When loaded this class will dispatch a 'loaded' event
    + *
      * @class ImageLoader
    - * @extends EventTarget
    + * @uses EventTarget
      * @constructor
    - * @param {String} url The url of the image
    - * @param {Boolean} crossorigin
    - */
    + * @param url {String} The url of the image
    + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin
    + */
     PIXI.ImageLoader = function(url, crossorigin)
     {
         PIXI.EventTarget.call(this);
    +
    +    /**
    +     * The texture being loaded
    +     *
    +     * @property texture
    +     * @type Texture
    +     */
         this.texture = PIXI.Texture.fromImage(url, crossorigin);
    +
    +    /**
    +     * if the image is loaded with loadFramedSpriteSheet
    +     * frames will contain the sprite sheet frames
    +     *
    +     */
    +    this.frames = [];
     };
     
    -// constructor
    -PIXI.ImageLoader.constructor = PIXI.ImageLoader;
    +// constructor
    +PIXI.ImageLoader.prototype.constructor = PIXI.ImageLoader;
     
    -/**
    +/**
      * Loads image or takes it from cache
    - */
    + *
    + * @method load
    + */
     PIXI.ImageLoader.prototype.load = function()
     {
         if(!this.texture.baseTexture.hasLoaded)
    @@ -188,15 +229,61 @@ PIXI.ImageLoader.prototype.load = function()
         }
     };
     
    -/**
    +/**
      * Invoked when image file is loaded or it is already cached and ready to use
    + *
    + * @method onLoaded
      * @private
    - */
    + */
     PIXI.ImageLoader.prototype.onLoaded = function()
     {
         this.dispatchEvent({type: "loaded", content: this});
     };
     
    +/**
    + * Loads image and split it to uniform sized frames
    + *
    + *
    + * @method loadFramedSpriteSheet
    + * @param frameWidth {Number} with of each frame
    + * @param frameHeight {Number} height of each frame
    + * @param textureName {String} if given, the frames will be cached in <textureName>-<ord> format 
    + */
    +PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHeight, textureName)
    +{
    +    this.frames = [];
    +    var cols = Math.floor(this.texture.width / frameWidth);
    +    var rows = Math.floor(this.texture.height / frameHeight);
    +
    +    var i=0;
    +    for (var y=0; y<rows; y++)
    +    {
    +        for (var x=0; x<cols; x++,i++)
    +        {
    +            var texture = new PIXI.Texture(this.texture, {
    +                x: x*frameWidth,
    +                y: y*frameHeight,
    +                width: frameWidth,
    +                height: frameHeight
    +            });
    +
    +            this.frames.push(texture);
    +            if (textureName) PIXI.TextureCache[textureName+'-'+i] = texture;
    +        }
    +    }
    +
    +    if(!this.texture.baseTexture.hasLoaded)
    +    {
    +        var scope = this;
    +        this.texture.baseTexture.addEventListener("loaded", function() {
    +            scope.onLoaded();
    +        });
    +    }
    +    else
    +    {
    +        this.onLoaded();
    +    }
    +};
         
    @@ -206,13 +293,13 @@ PIXI.ImageLoader.prototype.onLoaded = function()
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_loaders_JsonLoader.js.html b/docs/files/src_pixi_loaders_JsonLoader.js.html index 8e91182..292eab2 100644 --- a/docs/files/src_pixi_loaders_JsonLoader.js.html +++ b/docs/files/src_pixi_loaders_JsonLoader.js.html @@ -2,12 +2,12 @@ - src/pixi/loaders/JsonLoader.js - Pixi.JS - - - - - + src/pixi/loaders/JsonLoader.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,40 +166,72 @@
    -

    File: src/pixi/loaders/JsonLoader.js

    +

    File: src/pixi/loaders/JsonLoader.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -/**
    +/**
      * The json file loader is used to load in JSON data and parsing it
      * When loaded this class will dispatch a "loaded" event
      * If load failed this class will dispatch a "error" event
    + *
      * @class JsonLoader
    - * @extends EventTarget
    + * @uses EventTarget
      * @constructor
    - * @param {String} url the url of the JSON file
    - * @param {Boolean} crossorigin
    - */
    -
    + * @param url {String} The url of the JSON file
    + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin
    + */
     PIXI.JsonLoader = function (url, crossorigin) {
     	PIXI.EventTarget.call(this);
    +
    +	/**
    +	 * The url of the bitmap font data
    +	 *
    +	 * @property url
    +	 * @type String
    +	 */
     	this.url = url;
    -	this.baseUrl = url.replace(/[^\/]*$/, "");
    +
    +	/**
    +	 * Whether the requests should be treated as cross origin
    +	 *
    +	 * @property crossorigin
    +	 * @type Boolean
    +	 */
     	this.crossorigin = crossorigin;
    +
    +	/**
    +	 * [read-only] The base url of the bitmap font data
    +	 *
    +	 * @property baseUrl
    +	 * @type String
    +	 * @readOnly
    +	 */
    +	this.baseUrl = url.replace(/[^\/]*$/, "");
    +
    +	/**
    +	 * [read-only] Whether the data has loaded yet
    +	 *
    +	 * @property loaded
    +	 * @type Boolean
    +	 * @readOnly
    +	 */
     	this.loaded = false;
    -	
    +
     };
     
    -// constructor
    -PIXI.JsonLoader.constructor = PIXI.JsonLoader;
    +// constructor
    +PIXI.JsonLoader.prototype.constructor = PIXI.JsonLoader;
     
    -/**
    - * This will begin loading the JSON file
    - */
    +/**
    + * Loads the JSON data
    + *
    + * @method load
    + */
     PIXI.JsonLoader.prototype.load = function () {
     	this.ajaxRequest = new AjaxRequest();
     	var scope = this;
    @@ -184,32 +240,34 @@ PIXI.JsonLoader.prototype.load = function () {
     	};
     
     	this.ajaxRequest.open("GET", this.url, true);
    -	if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/json");
    +	if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/json");
     	this.ajaxRequest.send(null);
     };
     
    -/**
    +/**
      * Invoke when JSON file is loaded
    + *
    + * @method onJSONLoaded
      * @private
    - */
    + */
     PIXI.JsonLoader.prototype.onJSONLoaded = function () {
     	if (this.ajaxRequest.readyState == 4) {
     		if (this.ajaxRequest.status == 200 || window.location.href.indexOf("http") == -1) {
     			this.json = JSON.parse(this.ajaxRequest.responseText);
    -			
    +
     			if(this.json.frames)
     			{
    -				// sprite sheet
    +				// sprite sheet
     				var scope = this;
     				var textureUrl = this.baseUrl + this.json.meta.image;
     				var image = new PIXI.ImageLoader(textureUrl, this.crossorigin);
     				var frameData = this.json.frames;
    -			
    +
     				this.texture = image.texture.baseTexture;
     				image.addEventListener("loaded", function (event) {
     					scope.onLoaded();
     				});
    -			
    +
     				for (var i in frameData) {
     					var rect = frameData[i].frame;
     					if (rect) {
    @@ -220,20 +278,20 @@ PIXI.JsonLoader.prototype.onJSONLoaded = function () {
     							height: rect.h
     						});
     						if (frameData[i].trimmed) {
    -							//var realSize = frameData[i].spriteSourceSize;
    +							//var realSize = frameData[i].spriteSourceSize;
     							PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize;
    -							PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w)
    -							// calculate the offset!
    +							PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w)
    +							// calculate the offset!
     						}
     					}
     				}
    -			
    +
     				image.load();
    -				
    +
     			}
     			else if(this.json.bones)
     			{
    -				// spine animation
    +				// spine animation
     				var spineJsonParser = new spine.SkeletonJson();
     				var skeletonData = spineJsonParser.readSkeletonData(this.json);
     				PIXI.AnimCache[this.url] = skeletonData;
    @@ -243,20 +301,20 @@ PIXI.JsonLoader.prototype.onJSONLoaded = function () {
     			{
     				this.onLoaded();
     			}
    -			
    -			
    -			
    -			
    -		} else {
    +		}
    +		else
    +		{
     			this.onError();
     		}
     	}
     };
     
    -/**
    +/**
      * Invoke when json file loaded
    + *
    + * @method onLoaded
      * @private
    - */
    + */
     PIXI.JsonLoader.prototype.onLoaded = function () {
     	this.loaded = true;
     	this.dispatchEvent({
    @@ -265,10 +323,12 @@ PIXI.JsonLoader.prototype.onLoaded = function () {
     	});
     };
     
    -/**
    +/**
      * Invoke when error occured
    + *
    + * @method onError
      * @private
    - */
    + */
     PIXI.JsonLoader.prototype.onError = function () {
     	this.dispatchEvent({
     		type: "error",
    @@ -284,13 +344,13 @@ PIXI.JsonLoader.prototype.onError = function () {
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_loaders_SpineLoader.js.html b/docs/files/src_pixi_loaders_SpineLoader.js.html index a5d91bf..0590ea8 100644 --- a/docs/files/src_pixi_loaders_SpineLoader.js.html +++ b/docs/files/src_pixi_loaders_SpineLoader.js.html @@ -2,12 +2,12 @@ - src/pixi/loaders/SpineLoader.js - Pixi.JS - - - - - + src/pixi/loaders/SpineLoader.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,54 +166,72 @@
    -

    File: src/pixi/loaders/SpineLoader.js

    +

    File: src/pixi/loaders/SpineLoader.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi
    - * 
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + * based on pixi impact spine implementation made by Eemeli Kelokorpi (@ekelokorpi) https://github.com/ekelokorpi
    + *
      * Awesome JS run time provided by EsotericSoftware
    - * https://github.com/EsotericSoftware/spine-runtimes
    - * 
    - */
    + * https://github.com/EsotericSoftware/spine-runtimes
    + *
    + */
     
    -/**
    +/**
      * The Spine loader is used to load in JSON spine data
    - * To generate the data you need to use http://esotericsoftware.com/ and export the "JSON" format
    + * To generate the data you need to use http://esotericsoftware.com/ and export the "JSON" format
      * Due to a clash of names  You will need to change the extension of the spine file from *.json to *.anim for it to load
    - * See example 12 (http://www.goodboydigital.com/pixijs/examples/12/) to see a working example and check out the source
    - * You will need to generate a sprite sheet to accompany the spine data 
    + * See example 12 (http://www.goodboydigital.com/pixijs/examples/12/) to see a working example and check out the source
    + * You will need to generate a sprite sheet to accompany the spine data
      * When loaded this class will dispatch a "loaded" event
    + *
      * @class Spine
    + * @uses EventTarget
      * @constructor
    - * @extends EventTarget
    - * @param {String} url the url of the sprite sheet JSON file
    - * @param {Boolean} crossorigin
    - */
    -PIXI.SpineLoader = function(url, crossorigin) 
    + * @param url {String} The url of the JSON file
    + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin
    + */
    +PIXI.SpineLoader = function(url, crossorigin)
     {
     	PIXI.EventTarget.call(this);
    +
    +	/**
    +	 * The url of the bitmap font data
    +	 *
    +	 * @property url
    +	 * @type String
    +	 */
     	this.url = url;
    +
    +	/**
    +	 * Whether the requests should be treated as cross origin
    +	 *
    +	 * @property crossorigin
    +	 * @type Boolean
    +	 */
     	this.crossorigin = crossorigin;
    +
    +	/**
    +	 * [read-only] Whether the data has loaded yet
    +	 *
    +	 * @property loaded
    +	 * @type Boolean
    +	 * @readOnly
    +	 */
     	this.loaded = false;
     }
     
    -PIXI.SpineLoader.constructor = PIXI.SpineLoader;
    -
    -PIXI.SpineLoader.prototype.load = function()
    -{
    -	new PIXI.JsonLoader(this.url, this.crossorigin);
    -		jsonLoader.addEventListener("loaded", function (event) {
    -			scope.json = event.content.json;
    -			scope.onJSONLoaded();
    -		});
    -		jsonLoader.load();
    -};
    +PIXI.SpineLoader.prototype.constructor = PIXI.SpineLoader;
     
    +/**
    + * Loads the JSON data
    + *
    + * @method load
    + */
     PIXI.SpineLoader.prototype.load = function () {
    -	
    +
     	var scope = this;
     	var jsonLoader = new PIXI.JsonLoader(this.url, this.crossorigin);
     	jsonLoader.addEventListener("loaded", function (event) {
    @@ -199,25 +241,28 @@ PIXI.SpineLoader.prototype.load = function () {
     	jsonLoader.load();
     };
     
    -/**
    +/**
      * Invoke when JSON file is loaded
    + *
    + * @method onJSONLoaded
      * @private
    - */
    + */
     PIXI.SpineLoader.prototype.onJSONLoaded = function (event) {
    -	
     	var spineJsonParser = new spine.SkeletonJson();
    -	
     	var skeletonData = spineJsonParser.readSkeletonData(this.json);
    -	
    +
     	PIXI.AnimCache[this.url] = skeletonData;
     
     	this.onLoaded();
     };
     
    -
    -			
    -PIXI.SpineLoader.prototype.onLoaded = function()
    -{
    +/**
    + * Invoke when JSON file is loaded
    + *
    + * @method onLoaded
    + * @private
    + */
    +PIXI.SpineLoader.prototype.onLoaded = function () {
     	this.loaded = true;
         this.dispatchEvent({type: "loaded", content: this});
     };
    @@ -232,13 +277,13 @@ PIXI.SpineLoader.prototype.onLoaded = function()
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_loaders_SpriteSheetLoader.js.html b/docs/files/src_pixi_loaders_SpriteSheetLoader.js.html index 7f4f05f..7ec53e4 100644 --- a/docs/files/src_pixi_loaders_SpriteSheetLoader.js.html +++ b/docs/files/src_pixi_loaders_SpriteSheetLoader.js.html @@ -2,12 +2,12 @@ - src/pixi/loaders/SpriteSheetLoader.js - Pixi.JS - - - - - + src/pixi/loaders/SpriteSheetLoader.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,49 +166,88 @@
    -

    File: src/pixi/loaders/SpriteSheetLoader.js

    +

    File: src/pixi/loaders/SpriteSheetLoader.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -/**
    +/**
      * The sprite sheet loader is used to load in JSON sprite sheet data
    - * To generate the data you can use http://www.codeandweb.com/texturepacker and publish the "JSON" format
    + * To generate the data you can use http://www.codeandweb.com/texturepacker and publish the "JSON" format
      * There is a free version so thats nice, although the paid version is great value for money.
      * It is highly recommended to use Sprite sheets (also know as texture atlas") as it means sprite"s can be batched and drawn together for highly increased rendering speed.
      * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFromeId()
      * This loader will also load the image file that the Spritesheet points to as well as the data.
      * When loaded this class will dispatch a "loaded" event
    + *
      * @class SpriteSheetLoader
    - * @extends EventTarget
    + * @uses EventTarget
      * @constructor
    - * @param {String} url the url of the sprite sheet JSON file
    - * @param {Boolean} crossorigin
    - */
    + * @param url {String} The url of the sprite sheet JSON file
    + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin
    + */
     
     PIXI.SpriteSheetLoader = function (url, crossorigin) {
    -	/*
    +	/*
     	 * i use texture packer to load the assets..
    -	 * http://www.codeandweb.com/texturepacker
    +	 * http://www.codeandweb.com/texturepacker
     	 * make sure to set the format as "JSON"
    -	 */
    +	 */
     	PIXI.EventTarget.call(this);
    +
    +	/**
    +	 * The url of the bitmap font data
    +	 *
    +	 * @property url
    +	 * @type String
    +	 */
     	this.url = url;
    -	this.baseUrl = url.replace(/[^\/]*$/, "");
    -	this.texture = null;
    -	this.frames = {};
    +
    +	/**
    +	 * Whether the requests should be treated as cross origin
    +	 *
    +	 * @property crossorigin
    +	 * @type Boolean
    +	 */
     	this.crossorigin = crossorigin;
    +
    +	/**
    +	 * [read-only] The base url of the bitmap font data
    +	 *
    +	 * @property baseUrl
    +	 * @type String
    +	 * @readOnly
    +	 */
    +	this.baseUrl = url.replace(/[^\/]*$/, "");
    +
    +    /**
    +     * The texture being loaded
    +     *
    +     * @property texture
    +     * @type Texture
    +     */
    +    this.texture = null;
    +
    +    /**
    +     * The frames of the sprite sheet
    +     *
    +     * @property frames
    +     * @type Object
    +     */
    +	this.frames = {};
     };
     
    -// constructor
    -PIXI.SpriteSheetLoader.constructor = PIXI.SpriteSheetLoader;
    +// constructor
    +PIXI.SpriteSheetLoader.prototype.constructor = PIXI.SpriteSheetLoader;
     
    -/**
    +/**
      * This will begin loading the JSON file
    - */
    + *
    + * @method load
    + */
     PIXI.SpriteSheetLoader.prototype.load = function () {
     	var scope = this;
     	var jsonLoader = new PIXI.JsonLoader(this.url, this.crossorigin);
    @@ -195,10 +258,12 @@ PIXI.SpriteSheetLoader.prototype.load = function () {
     	jsonLoader.load();
     };
     
    -/**
    +/**
      * Invoke when JSON file is loaded
    + *
    + * @method onJSONLoaded
      * @private
    - */
    + */
     PIXI.SpriteSheetLoader.prototype.onJSONLoaded = function () {
     	var scope = this;
     	var textureUrl = this.baseUrl + this.json.meta.image;
    @@ -220,20 +285,22 @@ PIXI.SpriteSheetLoader.prototype.onJSONLoaded = function () {
     				height: rect.h
     			});
     			if (frameData[i].trimmed) {
    -				//var realSize = frameData[i].spriteSourceSize;
    +				//var realSize = frameData[i].spriteSourceSize;
     				PIXI.TextureCache[i].realSize = frameData[i].spriteSourceSize;
    -				PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w)
    -				// calculate the offset!
    +				PIXI.TextureCache[i].trim.x = 0; // (realSize.x / rect.w)
    +				// calculate the offset!
     			}
     		}
     	}
     
     	image.load();
     };
    -/**
    +/**
      * Invoke when all files are loaded (json and texture)
    + *
    + * @method onLoaded
      * @private
    - */
    + */
     PIXI.SpriteSheetLoader.prototype.onLoaded = function () {
     	this.dispatchEvent({
     		type: "loaded",
    @@ -250,13 +317,13 @@ PIXI.SpriteSheetLoader.prototype.onLoaded = function () {
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_primitives_Graphics.js.html b/docs/files/src_pixi_primitives_Graphics.js.html index 56e8996..9041f75 100644 --- a/docs/files/src_pixi_primitives_Graphics.js.html +++ b/docs/files/src_pixi_primitives_Graphics.js.html @@ -2,12 +2,12 @@ - src/pixi/primitives/Graphics.js - Pixi.JS - - - - - + src/pixi/primitives/Graphics.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,111 +166,152 @@
    -

    File: src/pixi/primitives/Graphics.js

    +

    File: src/pixi/primitives/Graphics.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
     
    -/**
    - * The Graphics class contains a set of methods that you can use to create primitive shapes and lines. 
    +/**
    + * The Graphics class contains a set of methods that you can use to create primitive shapes and lines.
      * It is important to know that with the webGL renderer only simple polys can be filled at this stage
    - * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png
    - * @class Graphics 
    + * Complex polys will not be filled. Heres an example of a complex poly: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png
    + *
    + * @class Graphics
      * @extends DisplayObjectContainer
      * @constructor
    - */
    + */
     PIXI.Graphics = function()
     {
     	PIXI.DisplayObjectContainer.call( this );
    -	
    +
     	this.renderable = true;
    -	
    +
    +    /**
    +     * The alpha of the fill of this graphics object
    +     *
    +     * @property fillAlpha
    +     * @type Number
    +     */
     	this.fillAlpha = 1;
    -	
    +
    +    /**
    +     * The width of any lines drawn
    +     *
    +     * @property lineWidth
    +     * @type Number
    +     */
     	this.lineWidth = 0;
    +
    +    /**
    +     * The color of any lines drawn
    +     *
    +     * @property lineColor
    +     * @type String
    +     */
     	this.lineColor = "black";
    -	
    +
    +    /**
    +     * Graphics data
    +     *
    +     * @property graphicsData
    +     * @type Array
    +     * @private
    +     */
     	this.graphicsData = [];
    -	
    +
    +    /**
    +     * Current path
    +     *
    +     * @property currentPath
    +     * @type Object
    +     * @private
    +     */
     	this.currentPath = {points:[]};
     }
     
    -// constructor
    -PIXI.Graphics.constructor = PIXI.Graphics;
    +// constructor
     PIXI.Graphics.prototype = Object.create( PIXI.DisplayObjectContainer.prototype );
    +PIXI.Graphics.prototype.constructor = PIXI.Graphics;
     
    -/**
    +/**
      * Specifies a line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method.
    + *
      * @method lineStyle
    - * @param lineWidth {Number}
    - * @param color {Number}
    - * @param alpha {Number}
    - */
    + * @param lineWidth {Number} width of the line to draw, will update the object's stored style
    + * @param color {Number} color of the line to draw, will update the object's stored style
    + * @param alpha {Number} alpha of the line to draw, will update the object's stored style
    + */
     PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha)
     {
     	if(this.currentPath.points.length == 0)this.graphicsData.pop();
    -	
    +
     	this.lineWidth = lineWidth || 0;
     	this.lineColor = color || 0;
     	this.lineAlpha = (alpha == undefined) ? 1 : alpha;
    -	
    -	this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, 
    +
    +	this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha,
     						fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY};
    -	
    +
     	this.graphicsData.push(this.currentPath);
     }
     
    -/**
    +/**
      * Moves the current drawing position to (x, y).
    + *
      * @method moveTo
    - * @param x {Number}
    - * @param y {Number}
    - */
    + * @param x {Number} the X coord to move to
    + * @param y {Number} the Y coord to move to
    + */
     PIXI.Graphics.prototype.moveTo = function(x, y)
     {
     	if(this.currentPath.points.length == 0)this.graphicsData.pop();
    -	
    -	this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, 
    +
    +	this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha,
     						fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY};
    -	
    +
     	this.currentPath.points.push(x, y);
    -	
    +
     	this.graphicsData.push(this.currentPath);
     }
     
    -/**
    - * Draws a line using the current line style from the current drawing position to (x, y); the current drawing position is then set to (x, y).
    +/**
    + * Draws a line using the current line style from the current drawing position to (x, y);
    + * the current drawing position is then set to (x, y).
    + *
      * @method lineTo
    - * @param x {Number}
    - * @param y {Number}
    - */
    + * @param x {Number} the X coord to draw to
    + * @param y {Number} the Y coord to draw to
    + */
     PIXI.Graphics.prototype.lineTo = function(x, y)
     {
     	this.currentPath.points.push(x, y);
     	this.dirty = true;
     }
     
    -/**
    - * Specifies a simple one-color fill that subsequent calls to other Graphics methods (such as lineTo() or drawCircle()) use when drawing.
    +/**
    + * Specifies a simple one-color fill that subsequent calls to other Graphics methods
    + * (such as lineTo() or drawCircle()) use when drawing.
    + *
      * @method beginFill
      * @param color {uint} the color of the fill
      * @param alpha {Number} the alpha
    - */
    + */
     PIXI.Graphics.prototype.beginFill = function(color, alpha)
     {
     	this.filling = true;
     	this.fillColor = color || 0;
    -	this.fillAlpha = alpha || 1;
    +	this.fillAlpha = (alpha == undefined) ? 1 : alpha;
     }
     
    -/**
    +/**
      * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method.
    + *
      * @method endFill
    - */
    + */
     PIXI.Graphics.prototype.endFill = function()
     {
     	this.filling = false;
    @@ -254,79 +319,158 @@ PIXI.Graphics.prototype.endFill = function()
     	this.fillAlpha = 1;
     }
     
    -/**
    +/**
      * @method drawRect
    - * @param x {Number}
    - * @param y {Number}
    - * @param width {Number}
    - * @param height {Number}
    - */
    + *
    + * @param x {Number} The X coord of the top-left of the rectangle
    + * @param y {Number} The Y coord of the top-left of the rectangle
    + * @param width {Number} The width of the rectangle
    + * @param height {Number} The height of the rectangle
    + */
     PIXI.Graphics.prototype.drawRect = function( x, y, width, height )
     {
     	if(this.currentPath.points.length == 0)this.graphicsData.pop();
    -	
    -	this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, 
    -						fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, 
    +
    +	this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha,
    +						fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling,
     						points:[x, y, width, height], type:PIXI.Graphics.RECT};
    -						
    +
     	this.graphicsData.push(this.currentPath);
     	this.dirty = true;
     }
     
    -/**
    +/**
      * Draws a circle.
    + *
      * @method drawCircle
    - * @param x {Number}
    - * @param y {Number}
    - * @param radius {Number}
    - */
    + * @param x {Number} The X coord of the center of the circle
    + * @param y {Number} The Y coord of the center of the circle
    + * @param radius {Number} The radius of the circle
    + */
     PIXI.Graphics.prototype.drawCircle = function( x, y, radius)
     {
     	if(this.currentPath.points.length == 0)this.graphicsData.pop();
    -	
    -	this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, 
    -						fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, 
    +
    +	this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha,
    +						fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling,
     						points:[x, y, radius, radius], type:PIXI.Graphics.CIRC};
    -						
    +
     	this.graphicsData.push(this.currentPath);
     	this.dirty = true;
     }
     
    -/**
    +/**
      * Draws an elipse.
    + *
      * @method drawElipse
      * @param x {Number}
      * @param y {Number}
      * @param width {Number}
      * @param height {Number}
    - */
    + */
     PIXI.Graphics.prototype.drawElipse = function( x, y, width, height)
     {
     	if(this.currentPath.points.length == 0)this.graphicsData.pop();
    -	
    -	this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha, 
    -						fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, 
    +
    +	this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha,
    +						fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling,
     						points:[x, y, width, height], type:PIXI.Graphics.ELIP};
    -						
    +
     	this.graphicsData.push(this.currentPath);
     	this.dirty = true;
     }
     
    -/**
    +/**
      * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings.
    + *
      * @method clear
    - */
    + */
     PIXI.Graphics.prototype.clear = function()
     {
     	this.lineWidth = 0;
     	this.filling = false;
    -	
    +
     	this.dirty = true;
     	this.clearDirty = true;
     	this.graphicsData = [];
    +
    +	this.bounds = null//new PIXI.Rectangle();
     }
     
    -// SOME TYPES:
    +
    +PIXI.Graphics.prototype.updateFilterBounds = function()
    +{
    +	if(!this.bounds)
    +	{
    +		var minX = Infinity;
    +		var maxX = -Infinity;
    +
    +		var minY = Infinity;
    +		var maxY = -Infinity;
    +
    +		var points, x, y;
    +
    +		for (var i = 0; i < this.graphicsData.length; i++) {
    +			
    +
    +			var data = this.graphicsData[i];
    +			var type = data.type;
    +			var lineWidth = data.lineWidth;
    +
    +			points = data.points;
    +
    +			if(type === PIXI.Graphics.RECT)
    +			{
    +				x = points.x - lineWidth/2;
    +				y = points.y - lineWidth/2;
    +				var width = points.width + lineWidth;
    +				var height = points.height + lineWidth;
    +
    +				minX = x < minX ? x : minX;
    +				maxX = x + width > maxX ? x + width : maxX;
    +
    +				minY = y < minY ? x : minY;
    +				maxY = y + height > maxY ? y + height : maxY;
    +			}
    +			else if(type === PIXI.Graphics.CIRC || type === PIXI.Graphics.ELIP)
    +			{
    +				x = points.x;
    +				y = points.y;
    +				var radius = points.radius + lineWidth/2;
    +				
    +				minX = x - radius < minX ? x - radius : minX;
    +				maxX = x + radius > maxX ? x + radius : maxX;
    +
    +				minY = y - radius < minY ? y - radius : minY;
    +				maxY = y + radius > maxY ? y + radius : maxY;
    +			}
    +			else
    +			{
    +				// POLY
    +				for (var j = 0; j < points.length; j+=2) 
    +				{
    +					
    +					x = points[j];
    +					y = points[j+1];
    +
    +					minX = x-lineWidth < minX ? x-lineWidth : minX;
    +					maxX = x+lineWidth > maxX ? x+lineWidth : maxX;
    +
    +					minY = y-lineWidth < minY ? y-lineWidth : minY;
    +					maxY = y+lineWidth > maxY ? y+lineWidth : maxY;
    +				};
    +			}
    +
    +		};
    +
    +		this.bounds = new PIXI.Rectangle(minX, minY, maxX - minX, maxY - minY);
    +
    +	}
    +
    +//	console.log(this.bounds);
    +}
    +
    +// SOME TYPES:
     PIXI.Graphics.POLY = 0;
     PIXI.Graphics.RECT = 1;
     PIXI.Graphics.CIRC = 2;
    @@ -341,13 +485,13 @@ PIXI.Graphics.ELIP = 3;
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_renderers_canvas_CanvasGraphics.js.html b/docs/files/src_pixi_renderers_canvas_CanvasGraphics.js.html index d09a4be..a0ec34a 100644 --- a/docs/files/src_pixi_renderers_canvas_CanvasGraphics.js.html +++ b/docs/files/src_pixi_renderers_canvas_CanvasGraphics.js.html @@ -2,12 +2,12 @@ - src/pixi/renderers/canvas/CanvasGraphics.js - Pixi.JS - - - - - + src/pixi/renderers/canvas/CanvasGraphics.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,64 +166,65 @@
    -

    File: src/pixi/renderers/canvas/CanvasGraphics.js

    +

    File: src/pixi/renderers/canvas/CanvasGraphics.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
     
    -/**
    +/**
      * A set of functions used by the canvas renderer to draw the primitive graphics data
    - * @class CanvasGraphics 
    - */
    + *
    + * @class CanvasGraphics
    + */
     PIXI.CanvasGraphics = function()
     {
    -	
    +
     }
     
     
    -/*
    - * @private
    +/*
    + * Renders the graphics object
    + *
      * @static
    + * @private
      * @method renderGraphics
      * @param graphics {Graphics}
      * @param context {Context2D}
    - */
    + */
     PIXI.CanvasGraphics.renderGraphics = function(graphics, context)
     {
     	var worldAlpha = graphics.worldAlpha;
    -	
    -	for (var i=0; i < graphics.graphicsData.length; i++) 
    +
    +	for (var i=0; i < graphics.graphicsData.length; i++)
     	{
     		var data = graphics.graphicsData[i];
     		var points = data.points;
    -		
    +
     		context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6);
     
     		context.lineWidth = data.lineWidth;
    -		
    +
     		if(data.type == PIXI.Graphics.POLY)
     		{
    -			//if(data.lineWidth <= 0)continue;
    -			
     			context.beginPath();
    -			
    +
     			context.moveTo(points[0], points[1]);
    -			
    -			for (var j=1; j < points.length/2; j++)
    +
    +			for (var j=1; j < points.length/2; j++)
     			{
     				context.lineTo(points[j * 2], points[j * 2 + 1]);
    -			} 
    -	      	
    -	      	// if the first and last point are the same close the path - much neater :)
    +			}
    +
    +	      	// if the first and last point are the same close the path - much neater :)
     	      	if(points[0] == points[points.length-2] && points[1] == points[points.length-1])
     	      	{
     	      		context.closePath();
     	      	}
    -			
    +
     			if(data.fill)
     			{
     				context.globalAlpha = data.fillAlpha * worldAlpha;
    @@ -214,29 +239,28 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context)
     		}
     		else if(data.type == PIXI.Graphics.RECT)
     		{
    -				
    -			// TODO - need to be Undefined!
    -			if(data.fillColor)
    +
    +			if(data.fillColor || data.fillColor === 0)
     			{
     				context.globalAlpha = data.fillAlpha * worldAlpha;
     				context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6);
    -				context.rect(points[0], points[1], points[2], points[3]);
    -				
    +				context.fillRect(points[0], points[1], points[2], points[3]);
    +
     			}
     			if(data.lineWidth)
     			{
     				context.globalAlpha = data.lineAlpha * worldAlpha;
     				context.strokeRect(points[0], points[1], points[2], points[3]);
     			}
    -			
    +
     		}
     		else if(data.type == PIXI.Graphics.CIRC)
     		{
    -			// TODO - need to be Undefined!
    +			// TODO - need to be Undefined!
           		context.beginPath();
     			context.arc(points[0], points[1], points[2],0,2*Math.PI);
     			context.closePath();
    -			
    +
     			if(data.fill)
     			{
     				context.globalAlpha = data.fillAlpha * worldAlpha;
    @@ -251,35 +275,35 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context)
     		}
     		else if(data.type == PIXI.Graphics.ELIP)
     		{
    -			
    -			// elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
    -			
    +
    +			// elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
    +
     			var elipseData =  data.points;
    -			
    +
     			var w = elipseData[2] * 2;
     			var h = elipseData[3] * 2;
    -	
    -			var x = elipseData[0] - w/2;
    -			var y = elipseData[1] - h/2;
    -			
    +
    +			var x = elipseData[0] - w/2;
    +			var y = elipseData[1] - h/2;
    +
           		context.beginPath();
    -			
    +
     			var kappa = .5522848,
    -			ox = (w / 2) * kappa, // control point offset horizontal
    -			oy = (h / 2) * kappa, // control point offset vertical
    -			xe = x + w,           // x-end
    -			ye = y + h,           // y-end
    -			xm = x + w / 2,       // x-middle
    -			ym = y + h / 2;       // y-middle
    -			
    +			ox = (w / 2) * kappa, // control point offset horizontal
    +			oy = (h / 2) * kappa, // control point offset vertical
    +			xe = x + w,           // x-end
    +			ye = y + h,           // y-end
    +			xm = x + w / 2,       // x-middle
    +			ym = y + h / 2;       // y-middle
    +
     			context.moveTo(x, ym);
     			context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
     			context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
     			context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
     			context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
    -  
    +
     			context.closePath();
    -			
    +
     			if(data.fill)
     			{
     				context.globalAlpha = data.fillAlpha * worldAlpha;
    @@ -292,51 +316,51 @@ PIXI.CanvasGraphics.renderGraphics = function(graphics, context)
           			context.stroke();
     			}
     		}
    -      	
    +
     	};
     }
     
    -/*
    - * @private
    +/*
    + * Renders a graphics mask
    + *
      * @static
    + * @private
      * @method renderGraphicsMask
      * @param graphics {Graphics}
      * @param context {Context2D}
    - */
    + */
     PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context)
     {
     	var worldAlpha = graphics.worldAlpha;
    -	
    +
     	var len = graphics.graphicsData.length;
     	if(len > 1)
     	{
     		len = 1;
     		console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object")
     	}
    -	
    -	for (var i=0; i < 1; i++) 
    +
    +	for (var i=0; i < 1; i++)
     	{
     		var data = graphics.graphicsData[i];
     		var points = data.points;
    -		
    +
     		if(data.type == PIXI.Graphics.POLY)
     		{
    -			//if(data.lineWidth <= 0)continue;
    -			
     			context.beginPath();
     			context.moveTo(points[0], points[1]);
    -			
    -			for (var j=1; j < points.length/2; j++)
    +
    +			for (var j=1; j < points.length/2; j++)
     			{
     				context.lineTo(points[j * 2], points[j * 2 + 1]);
    -			} 
    -	      	
    -	      	// if the first and last point are the same close the path - much neater :)
    +			}
    +
    +	      	// if the first and last point are the same close the path - much neater :)
     	      	if(points[0] == points[points.length-2] && points[1] == points[points.length-1])
     	      	{
     	      		context.closePath();
     	      	}
    -			
    +
     		}
     		else if(data.type == PIXI.Graphics.RECT)
     		{
    @@ -346,33 +370,33 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context)
     		}
     		else if(data.type == PIXI.Graphics.CIRC)
     		{
    -			// TODO - need to be Undefined!
    +			// TODO - need to be Undefined!
           		context.beginPath();
     			context.arc(points[0], points[1], points[2],0,2*Math.PI);
     			context.closePath();
     		}
     		else if(data.type == PIXI.Graphics.ELIP)
     		{
    -			
    -			// elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
    +
    +			// elipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
     			var elipseData =  data.points;
    -			
    +
     			var w = elipseData[2] * 2;
     			var h = elipseData[3] * 2;
    -	
    -			var x = elipseData[0] - w/2;
    -			var y = elipseData[1] - h/2;
    -			
    +
    +			var x = elipseData[0] - w/2;
    +			var y = elipseData[1] - h/2;
    +
           		context.beginPath();
    -			
    +
     			var kappa = .5522848,
    -			ox = (w / 2) * kappa, // control point offset horizontal
    -			oy = (h / 2) * kappa, // control point offset vertical
    -			xe = x + w,           // x-end
    -			ye = y + h,           // y-end
    -			xm = x + w / 2,       // x-middle
    -			ym = y + h / 2;       // y-middle
    -			
    +			ox = (w / 2) * kappa, // control point offset horizontal
    +			oy = (h / 2) * kappa, // control point offset vertical
    +			xe = x + w,           // x-end
    +			ye = y + h,           // y-end
    +			xm = x + w / 2,       // x-middle
    +			ym = y + h / 2;       // y-middle
    +
     			context.moveTo(x, ym);
     			context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
     			context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
    @@ -380,8 +404,8 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context)
     			context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
     			context.closePath();
     		}
    -      	
    -	   
    +
    +
     	};
     }
     
    @@ -394,13 +418,13 @@ PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context)
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_renderers_canvas_CanvasRenderer.js.html b/docs/files/src_pixi_renderers_canvas_CanvasRenderer.js.html index b4a1e3c..9f17324 100644 --- a/docs/files/src_pixi_renderers_canvas_CanvasRenderer.js.html +++ b/docs/files/src_pixi_renderers_canvas_CanvasRenderer.js.html @@ -2,12 +2,12 @@ - src/pixi/renderers/canvas/CanvasRenderer.js - Pixi.JS - - - - - + src/pixi/renderers/canvas/CanvasRenderer.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,105 +166,106 @@
    -

    File: src/pixi/renderers/canvas/CanvasRenderer.js

    +

    File: src/pixi/renderers/canvas/CanvasRenderer.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
     
    -/**
    +/**
      * the CanvasRenderer draws the stage and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL.
      * Dont forget to add the view to your DOM or you will not see anything :)
    + *
      * @class CanvasRenderer
      * @constructor
    - * @param width {Number} the width of the canvas view
    - * @default 0
    - * @param height {Number} the height of the canvas view
    - * @default 0
    + * @param width=0 {Number} the width of the canvas view
    + * @param height=0 {Number} the height of the canvas view
      * @param view {Canvas} the canvas to use as a view, optional
    - * @param transparent {Boolean} the transparency of the render view, default false
    - * @default false
    - * 
    - */
    + * @param transparent=false {Boolean} the transparency of the render view, default false
    + */
     PIXI.CanvasRenderer = function(width, height, view, transparent)
     {
     	this.transparent = transparent;
    -	
    -	/**
    +
    +	/**
     	 * The width of the canvas view
    +	 *
     	 * @property width
     	 * @type Number
     	 * @default 800
    -	 */
    +	 */
     	this.width = width || 800;
    -	/**
    +
    +	/**
     	 * The height of the canvas view
    +	 *
     	 * @property height
     	 * @type Number
     	 * @default 600
    -	 */
    +	 */
     	this.height = height || 600;
    -	
    -	this.refresh = true;
    -	
    -	/**
    +
    +	/**
     	 * The canvas element that the everything is drawn to
    +	 *
     	 * @property view
     	 * @type Canvas
    -	 */
    -	this.view = view || document.createElement( 'canvas' ); 
    -	
    -	// hack to enable some hardware acceleration!
    -	//this.view.style["transform"] = "translatez(0)";
    +	 */
    +	this.view = view || document.createElement( 'canvas' );
    +
    +	/**
    +	 * The canvas context that the everything is drawn to
    +	 * @property context
    +	 * @type Canvas 2d Context
    +	 */
    +	this.context = this.view.getContext("2d");
    +
    +	this.refresh = true;
    +	// hack to enable some hardware acceleration!
    +	//this.view.style["transform"] = "translatez(0)";
     	
         this.view.width = this.width;
     	this.view.height = this.height;  
     	this.count = 0;
    -	
    -	/**
    -	 * The canvas context that the everything is drawn to
    -	 * @property context
    -	 * @type Canvas 2d Context
    -	 */
    -	this.context = this.view.getContext("2d");
     }
     
    -// constructor
    -PIXI.CanvasRenderer.constructor = PIXI.CanvasRenderer;
    +// constructor
    +PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer;
     
    -/**
    +/**
      * Renders the stage to its canvas view
    + *
      * @method render
      * @param stage {Stage} the Stage element to be rendered
    - */
    + */
     PIXI.CanvasRenderer.prototype.render = function(stage)
     {
    -	// update children if need be
     	
    -	//stage.__childrenAdded = [];
    -	//stage.__childrenRemoved = [];
    +	//stage.__childrenAdded = [];
    +	//stage.__childrenRemoved = [];
     	
    -	// update textures if need be
    +	// update textures if need be
     	PIXI.texturesToUpdate = [];
     	PIXI.texturesToDestroy = [];
     	
    +	PIXI.visibleCount++;
     	stage.updateTransform();
     	
    -	// update the background color
    +	// update the background color
     	if(this.view.style.backgroundColor!=stage.backgroundColorString && !this.transparent)this.view.style.backgroundColor = stage.backgroundColorString;
     
     	this.context.setTransform(1,0,0,1,0,0); 
     	this.context.clearRect(0, 0, this.width, this.height)
         this.renderDisplayObject(stage);
    -    //as
    +    //as
        
    -    // run interaction!
    +    // run interaction!
     	if(stage.interactive)
     	{
    -		//need to add some events!
    +		//need to add some events!
     		if(!stage._interactiveEventsAdded)
     		{
     			stage._interactiveEventsAdded = true;
    @@ -248,18 +273,22 @@ PIXI.CanvasRenderer.prototype.render = function(stage)
     		}
     	}
     	
    -	// remove frame updates..
    +	// remove frame updates..
     	if(PIXI.Texture.frameUpdates.length > 0)
     	{
     		PIXI.Texture.frameUpdates = [];
     	}
    +	
    +	
     }
     
    -/**
    +/**
      * resizes the canvas view to the specified width and height
    - * @param the new width of the canvas view
    - * @param the new height of the canvas view
    - */
    + *
    + * @method resize
    + * @param width {Number} the new width of the canvas view
    + * @param height {Number} the new height of the canvas view
    + */
     PIXI.CanvasRenderer.prototype.resize = function(width, height)
     {
     	this.width = width;
    @@ -269,19 +298,22 @@ PIXI.CanvasRenderer.prototype.resize = function(width, height)
     	this.view.height = height;
     }
     
    -/**
    +/**
    + * Renders a display object
    + *
    + * @method renderDisplayObject
    + * @param displayObject {DisplayObject} The displayObject to render
      * @private
    - */
    -
    + */
     PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject)
     {
    -	// no loger recurrsive!
    +	// no loger recurrsive!
     	var transform;
     	var context = this.context;
     	
     	context.globalCompositeOperation = 'source-over';
     	
    -	// one the display object hits this. we can break the loop	
    +	// one the display object hits this. we can break the loop	
     	var testObject = displayObject.last._iNext;
     	displayObject = displayObject.first;
     	
    @@ -306,7 +338,7 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject)
     				
     			var frame = displayObject.texture.frame;
     			
    -			if(frame)
    +			if(frame && frame.width && frame.height)
     			{
     				context.globalAlpha = displayObject.worldAlpha;
     				
    @@ -335,6 +367,7 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject)
     		}
     		else if(displayObject instanceof PIXI.CustomRenderable)
     		{
    +			context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]);
     			displayObject.renderCanvas(this);
     		}
     		else if(displayObject instanceof PIXI.Graphics)
    @@ -344,59 +377,69 @@ PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject)
     		}
     		else if(displayObject instanceof PIXI.FilterBlock)
     		{
    -			if(displayObject.open)
    -			{
    -				context.save();
    -				
    -				var cacheAlpha = displayObject.mask.alpha;
    -				var maskTransform = displayObject.mask.worldTransform;
    -				
    -				context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5])
    -				
    -				displayObject.mask.worldAlpha = 0.5;
    -				
    -				context.worldAlpha = 0;
    -				
    -				PIXI.CanvasGraphics.renderGraphicsMask(displayObject.mask, context);
    -		//		context.fillStyle = 0xFF0000;
    -			//	context.fillRect(0, 0, 200, 200);
    -				context.clip();
    -				
    -				displayObject.mask.worldAlpha = cacheAlpha;
    -				//context.globalCompositeOperation = 'lighter';
    +			if(displayObject.data instanceof PIXI.Graphics)
    + 			{
    +				var mask = displayObject.data;
    +
    +				if(displayObject.open)
    +				{
    +					context.save();
    +					
    +					var cacheAlpha = mask.alpha;
    +					var maskTransform = mask.worldTransform;
    +					
    +					context.setTransform(maskTransform[0], maskTransform[3], maskTransform[1], maskTransform[4], maskTransform[2], maskTransform[5])
    +					
    +					mask.worldAlpha = 0.5;
    +					
    +					context.worldAlpha = 0;
    +					
    +					PIXI.CanvasGraphics.renderGraphicsMask(mask, context);
    +					context.clip();
    +					
    +					mask.worldAlpha = cacheAlpha;
    +				}
    +				else
    +				{
    +					context.restore();
    +				}
     			}
     			else
     			{
    -				//context.globalCompositeOperation = 'source-over';
    -				context.restore();
    +				// only masks supported right now!
     			}
     		}
    -	//	count++
    +	//	count++
     		displayObject = displayObject._iNext;
     		
     		
     	}
     	while(displayObject != testObject)
    +
    +	
     }
     
    -
    -/**
    +/**
    + * Renders a flat strip
    + *
    + * @method renderStripFlat
    + * @param strip {Strip} The Strip to render
      * @private
    - */
    + */
     PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip)
     {
     	var context = this.context;
     	var verticies = strip.verticies;
     	var uvs = strip.uvs;
     	
    -	var length = verticies.length/2;
    +	var length = verticies.length/2;
     	this.count++;
     	
     	context.beginPath();
     	for (var i=1; i < length-2; i++) 
     	{
     		
    -		// draw some triangles!
    +		// draw some triangles!
     		var index = i*2;
     		
     		 var x0 = verticies[index],   x1 = verticies[index+2], x2 = verticies[index+4];
    @@ -413,9 +456,13 @@ PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip)
     	context.closePath();
     }
     
    -/**
    +/**
    + * Renders a tiling sprite
    + *
    + * @method renderTilingSprite
    + * @param sprite {TilingSprite} The tilingsprite to render
      * @private
    - */
    + */
     PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite)
     {
     	var context = this.context;
    @@ -429,38 +476,40 @@ PIXI.CanvasRenderer.prototype.renderTilingSprite = function(sprite)
     	var tilePosition = sprite.tilePosition;
     	var tileScale = sprite.tileScale;
     	
    -    // offset
    +    // offset
         context.scale(tileScale.x,tileScale.y);
         context.translate(tilePosition.x, tilePosition.y);
      	
     	context.fillStyle = sprite.__tilePattern;
    -	context.fillRect(-tilePosition.x,-tilePosition.y,sprite.width / tileScale.x, sprite.height / tileScale.y);
    +	context.fillRect(-tilePosition.x,-tilePosition.y,sprite.width / tileScale.x, sprite.height / tileScale.y);
     	
    -	context.scale(1/tileScale.x, 1/tileScale.y);
    +	context.scale(1/tileScale.x, 1/tileScale.y);
         context.translate(-tilePosition.x, -tilePosition.y);
         
         context.closePath();
     }
     
    -
    -
    -/**
    +/**
    + * Renders a strip
    + *
    + * @method renderStrip
    + * @param strip {Strip} The Strip to render
      * @private
    - */
    + */
     PIXI.CanvasRenderer.prototype.renderStrip = function(strip)
     {
     	var context = this.context;
    -	//context.globalCompositeOperation = 'lighter';
    -	// draw triangles!!
    +
    +	// draw triangles!!
     	var verticies = strip.verticies;
     	var uvs = strip.uvs;
     	
    -	var length = verticies.length/2;
    +	var length = verticies.length/2;
     	this.count++;
     	for (var i=1; i < length-2; i++) 
     	{
     		
    -		// draw some triangles!
    +		// draw some triangles!
     		var index = i*2;
     		
     		 var x0 = verticies[index],   x1 = verticies[index+2], x2 = verticies[index+4];
    @@ -477,12 +526,10 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip)
     		context.lineTo(x2, y2);
     		context.closePath();
     		
    -	//	context.fillStyle = "white"//rgb(1, 1, 1,1));
    -	//	context.fill();
     		context.clip();
     		
     		
    -        // Compute matrix transform
    +        // Compute matrix transform
             var delta = u0*v1 + v0*u2 + u1*v2 - v1*u2 - v0*u1 - u0*v2;
             var delta_a = x0*v1 + v0*x2 + x1*v2 - v1*x2 - v0*x1 - x0*v2;
             var delta_b = u0*x1 + x0*u2 + u1*x2 - x1*u2 - x0*u1 - u0*x2;
    @@ -494,25 +541,16 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip)
     		
     		
     		    
    -        context.transform(delta_a/delta, delta_d/delta,
    -                      delta_b/delta, delta_e/delta,
    -                      delta_c/delta, delta_f/delta);
    +        context.transform(delta_a/delta, delta_d/delta,
    +                      delta_b/delta, delta_e/delta,
    +                      delta_c/delta, delta_f/delta);
                      
     		context.drawImage(strip.texture.baseTexture.source, 0, 0);
     	  	context.restore();
     	};
     	
    -//	context.globalCompositeOperation = 'source-over';	
     }
     
    -
    -
    -
    -
    -
    -
    -
    -
         
    @@ -522,13 +560,13 @@ PIXI.CanvasRenderer.prototype.renderStrip = function(strip)
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_renderers_webgl_PixiShader.js.html b/docs/files/src_pixi_renderers_webgl_PixiShader.js.html new file mode 100644 index 0000000..a1b2a0a --- /dev/null +++ b/docs/files/src_pixi_renderers_webgl_PixiShader.js.html @@ -0,0 +1,311 @@ + + + + + src/pixi/renderers/webgl/PixiShader.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/renderers/webgl/PixiShader.js

    + +
    +
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +
    +PIXI.PixiShader = function()
    +{
    +	// the webGL program..
    +	this.program;
    +	
    +	this.fragmentSrc = [
    +	  "precision lowp float;",
    +	  "varying vec2 vTextureCoord;",
    +	  "varying float vColor;",
    +	  "uniform sampler2D uSampler;",
    +	  "void main(void) {",
    +	    "gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;",
    +	  "}"
    +	];
    +	
    +}
    +
    +PIXI.PixiShader.prototype.init = function()
    +{
    +	var program = PIXI.compileProgram(this.vertexSrc || PIXI.PixiShader.defaultVertexSrc, this.fragmentSrc)
    +	
    +	var gl = PIXI.gl;
    +	
    +    gl.useProgram(program);
    +	
    +	// get and store the uniforms for the shader
    +	this.uSampler = gl.getUniformLocation(program, "uSampler");
    +	this.projectionVector = gl.getUniformLocation(program, "projectionVector");
    +	this.offsetVector = gl.getUniformLocation(program, "offsetVector");
    +	this.colorAttribute = gl.getAttribLocation(program, "aColor");
    +	//this.dimensions = gl.getUniformLocation(this.program, "dimensions");
    +	
    +	// get and store the attributes
    +	this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
    +	this.aTextureCoord = gl.getAttribLocation(program, "aTextureCoord");
    +	  
    +    // add those custom shaders!
    +    for (var key in this.uniforms)
    +    {
    +       
    +    	// get the uniform locations..
    +		program[key] = gl.getUniformLocation(program, key);
    +
    +
    +      
    +    }
    +  
    +	this.program = program;
    +}
    +
    +PIXI.PixiShader.prototype.syncUniforms = function()
    +{
    +	var gl = PIXI.gl;
    +	
    +	for (var key in this.uniforms) 
    +    {
    +    	//var 
    +    	var type = this.uniforms[key].type;
    +    	
    +    	// need to grow this!
    +    	if(type == "f")
    +    	{
    +			gl.uniform1f(this.program[key], this.uniforms[key].value);
    +    	}
    +    	if(type == "f2")
    +    	{
    +    	//	console.log(this.program[key])
    +			gl.uniform2f(this.program[key], this.uniforms[key].value.x, this.uniforms[key].value.y);
    +    	}
    +        else if(type == "f4")
    +        {
    +           // console.log(this.uniforms[key].value)
    +            gl.uniform4fv(this.program[key], this.uniforms[key].value);
    +        }
    +    	else if(type == "mat4")
    +    	{
    +    		gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value);
    +    	}
    +    	else if(type == "sampler2D")
    +    	{
    +    		// first texture...
    +    		var texture = this.uniforms[key].value;
    +    		
    +    		gl.activeTexture(gl.TEXTURE1);
    +	    	gl.bindTexture(gl.TEXTURE_2D, texture.baseTexture._glTexture);
    +	    	
    +    		gl.uniform1i(this.program[key], 1);
    +    		
    +    		// activate texture..
    +    		// gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value);
    +    		// gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value);
    +    	}
    +    }
    +    
    +}
    +
    +PIXI.PixiShader.defaultVertexSrc = [
    +  "attribute vec2 aVertexPosition;",
    +  "attribute vec2 aTextureCoord;",
    +  "attribute float aColor;",
    +  
    +  "uniform vec2 projectionVector;",
    + "uniform vec2 offsetVector;",
    +  "varying vec2 vTextureCoord;",
    +  
    +  "varying float vColor;",
    +
    +  "const vec2 center = vec2(-1.0, 1.0);",
    +  "void main(void) {",
    +    "gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);",
    +    "vTextureCoord = aTextureCoord;",
    +    "vColor = aColor;",
    +  "}"
    +];
    +
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_renderers_webgl_PrimitiveShader.js.html b/docs/files/src_pixi_renderers_webgl_PrimitiveShader.js.html new file mode 100644 index 0000000..ec967e2 --- /dev/null +++ b/docs/files/src_pixi_renderers_webgl_PrimitiveShader.js.html @@ -0,0 +1,249 @@ + + + + + src/pixi/renderers/webgl/PrimitiveShader.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/renderers/webgl/PrimitiveShader.js

    + +
    +
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +
    +PIXI.PrimitiveShader = function()
    +{
    +	// the webGL program..
    +	this.program;
    +    	
    +    this.fragmentSrc = [
    +      "precision mediump float;",
    +      "varying vec4 vColor;",
    +      "void main(void) {",
    +        "gl_FragColor = vColor;",
    +      "}"
    +    ];
    +
    +    this.vertexSrc  = [
    +      "attribute vec2 aVertexPosition;",
    +      "attribute vec4 aColor;",
    +      "uniform mat3 translationMatrix;",
    +      "uniform vec2 projectionVector;",
    +      "uniform vec2 offsetVector;",
    +      "uniform float alpha;",
    +      "varying vec4 vColor;",
    +      "void main(void) {",
    +        "vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);",
    +        "v -= offsetVector.xyx;",
    +        "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);",
    +        "vColor = aColor  * alpha;",
    +      "}"
    +    ];
    +	
    +}
    +
    +PIXI.PrimitiveShader.prototype.init = function()
    +{
    +	var program = PIXI.compileProgram(this.vertexSrc, this.fragmentSrc);
    +	
    +	var gl = PIXI.gl;
    +	
    +  gl.useProgram(program);
    +	
    +	// get and store the uniforms for the shader
    +	this.projectionVector = gl.getUniformLocation(program, "projectionVector");
    +	this.offsetVector = gl.getUniformLocation(program, "offsetVector");
    +	this.colorAttribute = gl.getAttribLocation(program, "aColor");
    +	
    +	// get and store the attributes
    +	this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
    +	
    +    this.translationMatrix = gl.getUniformLocation(program, "translationMatrix");
    +    this.alpha = gl.getUniformLocation(program, "alpha");
    +
    +	this.program = program;
    +}
    +
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_renderers_webgl_StripShader.js.html b/docs/files/src_pixi_renderers_webgl_StripShader.js.html new file mode 100644 index 0000000..4e56dc0 --- /dev/null +++ b/docs/files/src_pixi_renderers_webgl_StripShader.js.html @@ -0,0 +1,257 @@ + + + + + src/pixi/renderers/webgl/StripShader.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/renderers/webgl/StripShader.js

    + +
    +
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +
    +PIXI.StripShader = function()
    +{
    +	// the webGL program..
    +	this.program;
    +	
    +    this.fragmentSrc = [
    +      "precision mediump float;",
    +      "varying vec2 vTextureCoord;",
    +      "varying float vColor;",
    +      "uniform float alpha;",
    +      "uniform sampler2D uSampler;",
    +      "void main(void) {",
    +        "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));",
    +        "gl_FragColor = gl_FragColor * alpha;",
    +      "}"
    +    ];
    +
    +    this.vertexSrc = [
    +      "attribute vec2 aVertexPosition;",
    +      "attribute vec2 aTextureCoord;",
    +      "attribute float aColor;",
    +      "uniform mat3 translationMatrix;",
    +      "uniform vec2 projectionVector;",
    +      "varying vec2 vTextureCoord;",
    +      "varying vec2 offsetVector;",
    +      "varying float vColor;",
    +      "void main(void) {",
    +        "vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);",
    +        "v -= offsetVector.xyx;",
    +        "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);",
    +        "vTextureCoord = aTextureCoord;",
    +        "vColor = aColor;",
    +      "}"
    +    ];
    +}
    +
    +PIXI.StripShader.prototype.init = function()
    +{
    +	var program = PIXI.compileProgram(this.vertexSrc, this.fragmentSrc)
    +	
    +	var gl = PIXI.gl;
    +	
    +    gl.useProgram(program);
    +
    +	// get and store the uniforms for the shader
    +	this.uSampler = gl.getUniformLocation(program, "uSampler");
    +	this.projectionVector = gl.getUniformLocation(program, "projectionVector");
    +	this.offsetVector = gl.getUniformLocation(program, "offsetVector");
    +	this.colorAttribute = gl.getAttribLocation(program, "aColor");
    +	//this.dimensions = gl.getUniformLocation(this.program, "dimensions");
    +	
    +	// get and store the attributes
    +	this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
    +	this.aTextureCoord = gl.getAttribLocation(program, "aTextureCoord");
    +	  
    +    this.translationMatrix = gl.getUniformLocation(program, "translationMatrix");
    +    this.alpha = gl.getUniformLocation(program, "alpha");
    +  
    +	this.program = program;
    +}
    +
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_renderers_webgl_WebGLBatch.js.html b/docs/files/src_pixi_renderers_webgl_WebGLBatch.js.html index 3d14d09..0d6c2ab 100644 --- a/docs/files/src_pixi_renderers_webgl_WebGLBatch.js.html +++ b/docs/files/src_pixi_renderers_webgl_WebGLBatch.js.html @@ -2,12 +2,12 @@ - src/pixi/renderers/webgl/WebGLBatch.js - Pixi.JS - - - - - + src/pixi/renderers/webgl/WebGLBatch.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,19 +166,19 @@
    -

    File: src/pixi/renderers/webgl/WebGLBatch.js

    +

    File: src/pixi/renderers/webgl/WebGLBatch.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
     PIXI._batchs = [];
     
    -/**
    +/**
      * @private
    - */
    + */
     PIXI._getBatch = function(gl)
     {
     	if(PIXI._batchs.length == 0)
    @@ -167,18 +191,18 @@ PIXI._getBatch = function(gl)
     	}
     }
     
    -/**
    +/**
      * @private
    - */
    + */
     PIXI._returnBatch = function(batch)
     {
     	batch.clean();	
     	PIXI._batchs.push(batch);
     }
     
    -/**
    +/**
      * @private
    - */
    + */
     PIXI._restoreBatchs = function(gl)
     {
     	for (var i=0; i < PIXI._batchs.length; i++) 
    @@ -187,13 +211,18 @@ PIXI._restoreBatchs = function(gl)
     	};
     }
     
    -/**
    +/**
      * A WebGLBatch Enables a group of sprites to be drawn using the same settings.
    - * if a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch. All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster the webGL renderer will run. 
    + * if a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch.
    + * All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites
    + * in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled
    + * automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster
    + * the webGL renderer will run.
    + *
      * @class WebGLBatch
    - * @param an instance of the webGL context
    - * @return {PIXI.renderers.WebGLBatch} WebGLBatch {@link PIXI.renderers.WebGLBatch}
    - */
    + * @constructor
    + * @param gl {WebGLContext} an instance of the webGL context
    + */
     PIXI.WebGLBatch = function(gl)
     {
     	this.gl = gl;
    @@ -208,32 +237,34 @@ PIXI.WebGLBatch = function(gl)
     	this.dynamicSize = 1;
     }
     
    +// constructor
    +PIXI.WebGLBatch.prototype.constructor = PIXI.WebGLBatch;
     
    -// constructor
    -PIXI.WebGLBatch.constructor = PIXI.WebGLBatch;
    -
    -/**
    +/**
      * Cleans the batch so that is can be returned to an object pool and reused
    - */
    + *
    + * @method clean
    + */
     PIXI.WebGLBatch.prototype.clean = function()
     {
     	this.verticies = [];
     	this.uvs = [];
     	this.indices = [];
     	this.colors = [];
    -	//this.sprites = [];
     	this.dynamicSize = 1;
     	this.texture = null;
     	this.last = null;
     	this.size = 0;
    -	
     	this.head;
     	this.tail;
     }
     
    -/*
    - * recreates the buffers in the event of a context loss
    - */
    +/**
    + * Recreates the buffers in the event of a context loss
    + *
    + * @method restoreLostContext
    + * @param gl {WebGLContext}
    + */
     PIXI.WebGLBatch.prototype.restoreLostContext = function(gl)
     {
     	this.gl = gl;
    @@ -243,41 +274,43 @@ PIXI.WebGLBatch.prototype.restoreLostContext = function(gl)
     	this.colorBuffer =  gl.createBuffer();
     }
     
    -/**
    +/**
      * inits the batch's texture and blend mode based if the supplied sprite
    + *
      * @method init
    - * @param sprite {Sprite} the first sprite to be added to the batch. Only sprites with the same base texture and blend mode will be allowed to be added to this batch
    - */	
    + * @param sprite {Sprite} the first sprite to be added to the batch. Only sprites with
    + *		the same base texture and blend mode will be allowed to be added to this batch
    + */	
     PIXI.WebGLBatch.prototype.init = function(sprite)
     {
     	sprite.batch = this;
     	this.dirty = true;
     	this.blendMode = sprite.blendMode;
     	this.texture = sprite.texture.baseTexture;
    -//	this.sprites.push(sprite);
     	this.head = sprite;
     	this.tail = sprite;
     	this.size = 1;
    -	
    +
     	this.growBatch();
     }
     
    -/**
    +/**
      * inserts a sprite before the specified sprite
    + *
      * @method insertBefore
      * @param sprite {Sprite} the sprite to be added
      * @param nextSprite {nextSprite} the first sprite will be inserted before this sprite
    - */	
    + */	
     PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite)
     {
     	this.size++;
    -	
    +
     	sprite.batch = this;
     	this.dirty = true;
     	var tempPrev = nextSprite.__prev;
     	nextSprite.__prev = sprite;
     	sprite.__next = nextSprite;
    -	
    +
     	if(tempPrev)
     	{
     		sprite.__prev = tempPrev;
    @@ -286,28 +319,27 @@ PIXI.WebGLBatch.prototype.insertBefore = function(sprite, nextSprite)
     	else
     	{
     		this.head = sprite;
    -		//this.head.__prev = null
     	}
     }
     
    -/**
    +/**
      * inserts a sprite after the specified sprite
    + *
      * @method insertAfter
      * @param sprite {Sprite} the sprite to be added
      * @param  previousSprite {Sprite} the first sprite will be inserted after this sprite
    - */	
    + */	
     PIXI.WebGLBatch.prototype.insertAfter = function(sprite, previousSprite)
     {
     	this.size++;
    -	
    -	
    +
     	sprite.batch = this;
     	this.dirty = true;
    -	
    +
     	var tempNext = previousSprite.__next;
     	previousSprite.__next = sprite;
     	sprite.__prev = previousSprite;
    -	
    +
     	if(tempNext)
     	{
     		sprite.__next = tempNext;
    @@ -317,18 +349,18 @@ PIXI.WebGLBatch.prototype.insertAfter = function(sprite, previousSprite)
     	{
     		this.tail = sprite
     	}
    -	
     }
     
    -/**
    +/**
      * removes a sprite from the batch
    + *
      * @method remove
      * @param sprite {Sprite} the sprite to be removed
    - */	
    + */	
     PIXI.WebGLBatch.prototype.remove = function(sprite)
     {
     	this.size--;
    -	
    +
     	if(this.size == 0)
     	{
     		sprite.batch = null;
    @@ -336,7 +368,7 @@ PIXI.WebGLBatch.prototype.remove = function(sprite)
     		sprite.__next = null;
     		return;
     	}
    -	
    +
     	if(sprite.__prev)
     	{
     		sprite.__prev.__next = sprite.__next;
    @@ -346,7 +378,7 @@ PIXI.WebGLBatch.prototype.remove = function(sprite)
     		this.head = sprite.__next;
     		this.head.__prev = null;
     	}
    -	
    +
     	if(sprite.__next)
     	{
     		sprite.__next.__prev = sprite.__prev;
    @@ -356,49 +388,40 @@ PIXI.WebGLBatch.prototype.remove = function(sprite)
     		this.tail = sprite.__prev;
     		this.tail.__next = null
     	}
    -	
    +
     	sprite.batch = null;
     	sprite.__next = null;
     	sprite.__prev = null;
     	this.dirty = true;
     }
     
    -/**
    +/**
      * Splits the batch into two with the specified sprite being the start of the new batch.
    + *
      * @method split
      * @param sprite {Sprite} the sprite that indicates where the batch should be split
      * @return {WebGLBatch} the new batch
    - */
    + */
     PIXI.WebGLBatch.prototype.split = function(sprite)
     {
    -	
    -	//console.log("Splitting batch :" + this.size)
    -//	console.log(sprite)
    -//	console.log("-------")
     	this.dirty = true;
    -	
    -	//var val = (this.tail == this.head)
    -	//console.log(val + " SAME?");
    -	var batch = new PIXI.WebGLBatch(this.gl)//PIXI._getBatch(this.gl);
    +
    +	var batch = new PIXI.WebGLBatch(this.gl);
     	batch.init(sprite);
     	batch.texture = this.texture;
     	batch.tail = this.tail;
    -	//console.log("id is " +batcheee.id)
    -	
    +
     	this.tail = sprite.__prev;
     	this.tail.__next = null;
    -	
    +
     	sprite.__prev = null;
    -	// return a splite batch!
    -	//sprite.__prev.__next = null;
    -	//sprite.__prev = null;
    -	
    -	
    -	// TODO this size is wrong!
    -	// need to recalculate :/ problem with a linked list!
    -	// unless it gets calculated in the "clean"?
    -	
    -	// need to loop through items as there is no way to know the length on a linked list :/
    +	// return a splite batch!
    +
    +	// TODO this size is wrong!
    +	// need to recalculate :/ problem with a linked list!
    +	// unless it gets calculated in the "clean"?
    +
    +	// need to loop through items as there is no way to know the length on a linked list :/
     	var tempSize = 0;
     	while(sprite)
     	{
    @@ -406,42 +429,45 @@ PIXI.WebGLBatch.prototype.split = function(sprite)
     		sprite.batch = batch;
     		sprite = sprite.__next;
     	}
    -	
    +
     	batch.size = tempSize;
     	this.size -= tempSize;
    -	
    +
     	return batch;
     }
     
    -/**
    +/**
      * Merges two batchs together
    + *
      * @method merge
      * @param batch {WebGLBatch} the batch that will be merged 
    - */
    + */
     PIXI.WebGLBatch.prototype.merge = function(batch)
     {
     	this.dirty = true;
    -	
    +
     	this.tail.__next = batch.head;
     	batch.head.__prev = this.tail;
    -	
    +
     	this.size += batch.size;
    -			
    +
     	this.tail = batch.tail;
    -	
    +
     	var sprite = batch.head;
     	while(sprite)
     	{
     		sprite.batch = this;
     		sprite = sprite.__next;
     	}
    -	
     }
     
    -/**
    - * Grows the size of the batch. As the elements in the batch cannot have a dynamic size this function is used to increase the size of the batch. It also creates a little extra room so that the batch does not need to be resized every time a sprite is added
    - * @methos growBatch
    - */
    +/**
    + * Grows the size of the batch. As the elements in the batch cannot have a dynamic size this
    + * function is used to increase the size of the batch. It also creates a little extra room so
    + * that the batch does not need to be resized every time a sprite is added
    + *
    + * @method growBatch
    + */
     PIXI.WebGLBatch.prototype.growBatch = function()
     {
     	var gl = this.gl;
    @@ -453,27 +479,27 @@ PIXI.WebGLBatch.prototype.growBatch = function()
     	{
     		this.dynamicSize = this.size * 1.5
     	}
    -	// grow verts
    +	// grow verts
     	this.verticies = new Float32Array(this.dynamicSize * 8);
    -	
    +
     	gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
     	gl.bufferData(gl.ARRAY_BUFFER,this.verticies , gl.DYNAMIC_DRAW);
    -	
    -	this.uvs  = new Float32Array( this.dynamicSize * 8 )  
    +
    +	this.uvs  = new Float32Array( this.dynamicSize * 8 );
     	gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
     	gl.bufferData(gl.ARRAY_BUFFER, this.uvs , gl.DYNAMIC_DRAW);
    -	
    +
     	this.dirtyUVS = true;
    -	
    -	this.colors  = new Float32Array( this.dynamicSize * 4 )  
    +
    +	this.colors  = new Float32Array( this.dynamicSize * 4 );
     	gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer);
     	gl.bufferData(gl.ARRAY_BUFFER, this.colors , gl.DYNAMIC_DRAW);
    -	
    +
     	this.dirtyColors = true;
    -	
    +
     	this.indices = new Uint16Array(this.dynamicSize * 6); 
    -	var length = this.indices.length/6;
    -	
    +	var length = this.indices.length/6;
    +
     	for (var i=0; i < length; i++) 
     	{
     	    var index2 = i * 6;
    @@ -485,215 +511,208 @@ PIXI.WebGLBatch.prototype.growBatch = function()
     		this.indices[index2 + 4] = index3 + 2;
     		this.indices[index2 + 5] = index3 + 3;
     	};
    -	
    +
     	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
         gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);
    -	
     }
     
    -/**
    +/**
      * Refresh's all the data in the batch and sync's it with the webGL buffers
    + *
      * @method refresh
    - */
    + */
     PIXI.WebGLBatch.prototype.refresh = function()
     {
     	var gl = this.gl;
    -	
    +
     	if (this.dynamicSize < this.size)
     	{
     		this.growBatch();
     	}
     
     	var indexRun = 0;
    -	var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index
    -	var a, b, c, d, tx, ty
    -	
    -	var displayObject = this.head
    +	var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index;
    +	var a, b, c, d, tx, ty;
    +
    +	var displayObject = this.head;
     
     	while(displayObject)
     	{
     		index = indexRun * 8;
    -		
    +
     		var texture = displayObject.texture;
    -			
    +
     		var frame = texture.frame;
     		var tw = texture.baseTexture.width;
     		var th = texture.baseTexture.height;
    -		
    -		this.uvs[index + 0] = frame.x / tw;
    -		this.uvs[index +1] = frame.y / th;
    -		
    -		this.uvs[index +2] = (frame.x + frame.width) / tw;
    -		this.uvs[index +3] = frame.y / th;
    -		
    -		this.uvs[index +4] = (frame.x + frame.width) / tw;
    -		this.uvs[index +5] = (frame.y + frame.height) / th; 
    -		
    -		this.uvs[index +6] = frame.x / tw;
    -		this.uvs[index +7] = (frame.y + frame.height) / th;
    -		
    +
    +		this.uvs[index + 0] = frame.x / tw;
    +		this.uvs[index +1] = frame.y / th;
    +
    +		this.uvs[index +2] = (frame.x + frame.width) / tw;
    +		this.uvs[index +3] = frame.y / th;
    +
    +		this.uvs[index +4] = (frame.x + frame.width) / tw;
    +		this.uvs[index +5] = (frame.y + frame.height) / th; 
    +
    +		this.uvs[index +6] = frame.x / tw;
    +		this.uvs[index +7] = (frame.y + frame.height) / th;
    +
     		displayObject.updateFrame = false;
    -		
    +
     		colorIndex = indexRun * 4;
     		this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha;
    -		
    +
     		displayObject = displayObject.__next;
    -		
    +
     		indexRun ++;
     	}
    -	
    +
     	this.dirtyUVS = true;
     	this.dirtyColors = true;
     }
     
    -/**
    +/**
      * Updates all the relevant geometry and uploads the data to the GPU
    + *
      * @method update
    - */
    + */
     PIXI.WebGLBatch.prototype.update = function()
     {
     	var gl = this.gl;
     	var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index, index2, index3
    -	
    +
     	var a, b, c, d, tx, ty;
    -	
    +
     	var indexRun = 0;
    -	
    +
     	var displayObject = this.head;
    +	var verticies = this.verticies;
    +	var uvs = this.uvs;
    +	var colors = this.colors;
     	
     	while(displayObject)
     	{
    -		if(displayObject.worldVisible)
    +		if(displayObject.vcount === PIXI.visibleCount)
     		{
     			width = displayObject.texture.frame.width;
     			height = displayObject.texture.frame.height;
    -			
    -			// TODO trim??
    -			aX = displayObject.anchor.x;// - displayObject.texture.trim.x
    -			aY = displayObject.anchor.y; //- displayObject.texture.trim.y
    +
    +			// TODO trim??
    +			aX = displayObject.anchor.x;// - displayObject.texture.trim.x
    +			aY = displayObject.anchor.y; //- displayObject.texture.trim.y
     			w0 = width * (1-aX);
     			w1 = width * -aX;
    -			 
    +
     			h0 = height * (1-aY);
     			h1 = height * -aY;
    -			 
    +
     			index = indexRun * 8;
    -	
    +
     			worldTransform = displayObject.worldTransform;
    -		
    +
     			a = worldTransform[0];
     			b = worldTransform[3];
     			c = worldTransform[1];
     			d = worldTransform[4];
     			tx = worldTransform[2];
     			ty = worldTransform[5];
    -		
    -			this.verticies[index + 0 ] = a * w1 + c * h1 + tx; 
    -			this.verticies[index + 1 ] = d * h1 + b * w1 + ty;
    -			 
    -			this.verticies[index + 2 ] = a * w0 + c * h1 + tx; 
    -			this.verticies[index + 3 ] = d * h1 + b * w0 + ty; 
    -			
    -			this.verticies[index + 4 ] = a * w0 + c * h0 + tx; 
    -			this.verticies[index + 5 ] = d * h0 + b * w0 + ty; 
    -			
    -			this.verticies[index + 6] =  a * w1 + c * h0 + tx; 
    -			this.verticies[index + 7] =  d * h0 + b * w1 + ty; 
    -			
    -			
    +
    +			verticies[index + 0 ] = a * w1 + c * h1 + tx; 
    +			verticies[index + 1 ] = d * h1 + b * w1 + ty;
    +
    +			verticies[index + 2 ] = a * w0 + c * h1 + tx; 
    +			verticies[index + 3 ] = d * h1 + b * w0 + ty; 
    +
    +			verticies[index + 4 ] = a * w0 + c * h0 + tx; 
    +			verticies[index + 5 ] = d * h0 + b * w0 + ty; 
    +
    +			verticies[index + 6] =  a * w1 + c * h0 + tx; 
    +			verticies[index + 7] =  d * h0 + b * w1 + ty; 
    +
     			if(displayObject.updateFrame || displayObject.texture.updateFrame)
     			{
     				this.dirtyUVS = true;
    -				
    +
     				var texture = displayObject.texture;
    -				
    +
     				var frame = texture.frame;
     				var tw = texture.baseTexture.width;
     				var th = texture.baseTexture.height;
    -				
    -				this.uvs[index + 0] = frame.x / tw;
    -				this.uvs[index +1] = frame.y / th;
    -				
    -				this.uvs[index +2] = (frame.x + frame.width) / tw;
    -				this.uvs[index +3] = frame.y / th;
    -				
    -				this.uvs[index +4] = (frame.x + frame.width) / tw;
    -				this.uvs[index +5] = (frame.y + frame.height) / th; 
    -				
    -				this.uvs[index +6] = frame.x / tw;
    -				this.uvs[index +7] = (frame.y + frame.height) / th;
    -				
    +
    +				uvs[index + 0] = frame.x / tw;
    +				uvs[index +1] = frame.y / th;
    +
    +				uvs[index +2] = (frame.x + frame.width) / tw;
    +				uvs[index +3] = frame.y / th;
    +
    +				uvs[index +4] = (frame.x + frame.width) / tw;
    +				uvs[index +5] = (frame.y + frame.height) / th; 
    +
    +				uvs[index +6] = frame.x / tw;
    +				uvs[index +7] = (frame.y + frame.height) / th;
    +
     				displayObject.updateFrame = false;
     			}
    -			
    -			// TODO this probably could do with some optimisation....
    +
    +			// TODO this probably could do with some optimisation....
     			if(displayObject.cacheAlpha != displayObject.worldAlpha)
     			{
     				displayObject.cacheAlpha = displayObject.worldAlpha;
    -				
    +
     				var colorIndex = indexRun * 4;
    -				this.colors[colorIndex] = this.colors[colorIndex + 1] = this.colors[colorIndex + 2] = this.colors[colorIndex + 3] = displayObject.worldAlpha;
    +				colors[colorIndex] = colors[colorIndex + 1] = colors[colorIndex + 2] = colors[colorIndex + 3] = displayObject.worldAlpha;
     				this.dirtyColors = true;
     			}
     		}
     		else
     		{
     			index = indexRun * 8;
    -			
    -			this.verticies[index + 0 ] = 0;
    -			this.verticies[index + 1 ] = 0;
    -			 
    -			this.verticies[index + 2 ] = 0;
    -			this.verticies[index + 3 ] = 0;
    -			
    -			this.verticies[index + 4 ] = 0;
    -			this.verticies[index + 5 ] = 0;
    -			
    -			this.verticies[index + 6] = 0;
    -			this.verticies[index + 7] = 0;
    +
    +			verticies[index + 0 ] = verticies[index + 1 ] = verticies[index + 2 ] = verticies[index + 3 ] = verticies[index + 4 ] = verticies[index + 5 ] = verticies[index + 6] = 	verticies[index + 7] = 0;
     		}
    -		
    +
     		indexRun++;
     		displayObject = displayObject.__next;
        }
     }
     
    -/**
    +/**
      * Draws the batch to the frame buffer
    + *
      * @method render
    - */
    + */
     PIXI.WebGLBatch.prototype.render = function(start, end)
     {
    -	
    -//	console.log(start + " :: " + end + " : " + this.size);
     	start = start || 0;
    -	//end = end || this.size;
    -	if(end == undefined)end = this.size;
     
    +	if(end == undefined)end = this.size;
    +	
     	if(this.dirty)
     	{
     		this.refresh();
     		this.dirty = false;
    -		
     	}
    -	
    -	
    +
     	if (this.size == 0)return;
    -	
    +
     	this.update();
     	var gl = this.gl;
    +
    +	//TODO optimize this!
    +
    +	var shaderProgram = PIXI.defaultShader;
     	
    -	//TODO optimize this!
    -	
    -	var shaderProgram = PIXI.shaderProgram;
    -	gl.useProgram(shaderProgram);
    -	
    -	// update the verts..
    +	//gl.useProgram(shaderProgram);
    +
    +	// update the verts..
     	gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
    -	// ok..
    +	// ok..
     	gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verticies)
    -    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0);
    -	// update the uvs
    +    gl.vertexAttribPointer(shaderProgram.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
    +	// update the uvs
    +	//var isDefault = (shaderProgram == PIXI.shaderProgram)
    +
        	gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
     
         if(this.dirtyUVS)
    @@ -701,13 +720,13 @@ PIXI.WebGLBatch.prototype.render = function(start, end)
         	this.dirtyUVS = false;
         	gl.bufferSubData(gl.ARRAY_BUFFER,  0, this.uvs);
         }
    -    
    -    gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
    -	
    +
    +    gl.vertexAttribPointer(shaderProgram.aTextureCoord, 2, gl.FLOAT, false, 0, 0);
    +
         gl.activeTexture(gl.TEXTURE0);
         gl.bindTexture(gl.TEXTURE_2D, this.texture._glTexture);
    -	
    -	// update color!
    +
    +	// update color!
     	gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer);
     
     	if(this.dirtyColors)
    @@ -715,21 +734,17 @@ PIXI.WebGLBatch.prototype.render = function(start, end)
         	this.dirtyColors = false;
         	gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.colors);
     	}
    -	
    +
         gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0);
    -	
    -	// dont need to upload!
    +	// dont need to upload!
         gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
    -	
    -	
    -	//var startIndex = 0//1;
    +
     	var len = end - start;
    -	// console.log(this.size)
    -    // DRAW THAT this!
    +
    +    // DRAW THAT this!
         gl.drawElements(gl.TRIANGLES, len * 6, gl.UNSIGNED_SHORT, start * 2 * 6 );
     }
     
    -
         
    @@ -739,13 +754,13 @@ PIXI.WebGLBatch.prototype.render = function(start, end)
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_renderers_webgl_WebGLFilterManager.js.html b/docs/files/src_pixi_renderers_webgl_WebGLFilterManager.js.html new file mode 100644 index 0000000..d109a7c --- /dev/null +++ b/docs/files/src_pixi_renderers_webgl_WebGLFilterManager.js.html @@ -0,0 +1,708 @@ + + + + + src/pixi/renderers/webgl/WebGLFilterManager.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/renderers/webgl/WebGLFilterManager.js

    + +
    +
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
    +
    +
    +PIXI.WebGLFilterManager = function()
    +{
    +	this.filterStack = [];
    +	this.texturePool = [];
    +	
    +	this.offsetX = 0;
    +	this.offsetY = 0;
    +	
    +	this.initShaderBuffers();
    +}
    +
    +// API
    +
    +PIXI.WebGLFilterManager.prototype.begin = function(projection, buffer)
    +{
    +	this.width = projection.x * 2;
    +	this.height = -projection.y * 2;
    +	this.buffer = buffer;
    +}
    +
    +PIXI.WebGLFilterManager.prototype.pushFilter = function(filterBlock)
    +{
    +	var gl = PIXI.gl;
    +
    +	// filter program
    +	// OPTIMISATION - the first filter is free if its a simple color change?
    +	this.filterStack.push(filterBlock);
    +
    +	var filter = filterBlock.filterPasses[0];
    +
    +	
    +
    +	this.offsetX += filterBlock.target.filterArea.x;
    +	this.offsetY += filterBlock.target.filterArea.y;
    +	
    +	
    +	
    +	
    +	
    +	var texture = this.texturePool.pop();
    +	if(!texture)texture = new PIXI.FilterTexture(this.width, this.height);
    +	
    +	gl.bindTexture(gl.TEXTURE_2D,  texture.texture);
    +	
    +	this.getBounds(filterBlock.target);
    +		
    +	// addpadding?
    +	//displayObject.filterArea.x
    +
    +	var filterArea = filterBlock.target.filterArea;
    +
    +	var padidng = filter.padding;
    +	filterArea.x -= padidng;
    +	filterArea.y -= padidng;
    +	filterArea.width += padidng * 2;
    +	filterArea.height += padidng * 2;
    +
    +	// cap filter to screen size..
    +	if(filterArea.x < 0)filterArea.x = 0;	
    +	if(filterArea.width > this.width)filterArea.width = this.width;
    +	if(filterArea.y < 0)filterArea.y = 0;	
    +	if(filterArea.height > this.height)filterArea.height = this.height;
    +
    +
    +	//gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA,  filterArea.width, filterArea.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
    +	gl.bindFramebuffer(gl.FRAMEBUFFER, texture.frameBuffer);
    +   
    +  // console.log(filterArea)
    +	// set view port
    +	gl.viewport(0, 0, filterArea.width, filterArea.height);	
    +	
    +	PIXI.projection.x = filterArea.width/2;
    +	PIXI.projection.y = -filterArea.height/2;
    +	
    +	PIXI.offset.x = -filterArea.x; 
    +	PIXI.offset.y = -filterArea.y;
    +
    +	//console.log(PIXI.defaultShader.projectionVector)
    +	// update projection
    +	gl.uniform2f(PIXI.defaultShader.projectionVector, filterArea.width/2, -filterArea.height/2);
    +	gl.uniform2f(PIXI.defaultShader.offsetVector, -filterArea.x, -filterArea.y);
    +	//PIXI.primitiveProgram
    +
    +	gl.colorMask(true, true, true, true); 
    +	gl.clearColor(0,0,0, 0);     
    +	gl.clear(gl.COLOR_BUFFER_BIT);
    +	
    +	//filter.texture = texture;
    +	filterBlock._glFilterTexture = texture;
    +
    +	//console.log("PUSH")
    +}
    +
    +
    +PIXI.WebGLFilterManager.prototype.popFilter = function()
    +{
    +	
    +	var gl = PIXI.gl;
    +	
    +	var filterBlock = this.filterStack.pop();
    +
    +
    +
    +	var filterArea = filterBlock.target.filterArea;
    +
    +	var texture = filterBlock._glFilterTexture;
    +
    +	if(filterBlock.filterPasses.length > 1)
    +	{
    +		gl.viewport(0, 0, filterArea.width, filterArea.height);
    +
    +		gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
    +	
    +		this.vertexArray[0] = 0;
    +		this.vertexArray[1] = filterArea.height;
    +		
    +		this.vertexArray[2] = filterArea.width;
    +		this.vertexArray[3] = filterArea.height;
    +		
    +		this.vertexArray[4] = 0;
    +		this.vertexArray[5] = 0;
    +		
    +		this.vertexArray[6] = filterArea.width;
    +		this.vertexArray[7] = 0;
    +
    +
    +		gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray);
    +
    +	
    +		gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
    +		// nnow set the uvs..
    +		this.uvArray[2] = filterArea.width/this.width;
    +		this.uvArray[5] = filterArea.height/this.height;
    +		this.uvArray[6] = filterArea.width/this.width;
    +		this.uvArray[7] = filterArea.height/this.height;
    +		
    +		gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray);
    +
    +		var inputTexture = texture;
    +		var outputTexture = this.texturePool.pop();
    +		if(!outputTexture)outputTexture = new PIXI.FilterTexture(this.width, this.height);
    +		
    +		// need to clear this FBO as it may have some left over elements from a prvious filter.
    +		gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer );     
    +		gl.clear(gl.COLOR_BUFFER_BIT);
    +	 
    +		gl.disable(gl.BLEND);
    +		
    +		for (var i = 0; i < filterBlock.filterPasses.length-1; i++) 
    +		{
    +			var filterPass = filterBlock.filterPasses[i];
    +	
    +			gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer );
    +			
    +			// set texture
    +		    gl.activeTexture(gl.TEXTURE0);
    +			gl.bindTexture(gl.TEXTURE_2D, inputTexture.texture);
    +			
    +			// draw texture..
    +			//filterPass.applyFilterPass(filterArea.width, filterArea.height);
    +			this.applyFilterPass(filterPass, filterArea, filterArea.width, filterArea.height);
    +
    +			// swap the textures..
    +			var temp = inputTexture;
    +			inputTexture = outputTexture;
    +			outputTexture = temp;
    +			
    +		};
    +
    +		gl.enable(gl.BLEND);
    +
    +		texture = inputTexture;
    +		this.texturePool.push(outputTexture);
    +	}
    +
    +	var filter = filterBlock.filterPasses[filterBlock.filterPasses.length-1];
    +	
    +	this.offsetX -= filterArea.x;
    +	this.offsetY -= filterArea.y;
    +
    +	
    +	var sizeX = this.width;
    +	var sizeY = this.height;
    +	
    +	var offsetX = 0;
    +	var offsetY = 0;
    +	
    +	var buffer = this.buffer;
    +	
    +	// time to render the filters texture to the previous scene
    +	if(this.filterStack.length === 0)
    +	{
    +		gl.colorMask(true, true, true, this.buffer); 
    +	}
    +	else
    +	{
    +		var currentFilter = this.filterStack[this.filterStack.length-1];
    +		var filterArea = currentFilter.target.filterArea;
    +		
    +		sizeX = filterArea.width;
    +		sizeY = filterArea.height;
    +		
    +		offsetX = filterArea.x;
    +		offsetY = filterArea.y;
    +		
    +		buffer =  currentFilter._glFilterTexture.frameBuffer;
    +	}
    +	
    +	
    +
    +	// TODO need toremove thease global elements..
    +	PIXI.projection.x = sizeX/2;
    +	PIXI.projection.y = -sizeY/2;
    +
    +	PIXI.offset.x = offsetX;
    +	PIXI.offset.y = offsetY; 
    +	
    +
    +	var filterArea =  filterBlock.target.filterArea;
    +	var x = filterArea.x-offsetX;
    +	var y = filterArea.y-offsetY;
    +	
    +	// update the buffers..	
    +	// make sure to flip the y!
    +	gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
    +	
    +	this.vertexArray[0] = x;
    +	this.vertexArray[1] = y + filterArea.height;
    +	
    +	this.vertexArray[2] = x + filterArea.width;
    +	this.vertexArray[3] = y + filterArea.height;
    +	
    +	this.vertexArray[4] = x;
    +	this.vertexArray[5] = y;
    +	
    +	this.vertexArray[6] = x + filterArea.width;
    +	this.vertexArray[7] = y;
    +
    +	gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray);
    +	
    +	gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
    +
    +	this.uvArray[2] = filterArea.width/this.width;
    +	this.uvArray[5] = filterArea.height/this.height;
    +	this.uvArray[6] = filterArea.width/this.width;
    +	this.uvArray[7] = filterArea.height/this.height;
    +	
    +	gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray);
    +
    +	gl.viewport(0, 0, sizeX, sizeY);	
    +	// bind the buffer
    +	gl.bindFramebuffer(gl.FRAMEBUFFER, buffer );
    +	
    +	// set texture
    +    gl.activeTexture(gl.TEXTURE0);
    +	gl.bindTexture(gl.TEXTURE_2D, texture.texture);
    +	
    +	// apply!
    +	//filter.applyFilterPass(sizeX, sizeY);
    +	this.applyFilterPass(filter, filterArea, sizeX, sizeY);
    +
    +	// now restore the regular shader..
    +    gl.useProgram(PIXI.defaultShader.program);
    +	gl.uniform2f(PIXI.defaultShader.projectionVector, sizeX/2, -sizeY/2);
    +	gl.uniform2f(PIXI.defaultShader.offsetVector, -offsetX, -offsetY);
    +
    +	// return the texture to the pool
    +	this.texturePool.push(texture);
    +	filterBlock._glFilterTexture = null;	
    +}
    +
    +PIXI.WebGLFilterManager.prototype.applyFilterPass = function(filter, filterArea, width, height)
    +{
    +	// use program
    +	var gl = PIXI.gl;
    +
    +	if(!filter.shader)
    +	{
    +		var shader = new PIXI.PixiShader();
    +				
    +		shader.fragmentSrc = filter.fragmentSrc;
    +		shader.uniforms = filter.uniforms;
    +		shader.init();
    +		
    +		filter.shader = shader;
    +	}
    +
    +	var shader = filter.shader;
    +	
    +	// set the shader
    +	gl.useProgram(shader.program);
    +
    +	gl.uniform2f(shader.projectionVector, width/2, -height/2);
    +	gl.uniform2f(shader.offsetVector, 0,0)
    +
    +	if(filter.uniforms.dimensions)
    +	{
    +		//console.log(filter.uniforms.dimensions)
    +		filter.uniforms.dimensions.value[0] = this.width;//width;
    +		filter.uniforms.dimensions.value[1] = this.height;//height;
    +		filter.uniforms.dimensions.value[2] = this.vertexArray[0];
    +		filter.uniforms.dimensions.value[3] = this.vertexArray[5];//filterArea.height;
    +	//	console.log(this.vertexArray[5])
    +	}
    +
    +	shader.syncUniforms();
    +	
    +	gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
    +    gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
    +   
    +   	gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
    +    gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0);
    +	
    +    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
    +    
    +	// draw the filter...
    +    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
    +}
    +
    +PIXI.WebGLFilterManager.prototype.initShaderBuffers = function()
    +{
    +	var gl = PIXI.gl;
    +	
    +	// create some buffers
    +	this.vertexBuffer = gl.createBuffer();	
    +	this.uvBuffer = gl.createBuffer();
    +	this.indexBuffer = gl.createBuffer();
    +	
    +	// bind and upload the vertexs..
    +	// keep a refferance to the vertexFloatData..
    +	this.vertexArray = new Float32Array([0.0, 0.0, 
    +								         1.0, 0.0, 
    +								         0.0, 1.0, 
    +								         1.0, 1.0]);
    +	
    +	gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
    +	gl.bufferData(
    +    gl.ARRAY_BUFFER, 
    +    this.vertexArray, 
    +    gl.STATIC_DRAW);
    +    
    +    
    +    // bind and upload the uv buffer
    +	this.uvArray = new Float32Array([0.0, 0.0, 
    +								     1.0, 0.0, 
    +								     0.0, 1.0, 
    +								     1.0, 1.0]);
    +								         
    +	gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
    +	gl.bufferData(
    +    gl.ARRAY_BUFFER, 
    +    this.uvArray, 
    +    gl.STATIC_DRAW);
    +    
    +	// bind and upload the index
    +	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
    +	gl.bufferData(
    +    gl.ELEMENT_ARRAY_BUFFER, 
    +    new Uint16Array([0, 1, 2, 1, 3, 2]), 
    +    gl.STATIC_DRAW);
    +}
    +
    +PIXI.WebGLFilterManager.prototype.getBounds = function(displayObject)
    +{
    +	// time to get the width and height of the object!
    +	var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index, doTest;
    +	var a, b, c, d, tx, ty, x1, x2, x3, x4, y1, y2, y3, y4;
    +
    +	var tempObject = displayObject.first;
    +	var testObject = displayObject.last._iNext;
    +	
    +	var maxX = -Infinity;
    +	var maxY = -Infinity;
    +	
    +	var minX = Infinity;
    +	var minY = Infinity;
    +	
    +	do	
    +	{
    +		// TODO can be optimized! - what if there is no scale / rotation?
    +		
    +		if(tempObject.visible)
    +		{
    +			if(tempObject instanceof PIXI.Sprite)
    +			{
    +				width = tempObject.texture.frame.width;
    +				height = tempObject.texture.frame.height;
    +
    +				// TODO trim??
    +				aX = tempObject.anchor.x;
    +				aY = tempObject.anchor.y;
    +				w0 = width * (1-aX);
    +				w1 = width * -aX;
    +
    +				h0 = height * (1-aY);
    +				h1 = height * -aY;
    +
    +				doTest = true;
    +			}
    +			else if(tempObject instanceof PIXI.Graphics)
    +			{
    +				tempObject.updateFilterBounds();
    +
    +				var bounds = tempObject.bounds;
    +
    +				width = bounds.width;
    +				height = bounds.height;
    +
    +				w0 = bounds.x
    +				w1 = bounds.x + bounds.width;
    +
    +				h0 = bounds.y
    +				h1 = bounds.y + bounds.height;
    +
    +				doTest = true;	
    +			}
    +		}
    +		
    +		if(doTest)
    +		{
    +			worldTransform = tempObject.worldTransform;
    +
    +			a = worldTransform[0];
    +			b = worldTransform[3];
    +			c = worldTransform[1];
    +			d = worldTransform[4];
    +			tx = worldTransform[2];
    +			ty = worldTransform[5];
    +
    +			x1 = a * w1 + c * h1 + tx; 
    +			y1 = d * h1 + b * w1 + ty;
    +
    +			x2 = a * w0 + c * h1 + tx; 
    +			y2 = d * h1 + b * w0 + ty; 
    +
    +			x3 = a * w0 + c * h0 + tx; 
    +			y3 = d * h0 + b * w0 + ty; 
    +
    +			x4 =  a * w1 + c * h0 + tx; 
    +			y4 =  d * h0 + b * w1 + ty; 
    +
    +			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;
    +		}
    +
    +		doTest = false;
    +		tempObject = tempObject._iNext;
    +
    +	}
    +	while(tempObject != testObject)
    +	
    +	// maximum bounds is the size of the screen..
    +	//minX = minX > 0 ? minX : 0;
    +	//minY = minY > 0 ? minY : 0;
    +
    +	displayObject.filterArea.x = minX;
    +	displayObject.filterArea.y = minY;
    +
    +//	console.log(maxX+ " : " + minX)
    +	displayObject.filterArea.width = maxX - minX;
    +	displayObject.filterArea.height = maxY - minY;
    +}
    +
    +PIXI.FilterTexture = function(width, height)
    +{
    +	var gl = PIXI.gl;
    +	
    +    // next time to create a frame buffer and texture
    +	this.frameBuffer = gl.createFramebuffer();
    +    this.texture = gl.createTexture();
    +
    +    gl.bindTexture(gl.TEXTURE_2D,  this.texture);
    +    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    +	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    +	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    +	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    +	gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer );
    +	
    +	gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer );
    +	gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);
    +	
    +	this.resize(width, height);
    +}
    +
    +PIXI.FilterTexture.prototype.resize = function(width, height)
    +{
    +	this.width = width;
    +	this.height = height;
    +
    +	var gl = PIXI.gl;
    +
    +	gl.bindTexture(gl.TEXTURE_2D,  this.texture);
    +	gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA,  width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
    +	
    +}
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_renderers_webgl_WebGLGraphics.js.html b/docs/files/src_pixi_renderers_webgl_WebGLGraphics.js.html index 0240783..9279cb9 100644 --- a/docs/files/src_pixi_renderers_webgl_WebGLGraphics.js.html +++ b/docs/files/src_pixi_renderers_webgl_WebGLGraphics.js.html @@ -2,12 +2,12 @@ - src/pixi/renderers/webgl/WebGLGraphics.js - Pixi.JS - - - - - + src/pixi/renderers/webgl/WebGLGraphics.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,28 +166,35 @@
    -

    File: src/pixi/renderers/webgl/WebGLGraphics.js

    +

    File: src/pixi/renderers/webgl/WebGLGraphics.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -
    -
    -/**
    +/**
      * A set of functions used by the webGL renderer to draw the primitive graphics data
    - * @class CanvasGraphics 
    - */
    + *
    + * @class CanvasGraphics
    + */
     PIXI.WebGLGraphics = function()
     {
     	
     }
     
    +/**
    + * Renders the graphics object
    + *
    + * @static
    + * @private
    + * @method renderGraphics
    + * @param graphics {Graphics}
    + * @param projection {Object}
    + */
     PIXI.WebGLGraphics.renderGraphics = function(graphics, projection)
     {
    -	
     	var gl = PIXI.gl;
     	
     	if(!graphics._webGL)graphics._webGL = {points:[], indices:[], lastIndex:0, 
    @@ -187,42 +218,52 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection)
     		PIXI.WebGLGraphics.updateGraphics(graphics);
     	}
     	
    -	
     	PIXI.activatePrimitiveShader();
     	
    -	// This  could be speeded up fo sure!
    +	// This  could be speeded up fo sure!
     	var m = PIXI.mat3.clone(graphics.worldTransform);
     	
     	PIXI.mat3.transpose(m);
     	
    -	// set the matrix transform for the 
    +	// set the matrix transform for the 
      	gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
    +
    + 	gl.uniformMatrix3fv(PIXI.primitiveShader.translationMatrix, false, m);
      	
    - 	gl.uniformMatrix3fv(PIXI.primitiveProgram.translationMatrix, false, m);
    - 	
    -	gl.uniform2f(PIXI.primitiveProgram.projectionVector, projection.x, projection.y);
    +	gl.uniform2f(PIXI.primitiveShader.projectionVector, projection.x, -projection.y);
    +	gl.uniform2f(PIXI.primitiveShader.offsetVector, -PIXI.offset.x, -PIXI.offset.y);
     	
    -	gl.uniform1f(PIXI.primitiveProgram.alpha, graphics.worldAlpha);
    +	gl.uniform1f(PIXI.primitiveShader.alpha, graphics.worldAlpha);
     
     	gl.bindBuffer(gl.ARRAY_BUFFER, graphics._webGL.buffer);
     	
    -	// WHY DOES THIS LINE NEED TO BE THERE???
    -	gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0);
    -	// its not even used.. but need to be set or it breaks?
    -	// only on pc though..
    +	// WHY DOES THIS LINE NEED TO BE THERE???
    +	//gl.vertexAttribPointer(PIXI.shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0);
    +	// its not even used.. but need to be set or it breaks?
    +	// only on pc though..
     	
    -	gl.vertexAttribPointer(PIXI.primitiveProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 4 * 6, 0);
    -	gl.vertexAttribPointer(PIXI.primitiveProgram.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4);
    +	gl.vertexAttribPointer(PIXI.primitiveShader.aVertexPosition, 2, gl.FLOAT, false, 4 * 6, 0);
    +	gl.vertexAttribPointer(PIXI.primitiveShader.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4);
     	
    -	// set the index buffer!
    +	// set the index buffer!
     	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.indexBuffer);
     	
     	gl.drawElements(gl.TRIANGLE_STRIP,  graphics._webGL.indices.length, gl.UNSIGNED_SHORT, 0 );
     	
    -	// return to default shader...
    -	PIXI.activateDefaultShader();
    +	PIXI.deactivatePrimitiveShader();
    +	
    +	// return to default shader...
    +//	PIXI.activateShader(PIXI.defaultShader);
     }
     
    +/**
    + * Updates the graphics object
    + *
    + * @static
    + * @private
    + * @method updateGraphics
    + * @param graphics {Graphics}
    + */
     PIXI.WebGLGraphics.updateGraphics = function(graphics)
     {
     	for (var i=graphics._webGL.lastIndex; i < graphics.graphicsData.length; i++) 
    @@ -267,12 +308,20 @@ PIXI.WebGLGraphics.updateGraphics = function(graphics)
         gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, graphics._webGL.glIndicies, gl.STATIC_DRAW);
     }
     
    -
    +/**
    + * Builds a rectangle to draw
    + *
    + * @static
    + * @private
    + * @method buildRectangle
    + * @param graphics {Graphics}
    + * @param webGLData {Object}
    + */
     PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData)
     {
    -	// --- //
    -	// need to convert points to a nice regular data
    -	// 
    +	// --- //
    +	// need to convert points to a nice regular data
    +	// 
     	var rectData = graphicsData.points;
     	var x = rectData[0];
     	var y = rectData[1];
    @@ -292,9 +341,9 @@ PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData)
     		var verts = webGLData.points;
     		var indices = webGLData.indices;
     	
    -		var vertPos = verts.length/6;
    +		var vertPos = verts.length/6;
     		
    -		// start
    +		// start
     		verts.push(x, y);
     		verts.push(r, g, b, alpha);
     		
    @@ -307,7 +356,7 @@ PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData)
     		verts.push(x + width, y + height);
     		verts.push(r, g, b, alpha);
     		
    -		// insert 2 dead triangles..
    +		// insert 2 dead triangles..
     		indices.push(vertPos, vertPos, vertPos+1, vertPos+2, vertPos+3, vertPos+3)
     	}
     	
    @@ -324,11 +373,20 @@ PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData)
     	
     }
     
    +/**
    + * Builds a circle to draw
    + *
    + * @static
    + * @private
    + * @method buildCircle
    + * @param graphics {Graphics}
    + * @param webGLData {Object}
    + */
     PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData)
     {
    -	// --- //
    -	// need to convert points to a nice regular data
    -	// 
    +	// --- //
    +	// need to convert points to a nice regular data
    +	// 
     	var rectData = graphicsData.points;
     	var x = rectData[0];
     	var y = rectData[1];
    @@ -336,7 +394,7 @@ PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData)
     	var height = rectData[3];
     	
     	var totalSegs = 40;
    -	var seg = (Math.PI * 2) / totalSegs ;
    +	var seg = (Math.PI * 2) / totalSegs ;
     		
     	if(graphicsData.fill)
     	{
    @@ -350,7 +408,7 @@ PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData)
     		var verts = webGLData.points;
     		var indices = webGLData.indices;
     	
    -		var vecPos = verts.length/6;
    +		var vecPos = verts.length/6;
     		
     		indices.push(vecPos);
     		
    @@ -383,19 +441,28 @@ PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData)
     	
     }
     
    +/**
    + * Builds a line to draw
    + *
    + * @static
    + * @private
    + * @method buildLine
    + * @param graphics {Graphics}
    + * @param webGLData {Object}
    + */
     PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData)
     {
    -	// TODO OPTIMISE!
    +	// TODO OPTIMISE!
     	
     	var wrap = true;
     	var points = graphicsData.points;
     	if(points.length == 0)return;
     	
    -	// get first and last point.. figure out the middle!
    +	// get first and last point.. figure out the middle!
     	var firstPoint = new PIXI.Point( points[0], points[1] );
     	var lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] );
     	
    -	// if the first point is the last point - goona have issues :)
    +	// if the first point is the last point - goona have issues :)
     	if(firstPoint.x == lastPoint.x && firstPoint.y == lastPoint.y)
     	{
     		points.pop();
    @@ -412,14 +479,14 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData)
     	
     	var verts = webGLData.points;
     	var indices = webGLData.indices;
    -	var length = points.length / 2;
    +	var length = points.length / 2;
     	var indexCount = points.length;
    -	var indexStart = verts.length/6;
    +	var indexStart = verts.length/6;
     	
    -	// DRAW the Line
    -	var width = graphicsData.lineWidth / 2;
    +	// DRAW the Line
    +	var width = graphicsData.lineWidth / 2;
     	
    -	// sort color
    +	// sort color
     	var color = HEXtoRGB(graphicsData.lineColor);
     	var alpha = graphicsData.lineAlpha;
     	var r = color[0] * alpha;
    @@ -443,12 +510,12 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData)
     	
     	dist = Math.sqrt(perpx*perpx + perpy*perpy);
     	
    -	perpx /= dist;
    -	perpy /= dist;
    +	perpx /= dist;
    +	perpy /= dist;
     	perpx *= width;
     	perpy *= width;
     	
    -	// start
    +	// start
     	verts.push(p1x - perpx , p1y - perpy,
     				r, g, b, alpha);
     	
    @@ -470,8 +537,8 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData)
     		perpy = p1x - p2x;
     		
     		dist = Math.sqrt(perpx*perpx + perpy*perpy);
    -		perpx /= dist;
    -		perpy /= dist;
    +		perpx /= dist;
    +		perpy /= dist;
     		perpx *= width;
     		perpy *= width;
     
    @@ -479,8 +546,8 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData)
     		perp2y = p2x - p3x;
     		
     		dist = Math.sqrt(perp2x*perp2x + perp2y*perp2y);
    -		perp2x /= dist;
    -		perp2y /= dist;
    +		perp2x /= dist;
    +		perp2y /= dist;
     		perp2x *= width;
     		perp2y *= width;
     		
    @@ -497,8 +564,8 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData)
     	    	denom+=1;
     	    }
     	    
    -	    px = (b1*c2 - b2*c1)/denom;
    -	    py = (a2*c1 - a1*c2)/denom;
    +	    px = (b1*c2 - b2*c1)/denom;
    +	    py = (a2*c1 - a1*c2)/denom;
     		
     		pdist = (px -p2x) * (px -p2x) + (py -p2y) + (py -p2y);
     		
    @@ -508,8 +575,8 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData)
     			perp3y = perpy - perp2y;
     			
     			dist = Math.sqrt(perp3x*perp3x + perp3y*perp3y);
    -			perp3x /= dist;
    -			perp3y /= dist;
    +			perp3x /= dist;
    +			perp3y /= dist;
     			perp3x *= width;
     			perp3y *= width;
     			
    @@ -529,7 +596,7 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData)
     			verts.push(px , py);
     			verts.push(r, g, b, alpha);
     			
    -			verts.push(p2x - (px-p2x), p2y - (py - p2y));//, 4);
    +			verts.push(p2x - (px-p2x), p2y - (py - p2y));
     			verts.push(r, g, b, alpha);
     		}
     	}
    @@ -544,8 +611,8 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData)
     	perpy = p1x - p2x;
     	
     	dist = Math.sqrt(perpx*perpx + perpy*perpy);
    -	perpx /= dist;
    -	perpy /= dist;
    +	perpx /= dist;
    +	perpy /= dist;
     	perpx *= width;
     	perpy *= width;
     	
    @@ -565,19 +632,27 @@ PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData)
     	indices.push(indexStart-1);
     }
     
    -
    +/**
    + * Builds a polygon to draw
    + *
    + * @static
    + * @private
    + * @method buildPoly
    + * @param graphics {Graphics}
    + * @param webGLData {Object}
    + */
     PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData)
     {
     	var points = graphicsData.points;
     	if(points.length < 6)return;
     	
    -	// get first and last point.. figure out the middle!
    +	// get first and last point.. figure out the middle!
     	var verts = webGLData.points;
     	var indices = webGLData.indices;
     	
    -	var length = points.length / 2;
    +	var length = points.length / 2;
     	
    -	// sort color
    +	// sort color
     	var color = HEXtoRGB(graphicsData.fillColor);
     	var alpha = graphicsData.fillAlpha;
     	var r = color[0] * alpha;
    @@ -586,7 +661,7 @@ PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData)
     	
     	var triangles = PIXI.PolyK.Triangulate(points);
     	
    -	var vertPos = verts.length / 6;
    +	var vertPos = verts.length / 6;
     	
     	for (var i=0; i < triangles.length; i+=3) 
     	{
    @@ -605,7 +680,7 @@ PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData)
     }
     
     function HEXtoRGB(hex) {
    -	return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255];
    +	return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255];
     }
     
     
    @@ -621,13 +696,13 @@ function HEXtoRGB(hex) {
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_renderers_webgl_WebGLRenderGroup.js.html b/docs/files/src_pixi_renderers_webgl_WebGLRenderGroup.js.html index d73c577..59183b3 100644 --- a/docs/files/src_pixi_renderers_webgl_WebGLRenderGroup.js.html +++ b/docs/files/src_pixi_renderers_webgl_WebGLRenderGroup.js.html @@ -2,12 +2,12 @@ - src/pixi/renderers/webgl/WebGLRenderGroup.js - Pixi.JS - - - - - + src/pixi/renderers/webgl/WebGLRenderGroup.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,24 +166,27 @@
    -

    File: src/pixi/renderers/webgl/WebGLRenderGroup.js

    +

    File: src/pixi/renderers/webgl/WebGLRenderGroup.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -
    -
    -
    -/**
    +/**
      * A WebGLBatch Enables a group of sprites to be drawn using the same settings.
    - * if a group of sprites all have the same baseTexture and blendMode then they can be grouped into a batch. All the sprites in a batch can then be drawn in one go by the GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch even if the batch only contains one sprite. Batching is handled automatically by the webGL renderer. A good tip is: the smaller the number of batchs there are, the faster the webGL renderer will run. 
    + * if a group of sprites all have the same baseTexture and blendMode then they can be
    + * grouped into a batch. All the sprites in a batch can then be drawn in one go by the
    + * GPU which is hugely efficient. ALL sprites in the webGL renderer are added to a batch
    + * even if the batch only contains one sprite. Batching is handled automatically by the
    + * webGL renderer. A good tip is: the smaller the number of batchs there are, the faster
    + * the webGL renderer will run.
    + *
      * @class WebGLBatch
    - * @param an instance of the webGL context
    - * @return {PIXI.renderers.WebGLBatch} WebGLBatch {@link PIXI.renderers.WebGLBatch}
    - */
    + * @contructor
    + * @param gl {WebGLContext} An instance of the webGL context
    + */
     PIXI.WebGLRenderGroup = function(gl)
     {
     	this.gl = gl;
    @@ -168,106 +195,90 @@ PIXI.WebGLRenderGroup = function(gl)
     	this.backgroundColor;
     	this.batchs = [];
     	this.toRemove = [];
    +	
    +	this.filterManager = new PIXI.WebGLFilterManager();
     }
     
    -// constructor
    -PIXI.WebGLRenderGroup.constructor = PIXI.WebGLRenderGroup;
    +// constructor
    +PIXI.WebGLRenderGroup.prototype.constructor = PIXI.WebGLRenderGroup;
     
    +/**
    + * Add a display object to the webgl renderer
    + *
    + * @method setRenderable
    + * @param displayObject {DisplayObject}
    + * @private 
    + */
     PIXI.WebGLRenderGroup.prototype.setRenderable = function(displayObject)
     {
    -	// has this changed??
    +	// has this changed??
     	if(this.root)this.removeDisplayObjectAndChildren(this.root);
     	
     	displayObject.worldVisible = displayObject.visible;
     	
    -	// soooooo //
    -	// to check if any batchs exist already??
    +	// soooooo //
    +	// to check if any batchs exist already??
     	
    -	// TODO what if its already has an object? should remove it
    +	// TODO what if its already has an object? should remove it
     	this.root = displayObject;
     	this.addDisplayObjectAndChildren(displayObject);
     }
     
    -PIXI.WebGLRenderGroup.prototype.render = function(projection)
    +/**
    + * Renders the stage to its webgl view
    + *
    + * @method render
    + * @param projection {Object}
    + */
    +PIXI.WebGLRenderGroup.prototype.render = function(projection, buffer)
     {
     	PIXI.WebGLRenderer.updateTextures();
     	
     	var gl = this.gl;
    +	gl.uniform2f(PIXI.defaultShader.projectionVector, projection.x, projection.y);
     
    -	gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y);
    +	this.filterManager.begin(projection, buffer);
    +
    +	
     	gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
    -	
    -	// TODO remove this by replacing visible with getter setters..	
    -	this.checkVisibility(this.root, this.root.visible);
    -	
    -	// will render all the elements in the group
    +	// will render all the elements in the group
     	var renderable;
    -	
    -	
    +
     	for (var i=0; i < this.batchs.length; i++) 
     	{
    +		
     		renderable = this.batchs[i];
     		if(renderable instanceof PIXI.WebGLBatch)
     		{
     			this.batchs[i].render();
    +			continue;
     		}
    -		else if(renderable instanceof PIXI.TilingSprite)
    -		{
    -			if(renderable.visible)this.renderTilingSprite(renderable, projection);
    -		}
    -		else if(renderable instanceof PIXI.Strip)
    -		{
    -			if(renderable.visible)this.renderStrip(renderable, projection);
    -		}
    -		else if(renderable instanceof PIXI.Graphics)
    -		{
    -			if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix);
    -		}
    -		else if(renderable instanceof PIXI.FilterBlock)
    -		{
    -			/*
    -			 * for now only masks are supported..
    -			 */
    -			if(renderable.open)
    -			{
    -    			gl.enable(gl.STENCIL_TEST);
    -					
    -				gl.colorMask(false, false, false, false);
    -				gl.stencilFunc(gl.ALWAYS,1,0xff);
    -				gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE);
    -  
    -				PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection);
    -  					
    -				gl.colorMask(true, true, true, false);
    -				gl.stencilFunc(gl.NOTEQUAL,0,0xff);
    -				gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP);
    -			}
    -			else
    -			{
    -				gl.disable(gl.STENCIL_TEST);
    -			}
    -		}
    +		
    +		// render special
    +		this.renderSpecial(renderable, projection);
     	}
     	
     }
     
    -PIXI.WebGLRenderGroup.prototype.handleFilter = function(filter, projection)
    -{
    -	
    -}
    -
    -PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection)
    +/**
    + * Renders a specific displayObject
    + *
    + * @method renderSpecific
    + * @param displayObject {DisplayObject}
    + * @param projection {Object}
    + * @private
    + */
    +PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection, buffer)
     {
     	PIXI.WebGLRenderer.updateTextures();
    -	
     	var gl = this.gl;
    -	this.checkVisibility(displayObject, displayObject.visible);
    -	
    -//	gl.uniformMatrix4fv(PIXI.shaderProgram.mvMatrixUniform, false, projectionMatrix);
    -	gl.uniform2f(PIXI.shaderProgram.projectionVector, projection.x, projection.y);
     
    -	// to do!
    -	// render part of the scene...
    +	gl.uniform2f(PIXI.defaultShader.projectionVector, projection.x, projection.y);
    +
    +	this.filterManager.begin(projection, buffer);
    +
    +	// to do!
    +	// render part of the scene...
     	
     	var startIndex;
     	var startBatchIndex;
    @@ -275,20 +286,22 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project
     	var endIndex;
     	var endBatchIndex;
     	
    -	/*
    +	/*
     	 *  LOOK FOR THE NEXT SPRITE
     	 *  This part looks for the closest next sprite that can go into a batch
     	 *  it keeps looking until it finds a sprite or gets to the end of the display
     	 *  scene graph
    -	 */
    -	var nextRenderable = displayObject.last;
    +	 */
    +	var nextRenderable = displayObject.first;
     	while(nextRenderable._iNext)
     	{
    -		nextRenderable = nextRenderable._iNext;
     		if(nextRenderable.renderable && nextRenderable.__renderGroup)break;
    +		nextRenderable = nextRenderable._iNext;
     	}
     	var startBatch = nextRenderable.batch;
    +	//console.log(nextRenderable);
     	
    +	//console.log(renderable)
     	if(nextRenderable instanceof PIXI.Sprite)
     	{
     		startBatch = nextRenderable.batch;
    @@ -296,7 +309,7 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project
     		var head = startBatch.head;
     		var next = head;
     		
    -		// ok now we have the batch.. need to find the start index!
    +		// ok now we have the batch.. need to find the start index!
     		if(head == nextRenderable)
     		{
     			startIndex = 0;
    @@ -317,14 +330,12 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project
     		startBatch = nextRenderable;
     	}
     	
    -	// Get the LAST renderable object
    -	var lastRenderable = displayObject;
    -	var endBatch;
    -	var lastItem = displayObject;
    -	while(lastItem.children.length > 0)
    +	// Get the LAST renderable object
    +	var lastRenderable = displayObject.last;
    +	while(lastRenderable._iPrev)
     	{
    -		lastItem = lastItem.children[lastItem.children.length-1];
    -		if(lastItem.renderable)lastRenderable = lastItem;
    +		if(lastRenderable.renderable && lastRenderable.__renderGroup)break;
    +		lastRenderable = lastRenderable._iNext;
     	}
     	
     	if(lastRenderable instanceof PIXI.Sprite)
    @@ -353,7 +364,8 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project
     		endBatch = lastRenderable;
     	}
     	
    -	// TODO - need to fold this up a bit!
    +	//console.log(endBatch);
    +	// TODO - need to fold this up a bit!
     	
     	if(startBatch == endBatch)
     	{
    @@ -363,26 +375,26 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project
     		}
     		else
     		{
    -			this.renderSpecial(startBatch);
    +			this.renderSpecial(startBatch, projection);
     		}
     		return;
     	}
     	
    -	// now we have first and last!
    +	// now we have first and last!
     	startBatchIndex = this.batchs.indexOf(startBatch);
     	endBatchIndex = this.batchs.indexOf(endBatch);
     	
    -	// DO the first batch
    +	// DO the first batch
     	if(startBatch instanceof PIXI.WebGLBatch)
     	{
     		startBatch.render(startIndex);
     	}
     	else
     	{
    -		this.renderSpecial(startBatch);
    +		this.renderSpecial(startBatch, projection);
     	}
     	
    -	// DO the middle batchs..
    +	// DO the middle batchs..
     	for (var i=startBatchIndex+1; i < endBatchIndex; i++) 
     	{
     		renderable = this.batchs[i];
    @@ -393,58 +405,97 @@ PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, project
     		}
     		else
     		{
    -			this.renderSpecial(renderable);
    +			this.renderSpecial(renderable, projection);
     		}
     	}
     	
    -	// DO the last batch..
    +	// DO the last batch..
     	if(endBatch instanceof PIXI.WebGLBatch)
     	{
     		endBatch.render(0, endIndex+1);
     	}
     	else
     	{
    -		this.renderSpecial(endBatch);
    +		this.renderSpecial(endBatch, projection);
     	}
     }
     
    -PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable)
    +/**
    + * Renders a specific renderable
    + *
    + * @method renderSpecial
    + * @param renderable {DisplayObject}
    + * @param projection {Object}
    + * @private
    + */
    +PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection)
     {
    +	
    +	var worldVisible = renderable.vcount === PIXI.visibleCount
    +
    +
     	if(renderable instanceof PIXI.TilingSprite)
     	{
    -		if(renderable.visible)this.renderTilingSprite(renderable, projectionMatrix);
    +		if(worldVisible)this.renderTilingSprite(renderable, projection);
     	}
     	else if(renderable instanceof PIXI.Strip)
     	{
    -		if(renderable.visible)this.renderStrip(renderable, projectionMatrix);
    +		if(worldVisible)this.renderStrip(renderable, projection);
     	}
     	else if(renderable instanceof PIXI.CustomRenderable)
     	{
    -		if(renderable.visible) renderable.renderWebGL(this, projectionMatrix);
    +		if(worldVisible) renderable.renderWebGL(this, projection);
     	}
     	else if(renderable instanceof PIXI.Graphics)
     	{
    -		if(renderable.visible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable);//, projectionMatrix);
    +		if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);
     	}
     	else if(renderable instanceof PIXI.FilterBlock)
     	{
    -		/*
    -		 * for now only masks are supported..
    -		 */
    -		if(renderable.open)
    +		this.handleFilterBlock(renderable, projection);
    +	}
    +}
    +
    +PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(filterBlock, projection)
    +{
    +	/*
    +	 * for now only masks are supported..
    +	 */
    +	var gl = PIXI.gl;
    +	
    +	if(filterBlock.open)
    +	{
    +		if(filterBlock.data instanceof Array)
     		{
    +			//var filter = filterBlock.data[0];
    +			//console.log(filter)
    +			this.filterManager.pushFilter(filterBlock);//filter);
    +			// ok so..
    +			
    +		}
    +		else
    +		{
    +			
     			gl.enable(gl.STENCIL_TEST);
     				
     			gl.colorMask(false, false, false, false);
     			gl.stencilFunc(gl.ALWAYS,1,0xff);
     			gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE);
    -  
    -			PIXI.WebGLGraphics.renderGraphics(renderable.mask, projection);
    +			PIXI.WebGLGraphics.renderGraphics(filterBlock.data, projection);
     				
    -			gl.colorMask(true, true, true, false);
    +			gl.colorMask(true, true, true, true);
     			gl.stencilFunc(gl.NOTEQUAL,0,0xff);
     			gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP);
     		}
    +	}
    +	else
    +	{
    +		if(filterBlock.data instanceof Array)
    +		{
    +			this.filterManager.popFilter();
    +		//	PIXI.popShader();
    +		//	gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y);
    +		}
     		else
     		{
     			gl.disable(gl.STENCIL_TEST);
    @@ -452,46 +503,25 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable)
     	}
     }
     
    -PIXI.WebGLRenderGroup.prototype.checkVisibility = function(displayObject, globalVisible)
    -{
    -	// give the dp a reference to its renderGroup...
    -	var children = displayObject.children;
    -	//displayObject.worldVisible = globalVisible;
    -	for (var i=0; i < children.length; i++) 
    -	{
    -		var child = children[i];
    -		
    -		// TODO optimize... should'nt need to loop through everything all the time
    -		child.worldVisible = child.visible && globalVisible;
    -		
    -		// everything should have a batch!
    -		// time to see whats new!
    -		if(child.textureChange)
    -		{
    -			child.textureChange = false;
    -			if(child.worldVisible)this.updateTexture(child);
    -			// update texture!!
    -		}
    -		
    -		if(child.children.length > 0)
    -		{
    -			this.checkVisibility(child, child.worldVisible);
    -		}
    -	};
    -}
    -
    +/**
    + * Updates a webgl texture
    + *
    + * @method updateTexture
    + * @param displayObject {DisplayObject}
    + * @private
    + */
     PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject)
     {
     	
    -	// TODO definitely can optimse this function..
    +	// TODO definitely can optimse this function..
     	
     	this.removeObject(displayObject);
     	
    -	/*
    +	/*
     	 *  LOOK FOR THE PREVIOUS RENDERABLE
     	 *  This part looks for the closest previous sprite that can go into a batch
     	 *  It keeps going back until it finds a sprite or the stage
    -	 */
    +	 */
     	var previousRenderable = displayObject.first;
     	while(previousRenderable != this.root)
     	{
    @@ -499,12 +529,12 @@ PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject)
     		if(previousRenderable.renderable && previousRenderable.__renderGroup)break;
     	}
     	
    -	/*
    +	/*
     	 *  LOOK FOR THE NEXT SPRITE
     	 *  This part looks for the closest next sprite that can go into a batch
     	 *  it keeps looking until it finds a sprite or gets to the end of the display
     	 *  scene graph
    -	 */
    +	 */
     	var nextRenderable = displayObject.last;
     	while(nextRenderable._iNext)
     	{
    @@ -515,31 +545,39 @@ PIXI.WebGLRenderGroup.prototype.updateTexture = function(displayObject)
     	this.insertObject(displayObject, previousRenderable, nextRenderable);
     }
     
    +/**
    + * Adds filter blocks
    + *
    + * @method addFilterBlocks
    + * @param start {FilterBlock}
    + * @param end {FilterBlock}
    + * @private
    + */
     PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end)
     {
     	start.__renderGroup = this;
     	end.__renderGroup = this;
    -	/*
    +	/*
     	 *  LOOK FOR THE PREVIOUS RENDERABLE
     	 *  This part looks for the closest previous sprite that can go into a batch
     	 *  It keeps going back until it finds a sprite or the stage
    -	 */
    +	 */
     	var previousRenderable = start;
    -	while(previousRenderable != this.root)
    +	while(previousRenderable != this.root.first)
     	{
     		previousRenderable = previousRenderable._iPrev;
     		if(previousRenderable.renderable && previousRenderable.__renderGroup)break;
     	}
     	this.insertAfter(start, previousRenderable);
     		
    -	/*
    +	/*
     	 *  LOOK FOR THE NEXT SPRITE
     	 *  This part looks for the closest next sprite that can go into a batch
     	 *  it keeps looking until it finds a sprite or gets to the end of the display
     	 *  scene graph
    -	 */
    +	 */
     	var previousRenderable2 = end;
    -	while(previousRenderable2 != this.root)
    +	while(previousRenderable2 != this.root.first)
     	{
     		previousRenderable2 = previousRenderable2._iPrev;
     		if(previousRenderable2.renderable && previousRenderable2.__renderGroup)break;
    @@ -547,35 +585,50 @@ PIXI.WebGLRenderGroup.prototype.addFilterBlocks = function(start, end)
     	this.insertAfter(end, previousRenderable2);
     }
     
    +/**
    + * Remove filter blocks
    + *
    + * @method removeFilterBlocks
    + * @param start {FilterBlock}
    + * @param end {FilterBlock}
    + * @private
    + */
     PIXI.WebGLRenderGroup.prototype.removeFilterBlocks = function(start, end)
     {
     	this.removeObject(start);
     	this.removeObject(end);
     }
     
    +/**
    + * Adds a display object and children to the webgl context
    + *
    + * @method addDisplayObjectAndChildren
    + * @param displayObject {DisplayObject}
    + * @private
    + */
     PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayObject)
     {
     	if(displayObject.__renderGroup)displayObject.__renderGroup.removeDisplayObjectAndChildren(displayObject);
     	
    -	/*
    +	/*
     	 *  LOOK FOR THE PREVIOUS RENDERABLE
     	 *  This part looks for the closest previous sprite that can go into a batch
     	 *  It keeps going back until it finds a sprite or the stage
    -	 */
    +	 */
     	
     	var previousRenderable = displayObject.first;
    -	while(previousRenderable != this.root)
    +	while(previousRenderable != this.root.first)
     	{
     		previousRenderable = previousRenderable._iPrev;
     		if(previousRenderable.renderable && previousRenderable.__renderGroup)break;
     	}
     	
    -	/*
    +	/*
     	 *  LOOK FOR THE NEXT SPRITE
     	 *  This part looks for the closest next sprite that can go into a batch
     	 *  it keeps looking until it finds a sprite or gets to the end of the display
     	 *  scene graph
    -	 */
    +	 */
     	var nextRenderable = displayObject.last;
     	while(nextRenderable._iNext)
     	{
    @@ -583,7 +636,7 @@ PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayOb
     		if(nextRenderable.renderable && nextRenderable.__renderGroup)break;
     	}
     	
    -	// one the display object hits this. we can break the loop	
    +	// one the display object hits this. we can break the loop	
     	
     	var tempObject = displayObject.first;
     	var testObject = displayObject.last._iNext;
    @@ -603,11 +656,18 @@ PIXI.WebGLRenderGroup.prototype.addDisplayObjectAndChildren = function(displayOb
     	while(tempObject != testObject)
     }
     
    +/**
    + * Removes a display object and children to the webgl context
    + *
    + * @method removeDisplayObjectAndChildren
    + * @param displayObject {DisplayObject}
    + * @private
    + */
     PIXI.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren = function(displayObject)
     {
     	if(displayObject.__renderGroup != this)return;
     	
    -//	var displayObject = displayObject.first;
    +//	var displayObject = displayObject.first;
     	var lastObject = displayObject.last;
     	do	
     	{
    @@ -618,18 +678,25 @@ PIXI.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren = function(displa
     	while(displayObject)
     }
     
    -	
    -
    +/**
    + * Inserts a displayObject into the linked list
    + *
    + * @method insertObject
    + * @param displayObject {DisplayObject}
    + * @param previousObject {DisplayObject}
    + * @param nextObject {DisplayObject}
    + * @private
    + */
     PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousObject, nextObject)
     {
    -	// while looping below THE OBJECT MAY NOT HAVE BEEN ADDED
    +	// while looping below THE OBJECT MAY NOT HAVE BEEN ADDED
     	var previousSprite = previousObject;
     	var nextSprite = nextObject;
     	
    -	/*
    +	/*
     	 * so now we have the next renderable and the previous renderable
     	 * 
    -	 */
    +	 */
     	if(displayObject instanceof PIXI.Sprite)
     	{
     		var previousBatch
    @@ -649,7 +716,7 @@ PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousO
     		}
     		else
     		{
    -			// TODO reword!
    +			// TODO reword!
     			previousBatch = previousSprite;
     		}
     	
    @@ -659,7 +726,7 @@ PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousO
     			{
     				nextBatch = nextSprite.batch;
     			
    -				//batch may not exist if item was added to the display list but not to the webGL
    +				//batch may not exist if item was added to the display list but not to the webGL
     				if(nextBatch)
     				{
     					if(nextBatch.texture == displayObject.texture.baseTexture && nextBatch.blendMode == displayObject.blendMode)
    @@ -671,15 +738,15 @@ PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousO
     					{
     						if(nextBatch == previousBatch)
     						{
    -							// THERE IS A SPLIT IN THIS BATCH! //
    +							// THERE IS A SPLIT IN THIS BATCH! //
     							var splitBatch = previousBatch.split(nextSprite);
    -							// COOL!
    -							// add it back into the array	
    -							/*
    +							// COOL!
    +							// add it back into the array	
    +							/*
     							 * OOPS!
     							 * seems the new sprite is in the middle of a batch
     							 * lets split it.. 
    -							 */
    +							 */
     							var batch = PIXI.WebGLRenderer.getBatch();
     
     							var index = this.batchs.indexOf( previousBatch );
    @@ -693,22 +760,22 @@ PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousO
     			}
     			else
     			{
    -				// TODO re-word!
    +				// TODO re-word!
     				
     				nextBatch = nextSprite;
     			}
     		}
     		
    -		/*
    +		/*
     		 * looks like it does not belong to any batch!
     		 * but is also not intersecting one..
     		 * time to create anew one!
    -		 */
    +		 */
     		
     		var batch =  PIXI.WebGLRenderer.getBatch();
     		batch.init(displayObject);
     
    -		if(previousBatch) // if this is invalid it means 
    +		if(previousBatch) // if this is invalid it means 
     		{
     			var index = this.batchs.indexOf( previousBatch );
     			this.batchs.splice(index+1, 0, batch);
    @@ -723,34 +790,40 @@ PIXI.WebGLRenderGroup.prototype.insertObject = function(displayObject, previousO
     	else if(displayObject instanceof PIXI.TilingSprite)
     	{
     		
    -		// add to a batch!!
    +		// add to a batch!!
     		this.initTilingSprite(displayObject);
    -	//	this.batchs.push(displayObject);
    +	//	this.batchs.push(displayObject);
     		
     	}
     	else if(displayObject instanceof PIXI.Strip)
     	{
    -		// add to a batch!!
    +		// add to a batch!!
     		this.initStrip(displayObject);
    -	//	this.batchs.push(displayObject);
    +	//	this.batchs.push(displayObject);
     	}
    -	else if(displayObject)// instanceof PIXI.Graphics)
    +	else if(displayObject)// instanceof PIXI.Graphics)
     	{
    -		//displayObject.initWebGL(this);
    +		//displayObject.initWebGL(this);
     		
    -		// add to a batch!!
    -		//this.initStrip(displayObject);
    -		//this.batchs.push(displayObject);
    +		// add to a batch!!
    +		//this.initStrip(displayObject);
    +		//this.batchs.push(displayObject);
     	}
     	
     	this.insertAfter(displayObject, previousSprite);
     			
    -	// insert and SPLIT!
    +	// insert and SPLIT!
     
     }
     
    -				
    -			
    +/**
    + * Inserts a displayObject into the linked list
    + *
    + * @method insertAfter
    + * @param item {DisplayObject}
    + * @param displayObject {DisplayObject} The object to insert
    + * @private
    + */
     PIXI.WebGLRenderGroup.prototype.insertAfter = function(item, displayObject)
     {
     	if(displayObject instanceof PIXI.Sprite)
    @@ -759,29 +832,29 @@ PIXI.WebGLRenderGroup.prototype.insertAfter = function(item, displayObject)
     		
     		if(previousBatch)
     		{
    -			// so this object is in a batch!
    +			// so this object is in a batch!
     			
    -			// is it not? need to split the batch
    +			// is it not? need to split the batch
     			if(previousBatch.tail == displayObject)
     			{
    -				// is it tail? insert in to batchs	
    +				// is it tail? insert in to batchs	
     				var index = this.batchs.indexOf( previousBatch );
     				this.batchs.splice(index+1, 0, item);
     			}
     			else
     			{
    -				// TODO MODIFY ADD / REMOVE CHILD TO ACCOUNT FOR FILTERS (also get prev and next) //
    +				// TODO MODIFY ADD / REMOVE CHILD TO ACCOUNT FOR FILTERS (also get prev and next) //
     				
    -				// THERE IS A SPLIT IN THIS BATCH! //
    +				// THERE IS A SPLIT IN THIS BATCH! //
     				var splitBatch = previousBatch.split(displayObject.__next);
     				
    -				// COOL!
    -				// add it back into the array	
    -				/*
    +				// COOL!
    +				// add it back into the array	
    +				/*
     				 * OOPS!
     				 * seems the new sprite is in the middle of a batch
     				 * lets split it.. 
    -				 */
    +				 */
     				var index = this.batchs.indexOf( previousBatch );
     				this.batchs.splice(index+1, 0, item, splitBatch);
     			}
    @@ -798,26 +871,33 @@ PIXI.WebGLRenderGroup.prototype.insertAfter = function(item, displayObject)
     	}
     }
     
    +/**
    + * Removes a displayObject from the linked list
    + *
    + * @method removeObject
    + * @param displayObject {DisplayObject} The object to remove
    + * @private
    + */
     PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject)
     {
    -	// loop through children..
    -	// display object //
    +	// loop through children..
    +	// display object //
     	
    -	// add a child from the render group..
    -	// remove it and all its children!
    -	//displayObject.cacheVisible = false;//displayObject.visible;
    +	// add a child from the render group..
    +	// remove it and all its children!
    +	//displayObject.cacheVisible = false;//displayObject.visible;
     
    -	/*
    +	/*
     	 * removing is a lot quicker..
     	 * 
    -	 */
    +	 */
     	var batchToRemove;
     	
     	if(displayObject instanceof PIXI.Sprite)
     	{
    -		// should always have a batch!
    +		// should always have a batch!
     		var batch = displayObject.batch;
    -		if(!batch)return; // this means the display list has been altered befre rendering
    +		if(!batch)return; // this means the display list has been altered befre rendering
     		
     		batch.remove(displayObject);
     		
    @@ -831,19 +911,19 @@ PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject)
     		batchToRemove = displayObject;
     	}
     	
    -	/*
    +	/*
     	 * Looks like there is somthing that needs removing!
    -	 */
    +	 */
     	if(batchToRemove)	
     	{
     		var index = this.batchs.indexOf( batchToRemove );
    -		if(index == -1)return;// this means it was added then removed before rendered
    +		if(index == -1)return;// this means it was added then removed before rendered
     		
    -		// ok so.. check to see if you adjacent batchs should be joined.
    -		// TODO may optimise?
    +		// ok so.. check to see if you adjacent batchs should be joined.
    +		// TODO may optimise?
     		if(index == 0 || index == this.batchs.length-1)
     		{
    -			// wha - eva! just get of the empty batch!
    +			// wha - eva! just get of the empty batch!
     			this.batchs.splice(index, 1);
     			if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove);
     		
    @@ -854,7 +934,7 @@ PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject)
     		{
     			if(this.batchs[index-1].texture == this.batchs[index+1].texture && this.batchs[index-1].blendMode == this.batchs[index+1].blendMode)
     			{
    -				//console.log("MERGE")
    +				//console.log("MERGE")
     				this.batchs[index-1].merge(this.batchs[index+1]);
     				
     				if(batchToRemove instanceof PIXI.WebGLBatch)PIXI.WebGLRenderer.returnBatch(batchToRemove);
    @@ -870,21 +950,18 @@ PIXI.WebGLRenderGroup.prototype.removeObject = function(displayObject)
     }
     
     
    -/**
    +/**
    + * Initializes a tiling sprite
    + *
    + * @method initTilingSprite
    + * @param sprite {TilingSprite} The tiling sprite to initialize
      * @private
    - */
    -
    -
    -
    -
    -/**
    - * @private
    - */
    + */
     PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite)
     {
     	var gl = this.gl;
     
    -	// make the texture tilable..
    +	// make the texture tilable..
     			
     	sprite.verticies = new Float32Array([0, 0,
     										  sprite.width, 0,
    @@ -898,7 +975,7 @@ PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite)
     				
     	sprite.colors = new Float32Array([1,1,1,1]);
     	
    -	sprite.indices =  new Uint16Array([0, 1, 3,2])//, 2]);
    +	sprite.indices =  new Uint16Array([0, 1, 3,2])//, 2]);
     	
     	sprite._vertexBuffer = gl.createBuffer();
     	sprite._indexBuffer = gl.createBuffer();
    @@ -917,7 +994,7 @@ PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite)
         gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sprite._indexBuffer);
         gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sprite.indices, gl.STATIC_DRAW);
         
    -//    return ( (x > 0) && ((x & (x - 1)) == 0) );
    +//    return ( (x > 0) && ((x & (x - 1)) == 0) );
     
     	if(sprite.texture.baseTexture._glTexture)
     	{
    @@ -932,31 +1009,37 @@ PIXI.WebGLRenderGroup.prototype.initTilingSprite = function(sprite)
     	}
     }
     
    -/**
    +/**
    + * Renders a Strip
    + *
    + * @method renderStrip
    + * @param strip {Strip} The strip to render
    + * @param projection {Object}
      * @private
    - */
    + */
     PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection)
     {
     	var gl = this.gl;
    -	var shaderProgram = PIXI.shaderProgram;
    -//	mat
    -	//var mat4Real = PIXI.mat3.toMat4(strip.worldTransform);
    -	//PIXI.mat4.transpose(mat4Real);
    -	//PIXI.mat4.multiply(projectionMatrix, mat4Real, mat4Real )
     
    +	PIXI.activateStripShader();
    +
    +	var shader = PIXI.stripShader;
    +
    +	var program = shader.program;
     	
    -	gl.useProgram(PIXI.stripShaderProgram);
    -
     	var m = PIXI.mat3.clone(strip.worldTransform);
     	
     	PIXI.mat3.transpose(m);
     	
    -	// set the matrix transform for the 
    - 	gl.uniformMatrix3fv(PIXI.stripShaderProgram.translationMatrix, false, m);
    -	gl.uniform2f(PIXI.stripShaderProgram.projectionVector, projection.x, projection.y);
    -	gl.uniform1f(PIXI.stripShaderProgram.alpha, strip.worldAlpha);
    +//	console.log(projection)
    +	// set the matrix transform for the 
    + 	gl.uniformMatrix3fv(shader.translationMatrix, false, m);
    +	gl.uniform2f(shader.projectionVector, projection.x, projection.y);
    +	gl.uniform2f(shader.offsetVector, -PIXI.offset.x, -PIXI.offset.y);
    +	
    +	gl.uniform1f(shader.alpha, strip.worldAlpha);
     
    -/*
    +	/*
     	if(strip.blendMode == PIXI.blendModes.NORMAL)
     	{
     		gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
    @@ -965,27 +1048,26 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection)
     	{
     		gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR);
     	}
    -	*/
    -	
    +	*/
     	
    +	//console.log("!!")
     	if(!strip.dirty)
    -	{
    -		
    +	{	
     		gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer);
     		gl.bufferSubData(gl.ARRAY_BUFFER, 0, strip.verticies)
    -	    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0);
    +	    gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
     		
    -		// update the uvs
    +		// update the uvs
     	   	gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer);
    -	    gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
    +	    gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0);
     			
     	    gl.activeTexture(gl.TEXTURE0);
     	    gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture);
     		
     		gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer);
    -	    gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0);
    +	    gl.vertexAttribPointer(shader.colorAttribute, 1, gl.FLOAT, false, 0, 0);
     		
    -		// dont need to upload!
    +		// dont need to upload!
     	    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer);
     	}
     	else
    @@ -993,49 +1075,55 @@ PIXI.WebGLRenderGroup.prototype.renderStrip = function(strip, projection)
     		strip.dirty = false;
     		gl.bindBuffer(gl.ARRAY_BUFFER, strip._vertexBuffer);
     		gl.bufferData(gl.ARRAY_BUFFER, strip.verticies, gl.STATIC_DRAW)
    -	    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0);
    +	    gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
     		
    -		// update the uvs
    +		// update the uvs
     	   	gl.bindBuffer(gl.ARRAY_BUFFER, strip._uvBuffer);
     	   	gl.bufferData(gl.ARRAY_BUFFER, strip.uvs, gl.STATIC_DRAW)
    -	    gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
    +	    gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0);
     			
     	    gl.activeTexture(gl.TEXTURE0);
     	    gl.bindTexture(gl.TEXTURE_2D, strip.texture.baseTexture._glTexture);
    -		
    +	//	console.log(strip.texture.baseTexture._glTexture)
     		gl.bindBuffer(gl.ARRAY_BUFFER, strip._colorBuffer);
     		gl.bufferData(gl.ARRAY_BUFFER, strip.colors, gl.STATIC_DRAW)
    -	    gl.vertexAttribPointer(shaderProgram.colorAttribute, 1, gl.FLOAT, false, 0, 0);
    +	    gl.vertexAttribPointer(shader.colorAttribute, 1, gl.FLOAT, false, 0, 0);
     		
    -		// dont need to upload!
    +		// dont need to upload!
     	    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, strip._indexBuffer);
     	    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, strip.indices, gl.STATIC_DRAW);
     	    
     	}
    -	//console.log(gl.TRIANGLE_STRIP);
     	
     	gl.drawElements(gl.TRIANGLE_STRIP, strip.indices.length, gl.UNSIGNED_SHORT, 0);
         
    -  	gl.useProgram(PIXI.shaderProgram);
    +    PIXI.deactivateStripShader();
    +  	//gl.useProgram(PIXI.currentProgram);
     }
     
    -
    -/**
    +/**
    + * Renders a TilingSprite
    + *
    + * @method renderTilingSprite
    + * @param sprite {TilingSprite} The tiling sprite to render
    + * @param projectionMatrix {Object}
      * @private
    - */
    + */
     PIXI.WebGLRenderGroup.prototype.renderTilingSprite = function(sprite, projectionMatrix)
     {
     	var gl = this.gl;
    +
    +
     	var shaderProgram = PIXI.shaderProgram;
     	
     	var tilePosition = sprite.tilePosition;
     	var tileScale = sprite.tileScale;
     	
    -	var offsetX =  tilePosition.x/sprite.texture.baseTexture.width;
    -	var offsetY =  tilePosition.y/sprite.texture.baseTexture.height;
    +	var offsetX =  tilePosition.x/sprite.texture.baseTexture.width;
    +	var offsetY =  tilePosition.y/sprite.texture.baseTexture.height;
     	
    -	var scaleX =  (sprite.width / sprite.texture.baseTexture.width)  / tileScale.x;
    -	var scaleY =  (sprite.height / sprite.texture.baseTexture.height) / tileScale.y;
    +	var scaleX =  (sprite.width / sprite.texture.baseTexture.width)  / tileScale.x;
    +	var scaleY =  (sprite.height / sprite.texture.baseTexture.height) / tileScale.y;
     
     	sprite.uvs[0] = 0 - offsetX;
     	sprite.uvs[1] = 0 - offsetY;
    @@ -1055,14 +1143,16 @@ PIXI.WebGLRenderGroup.prototype.renderTilingSprite = function(sprite, projection
     	this.renderStrip(sprite, projectionMatrix);
     }
     
    -
    -
    -/**
    +/**
    + * Initializes a strip to be rendered
    + *
    + * @method initStrip
    + * @param strip {Strip} The strip to initialize
      * @private
    - */
    + */
     PIXI.WebGLRenderGroup.prototype.initStrip = function(strip)
     {
    -	// build the strip!
    +	// build the strip!
     	var gl = this.gl;
     	var shaderProgram = this.shaderProgram;
     	
    @@ -1095,13 +1185,13 @@ PIXI.WebGLRenderGroup.prototype.initStrip = function(strip)
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_renderers_webgl_WebGLRenderer.js.html b/docs/files/src_pixi_renderers_webgl_WebGLRenderer.js.html index eb6aae6..df7b30e 100644 --- a/docs/files/src_pixi_renderers_webgl_WebGLRenderer.js.html +++ b/docs/files/src_pixi_renderers_webgl_WebGLRenderer.js.html @@ -2,12 +2,12 @@ - src/pixi/renderers/webgl/WebGLRenderer.js - Pixi.JS - - - - - + src/pixi/renderers/webgl/WebGLRenderer.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,102 +166,121 @@
    -

    File: src/pixi/renderers/webgl/WebGLRenderer.js

    +

    File: src/pixi/renderers/webgl/WebGLRenderer.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
     PIXI._defaultFrame = new PIXI.Rectangle(0,0,1,1);
     
    -// an instance of the gl context..
    -// only one at the moment :/
    +// an instance of the gl context..
    +// only one at the moment :/
     PIXI.gl;
     
    -/**
    - * the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer should be used for browsers support webGL. This Render works by automatically managing webGLBatchs. So no need for Sprite Batch's or Sprite Cloud's
    +/**
    + * the WebGLRenderer is draws the stage and all its content onto a webGL enabled canvas. This renderer
    + * should be used for browsers support webGL. This Render works by automatically managing webGLBatchs.
    + * So no need for Sprite Batch's or Sprite Cloud's
      * Dont forget to add the view to your DOM or you will not see anything :)
    + *
      * @class WebGLRenderer
      * @constructor
    - * @param width {Number} the width of the canvas view
    - * @default 0
    - * @param height {Number} the height of the canvas view
    - * @default 0
    + * @param width=0 {Number} the width of the canvas view
    + * @param height=0 {Number} the height of the canvas view
      * @param view {Canvas} the canvas to use as a view, optional
    - * @param transparent {Boolean} the transparency of the render view, default false
    - * @default false
    + * @param transparent=false {Boolean} the transparency of the render view, default false
    + * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment)
      * 
    - */
    -PIXI.WebGLRenderer = function(width, height, view, transparent)
    + */
    +PIXI.WebGLRenderer = function(width, height, view, transparent, antialias)
     {
    -	// do a catch.. only 1 webGL renderer..
    +	// do a catch.. only 1 webGL renderer..
     
    -	//console.log(transparent)
     	this.transparent = !!transparent;
    -	
    +
     	this.width = width || 800;
     	this.height = height || 600;
    -	
    +
     	this.view = view || document.createElement( 'canvas' ); 
         this.view.width = this.width;
     	this.view.height = this.height;
    -	
    -	// deal with losing context..	
    +
    +	// deal with losing context..	
         var scope = this;
     	this.view.addEventListener('webglcontextlost', function(event) { scope.handleContextLost(event); }, false)
     	this.view.addEventListener('webglcontextrestored', function(event) { scope.handleContextRestored(event); }, false)
     
     	this.batchs = [];
    +
    +	var options = {
    +		alpha: this.transparent,
    +		antialias:!!antialias, // SPEED UP??
    +		premultipliedAlpha:false,
    +		stencil:true
    +	}
    +
    +	//try 'experimental-webgl'
    +	try {
    +		PIXI.gl = this.gl = this.view.getContext("experimental-webgl",  options);
    +	} catch (e) {
    +		//try 'webgl'
    +		try {
    +			PIXI.gl = this.gl = this.view.getContext("webgl",  options);
    +		} catch (e) {
    +			// fail, not able to get a context
    +			throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this);
    +		}
    +	}
    +
    +    PIXI.initDefaultShaders();
    + 
    +
     	
    -	try 
    - 	{
    -        PIXI.gl = this.gl = this.view.getContext("experimental-webgl",  {  	
    -    		 alpha: this.transparent,
    -    		 antialias:true, // SPEED UP??
    -    		 premultipliedAlpha:false,
    -    		 stencil:true
    -        });
    -    } 
    -    catch (e) 
    -    {
    -    	throw new Error(" This browser does not support webGL. Try using the canvas renderer" + this);
    -    }
    -    
    -    PIXI.initPrimitiveShader();
    -    PIXI.initDefaultShader();
    -    PIXI.initDefaultStripShader();
    -    
    -    PIXI.activateDefaultShader();
    -    
    +
    +   // PIXI.activateDefaultShader();
    +
         var gl = this.gl;
    -    PIXI.WebGLRenderer.gl = gl;
         
    +    gl.useProgram(PIXI.defaultShader.program);
    +
    +
    +    PIXI.WebGLRenderer.gl = gl;
    +
         this.batch = new PIXI.WebGLBatch(gl);
        	gl.disable(gl.DEPTH_TEST);
        	gl.disable(gl.CULL_FACE);
    -   	
    -   	//
    -   	 
    -   	 
    +
         gl.enable(gl.BLEND);
         gl.colorMask(true, true, true, this.transparent); 
    -    
    +
         PIXI.projection = new PIXI.Point(400, 300);
    -    
    +    PIXI.offset = new PIXI.Point(0, 0);
    +
    +    // TODO remove thease globals..
    +
         this.resize(this.width, this.height);
         this.contextLost = false;
    -    
    +
    +	//PIXI.pushShader(PIXI.defaultShader);
    +
         this.stageRenderGroup = new PIXI.WebGLRenderGroup(this.gl);
    +    
     }
     
    -// constructor
    -PIXI.WebGLRenderer.constructor = PIXI.WebGLRenderer;
    +// constructor
    +PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer;
     
    -/**
    +/**
    + * Gets a new WebGLBatch from the pool
    + *
    + * @static
    + * @method getBatch
    + * @return {WebGLBatch}
      * @private 
    - */
    + */
     PIXI.WebGLRenderer.getBatch = function()
     {
     	if(PIXI._batchs.length == 0)
    @@ -250,86 +293,72 @@ PIXI.WebGLRenderer.getBatch = function()
     	}
     }
     
    -/**
    +/**
    + * Puts a batch back into the pool
    + *
    + * @static
    + * @method returnBatch
    + * @param batch {WebGLBatch} The batch to return
      * @private
    - */
    + */
     PIXI.WebGLRenderer.returnBatch = function(batch)
     {
     	batch.clean();	
     	PIXI._batchs.push(batch);
     }
     
    -
    -/**
    - * @private
    - */
    -
    -
    -
    -/**
    +/**
      * Renders the stage to its webGL view
    + *
      * @method render
    - * @param stage {Stage} the PIXI.Stage element to be rendered
    - */
    + * @param stage {Stage} the Stage element to be rendered
    + */
     PIXI.WebGLRenderer.prototype.render = function(stage)
     {
     	if(this.contextLost)return;
     	
     	
    -	// if rendering a new stage clear the batchs..
    +	// if rendering a new stage clear the batchs..
     	if(this.__stage !== stage)
     	{
    -		// TODO make this work
    -		// dont think this is needed any more?
    -		//if(this.__stage)this.checkVisibility(this.__stage, false)
    -		
    +		// TODO make this work
    +		// dont think this is needed any more?
     		this.__stage = stage;
     		this.stageRenderGroup.setRenderable(stage);
     	}
    -	
    -	// TODO not needed now... 
    -	// update children if need be
    -	// best to remove first!
    -	/*for (var i=0; i < stage.__childrenRemoved.length; i++)
    -	{
    -		var group = stage.__childrenRemoved[i].__renderGroup
    -		if(group)group.removeDisplayObject(stage.__childrenRemoved[i]);
    -	}*/
     
    -	// update any textures	
    +	// update any textures	
     	PIXI.WebGLRenderer.updateTextures();
     		
    -	// recursivly loop through all items!
    -	//this.checkVisibility(stage, true);
    -	
    -	// update the scene graph	
    +	// update the scene graph	
    +	PIXI.visibleCount++;
     	stage.updateTransform();
     	
     	var gl = this.gl;
     	
    -	// -- Does this need to be set every frame? -- //
    +	// -- Does this need to be set every frame? -- //
     	gl.colorMask(true, true, true, this.transparent); 
     	gl.viewport(0, 0, this.width, this.height);	
     	
    -	// set the correct matrix..	
    -   //	gl.uniformMatrix4fv(this.shaderProgram.mvMatrixUniform, false, this.projectionMatrix);
    -   
        	gl.bindFramebuffer(gl.FRAMEBUFFER, null);
     		
     	gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], !this.transparent);     
     	gl.clear(gl.COLOR_BUFFER_BIT);
     
    -	// HACK TO TEST
    -	//PIXI.projectionMatrix = this.projectionMatrix;
    +	// HACK TO TEST
     	
     	this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit;
    +	
    +	PIXI.projection.x =  this.width/2;
    +	PIXI.projection.y =  -this.height/2;
    +	
     	this.stageRenderGroup.render(PIXI.projection);
     	
    -	// interaction
    -	// run interaction!
    +	// interaction
    +	// run interaction!
     	if(stage.interactive)
     	{
    -		//need to add some events!
    +		//need to add some events!
     		if(!stage._interactiveEventsAdded)
     		{
     			stage._interactiveEventsAdded = true;
    @@ -337,7 +366,7 @@ PIXI.WebGLRenderer.prototype.render = function(stage)
     		}
     	}
     	
    -	// after rendering lets confirm all frames that have been uodated..
    +	// after rendering lets confirm all frames that have been uodated..
     	if(PIXI.Texture.frameUpdates.length > 0)
     	{
     		for (var i=0; i < PIXI.Texture.frameUpdates.length; i++) 
    @@ -349,38 +378,51 @@ PIXI.WebGLRenderer.prototype.render = function(stage)
     	}
     }
     
    -/**
    +/**
    + * Updates the textures loaded into this webgl renderer
    + *
    + * @static
    + * @method updateTextures
      * @private
    - */
    -
    + */
     PIXI.WebGLRenderer.updateTextures = function()
     {
    -	for (var i=0; i < PIXI.texturesToUpdate.length; i++) this.updateTexture(PIXI.texturesToUpdate[i]);
    -	for (var i=0; i < PIXI.texturesToDestroy.length; i++) this.destroyTexture(PIXI.texturesToDestroy[i]);
    +	//TODO break this out into a texture manager...
    +	for (var i=0; i < PIXI.texturesToUpdate.length; i++) PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]);
    +	for (var i=0; i < PIXI.texturesToDestroy.length; i++) PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]);
     	PIXI.texturesToUpdate = [];
     	PIXI.texturesToDestroy = [];
     }
     
    +/**
    + * Updates a loaded webgl texture
    + *
    + * @static
    + * @method updateTexture
    + * @param texture {Texture} The texture to update
    + * @private
    + */
     PIXI.WebGLRenderer.updateTexture = function(texture)
     {
    +	//TODO break this out into a texture manager...
     	var gl = PIXI.gl;
     	
     	if(!texture._glTexture)
     	{
     		texture._glTexture = gl.createTexture();
     	}
    -	
    +
     	if(texture.hasLoaded)
     	{
     		gl.bindTexture(gl.TEXTURE_2D, texture._glTexture);
     	 	gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
    -	 	
    +
     		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source);
     		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
     		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    -		
    -		// reguler...
    -		
    +
    +		// reguler...
    +
     		if(!texture._powerOf2)
     		{
     			gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    @@ -391,16 +433,23 @@ PIXI.WebGLRenderer.updateTexture = function(texture)
     			gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
     			gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
     		}
    -		
    +
     		gl.bindTexture(gl.TEXTURE_2D, null);
     	}
    -	
     }
     
    -PIXI.WebGLRenderer.prototype.destroyTexture = function(texture)
    +/**
    + * Destroys a loaded webgl texture
    + *
    + * @method destroyTexture
    + * @param texture {Texture} The texture to update
    + * @private
    + */
    +PIXI.WebGLRenderer.destroyTexture = function(texture)
     {
    -	var gl = this.gl;
    -	
    +	//TODO break this out into a texture manager...
    +	var gl = PIXI.gl;
    +
     	if(texture._glTexture)
     	{
     		texture._glTexture = gl.createTexture();
    @@ -408,72 +457,83 @@ PIXI.WebGLRenderer.prototype.destroyTexture = function(texture)
     	}
     }
     
    -/**
    +/**
      * resizes the webGL view to the specified width and height
    + *
      * @method resize
      * @param width {Number} the new width of the webGL view
      * @param height {Number} the new height of the webGL view
    - */
    + */
     PIXI.WebGLRenderer.prototype.resize = function(width, height)
     {
     	this.width = width;
     	this.height = height;
    -	
    +
     	this.view.width = width;
     	this.view.height = height;
    -	
    +
     	this.gl.viewport(0, 0, this.width, this.height);	
    +
    +	//var projectionMatrix = this.projectionMatrix;
    +
    +	PIXI.projection.x =  this.width/2;
    +	PIXI.projection.y =  -this.height/2;
     	
    -	//var projectionMatrix = this.projectionMatrix;
    -	
    -	PIXI.projection.x =  this.width/2;
    -	PIXI.projection.y =  this.height/2;
    -	
    -//	projectionMatrix[0] = 2/this.width;
    -//	projectionMatrix[5] = -2/this.height;
    -//	projectionMatrix[12] = -1;
    -//	projectionMatrix[13] = 1;
    +	//PIXI.size.x =  this.width/2;
    +	//PIXI.size.y =  -this.height/2;
    +
    +//	projectionMatrix[0] = 2/this.width;
    +//	projectionMatrix[5] = -2/this.height;
    +//	projectionMatrix[12] = -1;
    +//	projectionMatrix[13] = 1;
     }
     
    -/**
    +/**
    + * Handles a lost webgl context
    + *
    + * @method handleContextLost
    + * @param event {Event}
      * @private
    - */
    + */
     PIXI.WebGLRenderer.prototype.handleContextLost = function(event)
     {
     	event.preventDefault();
     	this.contextLost = true;
     }
     
    -/**
    +/**
    + * Handles a restored webgl context
    + *
    + * @method handleContextRestored
    + * @param event {Event}
      * @private
    - */
    + */
     PIXI.WebGLRenderer.prototype.handleContextRestored = function(event)
     {
     	this.gl = this.view.getContext("experimental-webgl",  {  	
     		alpha: true
         });
    -        
    +
     	this.initShaders();	
    -	
    +
     	for(var key in PIXI.TextureCache) 
     	{
             	var texture = PIXI.TextureCache[key].baseTexture;
             	texture._glTexture = null;
             	PIXI.WebGLRenderer.updateTexture(texture);
     	};
    -	
    +
     	for (var i=0; i <  this.batchs.length; i++) 
     	{
    -		this.batchs[i].restoreLostContext(this.gl)//
    +		this.batchs[i].restoreLostContext(this.gl)//
     		this.batchs[i].dirty = true;
     	};
    -	
    +
     	PIXI._restoreBatchs(this.gl);
    -	
    +
     	this.contextLost = false;
     }
     
    -
         
    @@ -483,13 +543,13 @@ PIXI.WebGLRenderer.prototype.handleContextRestored = function(event)
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_renderers_webgl_WebGLShaders.js.html b/docs/files/src_pixi_renderers_webgl_WebGLShaders.js.html index 1dff6c3..085bec1 100644 --- a/docs/files/src_pixi_renderers_webgl_WebGLShaders.js.html +++ b/docs/files/src_pixi_renderers_webgl_WebGLShaders.js.html @@ -2,12 +2,12 @@ - src/pixi/renderers/webgl/WebGLShaders.js - Pixi.JS - - - - - + src/pixi/renderers/webgl/WebGLShaders.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,167 +166,74 @@
    -

    File: src/pixi/renderers/webgl/WebGLShaders.js

    +

    File: src/pixi/renderers/webgl/WebGLShaders.js

    -
    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
     
    -/*
    - * the default suoer fast shader!
    - */
    +PIXI.initDefaultShaders = function() 
    +{
    +	PIXI.primitiveShader = new PIXI.PrimitiveShader();
    +  PIXI.primitiveShader.init();
     
    -PIXI.shaderFragmentSrc = [
    -  "precision mediump float;",
    -  "varying vec2 vTextureCoord;",
    -  "varying float vColor;",
    -  "uniform sampler2D uSampler;",
    -  "void main(void) {",
    -    "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));",
    -    "gl_FragColor = gl_FragColor * vColor;",
    -  "}"
    -];
    +  PIXI.stripShader = new PIXI.StripShader();
    +  PIXI.stripShader.init();
     
    -PIXI.shaderVertexSrc = [
    -  "attribute vec2 aVertexPosition;",
    -  "attribute vec2 aTextureCoord;",
    -  "attribute float aColor;",
    -  //"uniform mat4 uMVMatrix;",
    +	PIXI.defaultShader = new PIXI.PixiShader();
    +	PIXI.defaultShader.init();
    +
    +  var gl = PIXI.gl; 
    +  var shaderProgram = PIXI.defaultShader.program;
    + 
    +
    +  gl.useProgram(shaderProgram);
       
    -  "uniform vec2 projectionVector;",
    -  "varying vec2 vTextureCoord;",
    -  "varying float vColor;",
    -  "void main(void) {",
    -   // "gl_Position = uMVMatrix * vec4(aVertexPosition, 1.0, 1.0);",
    -    "gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);",
    -    "vTextureCoord = aTextureCoord;",
    -    "vColor = aColor;",
    -  "}"
    -];
    -
    -/*
    - * the triangle strip shader..
    - */
    -
    -PIXI.stripShaderFragmentSrc = [
    -  "precision mediump float;",
    -  "varying vec2 vTextureCoord;",
    -  "varying float vColor;",
    -  "uniform float alpha;",
    -  "uniform sampler2D uSampler;",
    -  "void main(void) {",
    -    "gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));",
    -    "gl_FragColor = gl_FragColor * alpha;",
    -  "}"
    -];
    -
    -
    -PIXI.stripShaderVertexSrc = [
    -  "attribute vec2 aVertexPosition;",
    -  "attribute vec2 aTextureCoord;",
    -  "attribute float aColor;",
    -  "uniform mat3 translationMatrix;",
    -  "uniform vec2 projectionVector;",
    -  "varying vec2 vTextureCoord;",
    -  "varying float vColor;",
    -  "void main(void) {",
    -	"vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);",
    -    "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);",
    -    "vTextureCoord = aTextureCoord;",
    -    "vColor = aColor;",
    -  "}"
    -];
    -
    -
    -/*
    - * primitive shader..
    - */
    -
    -PIXI.primitiveShaderFragmentSrc = [
    -  "precision mediump float;",
    -  "varying vec4 vColor;",
    -  "void main(void) {",
    -    "gl_FragColor = vColor;",
    -  "}"
    -];
    -
    -PIXI.primitiveShaderVertexSrc = [
    -  "attribute vec2 aVertexPosition;",
    -  "attribute vec4 aColor;",
    -  "uniform mat3 translationMatrix;",
    -  "uniform vec2 projectionVector;",
    -  "uniform float alpha;",
    -  "varying vec4 vColor;",
    -  "void main(void) {",
    -  	"vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);",
    -    "gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);",
    -    "vColor = aColor  * alpha;",
    -  "}"
    -];
    -
    -PIXI.initPrimitiveShader = function() 
    -{
    -	var gl = PIXI.gl;
    -
    -	var shaderProgram = PIXI.compileProgram(PIXI.primitiveShaderVertexSrc, PIXI.primitiveShaderFragmentSrc)
    -	
    -    gl.useProgram(shaderProgram);
    -
    -    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
    -    shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor");
    -    
    -    shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector");
    -    shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix");
    -    
    -	shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha");
    -
    -	PIXI.primitiveProgram = shaderProgram;
    +  gl.enableVertexAttribArray(PIXI.defaultShader.aVertexPosition);
    +  gl.enableVertexAttribArray(PIXI.defaultShader.colorAttribute);
    +  gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord);
     }
     
    -PIXI.initDefaultShader = function() 
    +PIXI.activatePrimitiveShader = function()
     {
    -	var gl = this.gl;
    -	var shaderProgram = PIXI.compileProgram(PIXI.shaderVertexSrc, PIXI.shaderFragmentSrc)
    -	
    -    gl.useProgram(shaderProgram);
    +  var gl = PIXI.gl;
    +  
    +  gl.useProgram(PIXI.primitiveShader.program);
    +  gl.disableVertexAttribArray(PIXI.defaultShader.aTextureCoord);
    +} 
     
    -    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
    -    shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector");
    -    shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
    -	shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor");
    +PIXI.deactivatePrimitiveShader = function()
    +{
    +  var gl = PIXI.gl;
     
    -   // shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
    -    shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
    -    
    -	PIXI.shaderProgram = shaderProgram;
    +  gl.useProgram(PIXI.defaultShader.program);
    +  gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord);
     }
     
    -PIXI.initDefaultStripShader = function() 
    +PIXI.activateStripShader = function()
     {
    -	var gl = this.gl;
    -	var shaderProgram = PIXI.compileProgram(PIXI.stripShaderVertexSrc, PIXI.stripShaderFragmentSrc)
    -	
    -    gl.useProgram(shaderProgram);
    +  var gl = PIXI.gl;
    +  
    +  gl.useProgram(PIXI.stripShader.program);
    + // gl.disableVertexAttribArray(PIXI.defaultShader.aTextureCoord);
    +} 
     
    -    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
    -    shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector");
    -    shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
    -	shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix");
    -	shaderProgram.alpha = gl.getUniformLocation(shaderProgram, "alpha");
    +PIXI.deactivateStripShader = function()
    +{
    +  var gl = PIXI.gl;
     
    -	shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor");
    -
    -    shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector");
    -    
    -    shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
    -    
    -	PIXI.stripShaderProgram = shaderProgram;
    +  gl.useProgram(PIXI.defaultShader.program);
    +  //gl.enableVertexAttribArray(PIXI.defaultShader.aTextureCoord);
     }
     
    +/*
    +
    +SHADER COMPILER HELPERS
    +*/
    +
     PIXI.CompileVertexShader = function(gl, shaderSrc)
     {
       return PIXI._CompileShader(gl, shaderSrc, gl.VERTEX_SHADER);
    @@ -321,7 +252,7 @@ PIXI._CompileShader = function(gl, shaderSrc, shaderType)
       gl.compileShader(shader);
     
       if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    -    alert(gl.getShaderInfoLog(shader));
    +    console.log(gl.getShaderInfoLog(shader));
         return null;
       }
     
    @@ -342,42 +273,12 @@ PIXI.compileProgram = function(vertexSrc, fragmentSrc)
         gl.linkProgram(shaderProgram);
     
         if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
    -        alert("Could not initialise shaders");
    +        console.log("Could not initialise shaders");
         }
     
     	return shaderProgram;
     } 
     
    -
    -PIXI.activateDefaultShader = function()
    -{
    -	var gl = PIXI.gl;
    -	var shaderProgram = PIXI.shaderProgram;
    -	
    -	gl.useProgram(shaderProgram);
    -	
    -	
    -	gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
    -    gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
    -    gl.enableVertexAttribArray(shaderProgram.colorAttribute);
    -}
    -
    -	
    -
    -PIXI.activatePrimitiveShader = function()
    -{
    -	var gl = PIXI.gl;
    -	
    -	gl.disableVertexAttribArray(PIXI.shaderProgram.textureCoordAttribute);
    -    gl.disableVertexAttribArray(PIXI.shaderProgram.colorAttribute);
    -    
    -	gl.useProgram(PIXI.primitiveProgram);
    -	
    -	gl.enableVertexAttribArray(PIXI.primitiveProgram.vertexPositionAttribute);
    -	gl.enableVertexAttribArray(PIXI.primitiveProgram.colorAttribute);
    -} 
    -
    -
         
    @@ -387,13 +288,13 @@ PIXI.activatePrimitiveShader = function()
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_text_BitmapText.js.html b/docs/files/src_pixi_text_BitmapText.js.html index 5e9bbc2..8c436af 100644 --- a/docs/files/src_pixi_text_BitmapText.js.html +++ b/docs/files/src_pixi_text_BitmapText.js.html @@ -2,12 +2,12 @@ - src/pixi/text/BitmapText.js - Pixi.JS - - - - - + src/pixi/text/BitmapText.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,27 +166,28 @@
    -

    File: src/pixi/text/BitmapText.js

    +

    File: src/pixi/text/BitmapText.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -/**
    +/**
      * A Text Object will create a line(s) of text using bitmap font. To split a line you can use "\n", "\r" or "\r\n"
    - * You can generate the fnt files using 
    - * http://www.angelcode.com/products/bmfont/ for windows or
    - * http://www.bmglyph.com/ for mac.
    + * You can generate the fnt files using
    + * http://www.angelcode.com/products/bmfont/ for windows or
    + * http://www.bmglyph.com/ for mac.
    + *
      * @class BitmapText
      * @extends DisplayObjectContainer
      * @constructor
    - * @param {String} text The copy that you would like the text to display
    - * @param {Object} style The style parameters
    - * @param {String} style.font The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously)
    - * @param {String} [style.align="left"] An alignment of the multiline text ("left", "center" or "right")
    - */
    + * @param text {String} The copy that you would like the text to display
    + * @param style {Object} The style parameters
    + * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously)
    + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right")
    + */
     PIXI.BitmapText = function(text, style)
     {
         PIXI.DisplayObjectContainer.call(this);
    @@ -174,28 +199,30 @@ PIXI.BitmapText = function(text, style)
     
     };
     
    -// constructor
    -PIXI.BitmapText.constructor = PIXI.BitmapText;
    +// constructor
     PIXI.BitmapText.prototype = Object.create(PIXI.DisplayObjectContainer.prototype);
    +PIXI.BitmapText.prototype.constructor = PIXI.BitmapText;
     
    -/**
    +/**
      * Set the copy for the text object
    + *
      * @method setText
    - * @param {String} text The copy that you would like the text to display
    - */
    + * @param text {String} The copy that you would like the text to display
    + */
     PIXI.BitmapText.prototype.setText = function(text)
     {
         this.text = text || " ";
         this.dirty = true;
     };
     
    -/**
    +/**
      * Set the style of the text
    + *
      * @method setStyle
    - * @param {Object} style The style parameters
    - * @param {String} style.font The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously)
    - * @param {String} [style.align="left"] An alignment of the multiline text ("left", "center" or "right")
    - */
    + * @param style {Object} The style parameters
    + * @param style.font {String} The size (optional) and bitmap font id (required) eq "Arial" or "20px Arial" (must have loaded previously)
    + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right")
    + */
     PIXI.BitmapText.prototype.setStyle = function(style)
     {
         style = style || {};
    @@ -209,10 +236,12 @@ PIXI.BitmapText.prototype.setStyle = function(style)
         this.dirty = true;
     };
     
    -/**
    +/**
      * Renders text
    + *
    + * @method updateText
      * @private
    - */
    + */
     PIXI.BitmapText.prototype.updateText = function()
     {
         var data = PIXI.BitmapText.fonts[this.fontName];
    @@ -222,11 +251,11 @@ PIXI.BitmapText.prototype.updateText = function()
         var maxLineWidth = 0;
         var lineWidths = [];
         var line = 0;
    -    var scale = this.fontSize / data.size;
    +    var scale = this.fontSize / data.size;
         for(var i = 0; i < this.text.length; i++)
         {
             var charCode = this.text.charCodeAt(i);
    -        if(/(?:\r\n|\r|\n)/.test(this.text.charAt(i)))
    +        if(/(?:\r\n|\r|\n)/.test(this.text.charAt(i)))
             {
                 lineWidths.push(pos.x);
                 maxLineWidth = Math.max(maxLineWidth, pos.x);
    @@ -237,7 +266,7 @@ PIXI.BitmapText.prototype.updateText = function()
                 prevCharCode = null;
                 continue;
             }
    -        
    +
             var charData = data.chars[charCode];
             if(!charData) continue;
     
    @@ -264,14 +293,14 @@ PIXI.BitmapText.prototype.updateText = function()
             }
             else if(this.style.align == "center")
             {
    -            alignOffset = (maxLineWidth - lineWidths[i]) / 2;
    +            alignOffset = (maxLineWidth - lineWidths[i]) / 2;
             }
             lineAlignOffsets.push(alignOffset);
         }
     
         for(i = 0; i < chars.length; i++)
         {
    -        var c = new PIXI.Sprite(chars[i].texture)//PIXI.Sprite.fromFrame(chars[i].charCode);
    +        var c = new PIXI.Sprite(chars[i].texture)//PIXI.Sprite.fromFrame(chars[i].charCode);
             c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale;
             c.position.y = chars[i].position.y * scale;
             c.scale.x = c.scale.y = scale;
    @@ -282,9 +311,12 @@ PIXI.BitmapText.prototype.updateText = function()
         this.height = (pos.y + data.lineHeight) * scale;
     };
     
    -/**
    +/**
    + * Updates the transfor of this object
    + *
    + * @method updateTransform
      * @private
    - */
    + */
     PIXI.BitmapText.prototype.updateTransform = function()
     {
     	if(this.dirty)
    @@ -297,11 +329,12 @@ PIXI.BitmapText.prototype.updateTransform = function()
     
             this.dirty = false;
     	}
    -	
    +
     	PIXI.DisplayObjectContainer.prototype.updateTransform.call(this);
     };
     
     PIXI.BitmapText.fonts = {};
    +
         
    @@ -311,13 +344,13 @@ PIXI.BitmapText.fonts = {};
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_text_Text.js.html b/docs/files/src_pixi_text_Text.js.html index 0ad9379..8702980 100644 --- a/docs/files/src_pixi_text_Text.js.html +++ b/docs/files/src_pixi_text_Text.js.html @@ -2,12 +2,12 @@ - src/pixi/text/Text.js - Pixi.JS - - - - - + src/pixi/text/Text.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,29 +166,30 @@
    -

    File: src/pixi/text/Text.js

    +

    File: src/pixi/text/Text.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -/**
    +/**
      * A Text Object will create a line(s) of text to split a line you can use "\n"
    + *
      * @class Text
      * @extends Sprite
      * @constructor
    - * @param {String} text The copy that you would like the text to display
    - * @param {Object} [style] The style parameters
    - * @param {String} [style.font] default "bold 20pt Arial" The style and size of the font
    - * @param {Object} [style.fill="black"] A canvas fillstyle that will be used on the text eg "red", "#00FF00"
    - * @param {String} [style.align="left"] An alignment of the multiline text ("left", "center" or "right")
    - * @param {String} [style.stroke] A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00"
    - * @param {Number} [style.strokeThickness=0] A number that represents the thickness of the stroke. Default is 0 (no stroke)
    - * @param {Boolean} [style.wordWrap=false] Indicates if word wrap should be used
    - * @param {Number} [style.wordWrapWidth=100] The width at which text will wrap
    - */
    + * @param text {String} The copy that you would like the text to display
    + * @param [style] {Object} The style parameters
    + * @param [style.font] {String} default "bold 20pt Arial" The style and size of the font
    + * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00"
    + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right")
    + * @param [style.stroke] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00"
    + * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke)
    + * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used
    + * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap
    + */
     PIXI.Text = function(text, style)
     {
         this.canvas = document.createElement("canvas");
    @@ -173,34 +198,35 @@ PIXI.Text = function(text, style)
     
         this.setText(text);
         this.setStyle(style);
    -    
    -     this.updateText();
    +
    +    this.updateText();
         this.dirty = false;
     };
     
    -// constructor
    -PIXI.Text.constructor = PIXI.Text;
    +// constructor
     PIXI.Text.prototype = Object.create(PIXI.Sprite.prototype);
    +PIXI.Text.prototype.constructor = PIXI.Text;
     
    -/**
    +/**
      * Set the style of the text
    + *
      * @method setStyle
    - * @param {Object} [style] The style parameters
    - * @param {String} [style.font="bold 20pt Arial"] The style and size of the font
    - * @param {Object} [style.fill="black"] A canvas fillstyle that will be used on the text eg "red", "#00FF00"
    - * @param {String} [style.align="left"] An alignment of the multiline text ("left", "center" or "right")
    - * @param {String} [style.stroke="black"] A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00"
    - * @param {Number} [style.strokeThickness=0] A number that represents the thickness of the stroke. Default is 0 (no stroke)
    - * @param {Boolean} [style.wordWrap=false] Indicates if word wrap should be used
    - * @param {Number} [style.wordWrapWidth=100] The width at which text will wrap
    - */
    + * @param [style] {Object} The style parameters
    + * @param [style.font="bold 20pt Arial"] {String} The style and size of the font
    + * @param [style.fill="black"] {Object} A canvas fillstyle that will be used on the text eg "red", "#00FF00"
    + * @param [style.align="left"] {String} An alignment of the multiline text ("left", "center" or "right")
    + * @param [style.stroke="black"] {String} A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00"
    + * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke)
    + * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used
    + * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap
    + */
     PIXI.Text.prototype.setStyle = function(style)
     {
         style = style || {};
         style.font = style.font || "bold 20pt Arial";
         style.fill = style.fill || "black";
         style.align = style.align || "left";
    -    style.stroke = style.stroke || "black"; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136
    +    style.stroke = style.stroke || "black"; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136
         style.strokeThickness = style.strokeThickness || 0;
         style.wordWrap = style.wordWrap || false;
         style.wordWrapWidth = style.wordWrapWidth || 100;
    @@ -208,35 +234,38 @@ PIXI.Text.prototype.setStyle = function(style)
         this.dirty = true;
     };
     
    -/**
    +/**
      * Set the copy for the text object. To split a line you can use "\n"
    + *
      * @methos setText
      * @param {String} text The copy that you would like the text to display
    - */
    -PIXI.Sprite.prototype.setText = function(text)
    + */
    +PIXI.Text.prototype.setText = function(text)
     {
         this.text = text.toString() || " ";
         this.dirty = true;
     };
     
    -/**
    +/**
      * Renders text
    + *
    + * @method updateText
      * @private
    - */
    + */
     PIXI.Text.prototype.updateText = function()
     {
     	this.context.font = this.style.font;
    -	
    +
     	var outputText = this.text;
    -	
    -	// word wrap
    -	// preserve original text
    +
    +	// word wrap
    +	// preserve original text
     	if(this.style.wordWrap)outputText = this.wordWrap(this.text);
     
    -	//split text into lines
    -	var lines = outputText.split(/(?:\r\n|\r|\n)/);
    +	//split text into lines
    +	var lines = outputText.split(/(?:\r\n|\r|\n)/);
     
    -	//calculate text width
    +	//calculate text width
     	var lineWidths = [];
     	var maxLineWidth = 0;
     	for (var i = 0; i < lines.length; i++)
    @@ -246,32 +275,32 @@ PIXI.Text.prototype.updateText = function()
     		maxLineWidth = Math.max(maxLineWidth, lineWidth);
     	}
     	this.canvas.width = maxLineWidth + this.style.strokeThickness;
    -	
    -	//calculate text height
    +
    +	//calculate text height
     	var lineHeight = this.determineFontHeight("font: " + this.style.font  + ";") + this.style.strokeThickness;
     	this.canvas.height = lineHeight * lines.length;
     
    -	//set canvas text styles
    +	//set canvas text styles
     	this.context.fillStyle = this.style.fill;
     	this.context.font = this.style.font;
    -	
    +
     	this.context.strokeStyle = this.style.stroke;
     	this.context.lineWidth = this.style.strokeThickness;
     
     	this.context.textBaseline = "top";
     
    -	//draw lines line by line
    +	//draw lines line by line
     	for (i = 0; i < lines.length; i++)
     	{
    -		var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight);
    -	
    +		var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight);
    +
     		if(this.style.align == "right")
     		{
     			linePosition.x += maxLineWidth - lineWidths[i];
     		}
     		else if(this.style.align == "center")
     		{
    -			linePosition.x += (maxLineWidth - lineWidths[i]) / 2;
    +			linePosition.x += (maxLineWidth - lineWidths[i]) / 2;
     		}
     
     		if(this.style.stroke && this.style.strokeThickness)
    @@ -284,52 +313,60 @@ PIXI.Text.prototype.updateText = function()
     			this.context.fillText(lines[i], linePosition.x, linePosition.y);
     		}
     	}
    -	
    +
         this.updateTexture();
     };
     
    -/**
    +/**
      * Updates texture size based on canvas size
    + *
    + * @method updateTexture
      * @private
    - */
    + */
     PIXI.Text.prototype.updateTexture = function()
     {
    -
         this.texture.baseTexture.width = this.canvas.width;
         this.texture.baseTexture.height = this.canvas.height;
         this.texture.frame.width = this.canvas.width;
         this.texture.frame.height = this.canvas.height;
    -    
    +
       	this._width = this.canvas.width;
         this._height = this.canvas.height;
    -	
    +
         PIXI.texturesToUpdate.push(this.texture.baseTexture);
     };
     
    -/**
    +/**
    + * Updates the transfor of this object
    + *
    + * @method updateTransform
      * @private
    - */
    + */
     PIXI.Text.prototype.updateTransform = function()
     {
     	if(this.dirty)
     	{
    -		this.updateText();	
    +		this.updateText();
     		this.dirty = false;
     	}
    -	
    +
     	PIXI.Sprite.prototype.updateTransform.call(this);
     };
     
    -/*
    - * http://stackoverflow.com/users/34441/ellisbben
    +/*
    + * http://stackoverflow.com/users/34441/ellisbben
      * great solution to the problem!
    - */
    -PIXI.Text.prototype.determineFontHeight = function(fontStyle) 
    + *
    + * @method determineFontHeight
    + * @param fontStyle {Object}
    + * @private
    + */
    +PIXI.Text.prototype.determineFontHeight = function(fontStyle)
     {
    -	// build a little reference dictionary so if the font style has been used return a
    -	// cached version...
    +	// build a little reference dictionary so if the font style has been used return a
    +	// cached version...
     	var result = PIXI.Text.heightCache[fontStyle];
    -	
    +
     	if(!result)
     	{
     		var body = document.getElementsByTagName("body")[0];
    @@ -338,30 +375,33 @@ PIXI.Text.prototype.determineFontHeight = function(fontStyle)
     		dummy.appendChild(dummyText);
     		dummy.setAttribute("style", fontStyle + ';position:absolute;top:0;left:0');
     		body.appendChild(dummy);
    -		
    +
     		result = dummy.offsetHeight;
     		PIXI.Text.heightCache[fontStyle] = result;
    -		
    +
     		body.removeChild(dummy);
     	}
    -	
    +
     	return result;
     };
     
    -/**
    +/**
      * A Text Object will apply wordwrap
    + *
    + * @method wordWrap
    + * @param text {String}
      * @private
    - */
    + */
     PIXI.Text.prototype.wordWrap = function(text)
     {
    -	// search good wrap position
    +	// search good wrap position
     	var searchWrapPos = function(ctx, text, start, end, wrapWidth)
     	{
    -		var p = Math.floor((end-start) / 2) + start;
    +		var p = Math.floor((end-start) / 2) + start;
     		if(p == start) {
     			return 1;
     		}
    -		
    +
     		if(ctx.measureText(text.substring(0,p)).width <= wrapWidth)
     		{
     			if(ctx.measureText(text.substring(0,p+1)).width > wrapWidth)
    @@ -378,7 +418,7 @@ PIXI.Text.prototype.wordWrap = function(text)
     			return arguments.callee(ctx, text, start, p, wrapWidth);
     		}
     	};
    -	 
    +
     	var lineWrap = function(ctx, text, wrapWidth)
     	{
     		if(ctx.measureText(text).width <= wrapWidth || text.length < 1)
    @@ -388,24 +428,30 @@ PIXI.Text.prototype.wordWrap = function(text)
     		var pos = searchWrapPos(ctx, text, 0, text.length, wrapWidth);
     		return text.substring(0, pos) + "\n" + arguments.callee(ctx, text.substring(pos), wrapWidth);
     	};
    -	
    +
     	var result = "";
     	var lines = text.split("\n");
     	for (var i = 0; i < lines.length; i++)
     	{
     		result += lineWrap(this.context, lines[i], this.style.wordWrapWidth) + "\n";
     	}
    -	
    +
     	return result;
     };
     
    +/**
    + * Destroys this text object
    + *
    + * @method destroy
    + * @param destroyTexture {Boolean}
    + */
     PIXI.Text.prototype.destroy = function(destroyTexture)
     {
     	if(destroyTexture)
     	{
     		this.texture.destroy();
     	}
    -		
    +
     };
     
     PIXI.Text.heightCache = {};
    @@ -419,13 +465,13 @@ PIXI.Text.heightCache = {};
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_textures_BaseTexture.js.html b/docs/files/src_pixi_textures_BaseTexture.js.html index 98f2ff6..b4888f2 100644 --- a/docs/files/src_pixi_textures_BaseTexture.js.html +++ b/docs/files/src_pixi_textures_BaseTexture.js.html @@ -2,12 +2,12 @@ - src/pixi/textures/BaseTexture.js - Pixi.JS - - - - - + src/pixi/textures/BaseTexture.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,83 +166,92 @@
    -

    File: src/pixi/textures/BaseTexture.js

    +

    File: src/pixi/textures/BaseTexture.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
     PIXI.BaseTextureCache = {};
     PIXI.texturesToUpdate = [];
     PIXI.texturesToDestroy = [];
     
    -/**
    +/**
      * A texture stores the information that represents an image. All textures have a base texture
    + *
      * @class BaseTexture
    - * @extends EventTarget
    + * @uses EventTarget
      * @constructor
      * @param source {String} the source object (image or canvas)
    - */
    + */
     PIXI.BaseTexture = function(source)
     {
     	PIXI.EventTarget.call( this );
    -	
    -	/*
    -	 * The url of the texture
    -	 * @property imageUrl
    -	 * @type String
    -	 */
    -	//this.imageUrl = source.src;
    -	
    -	/**
    -	 * [read only] The width of the base texture set when the image has loaded
    +
    +	/**
    +	 * [read-only] The width of the base texture set when the image has loaded
    +	 *
     	 * @property width
     	 * @type Number
    -	 */
    +	 * @readOnly
    +	 */
     	this.width = 100;
    -	/**
    -	 * [read only] The height of the base texture set when the image has loaded
    +
    +	/**
    +	 * [read-only] The height of the base texture set when the image has loaded
    +	 *
     	 * @property height
     	 * @type Number
    -	 */
    +	 * @readOnly
    +	 */
     	this.height = 100;
    -	
    -	/**
    +
    +	/**
    +	 * [read-only] Describes if the base texture has loaded or not
    +	 *
    +	 * @property hasLoaded
    +	 * @type Boolean
    +	 * @readOnly
    +	 */
    +	this.hasLoaded = false;
    +
    +	/**
     	 * The source that is loaded to create the texture
    +	 *
     	 * @property source
     	 * @type Image
    -	 */
    -	this.source = source//new Image();
    -	
    +	 */
    +	this.source = source;
    +
     	if(!source)return;
    -	
    -	if(this.source instanceof Image)
    +
    +	if(this.source instanceof Image || this.source instanceof HTMLImageElement)
     	{
     		if(this.source.complete)
     		{
     			this.hasLoaded = true;
     			this.width = this.source.width;
     			this.height = this.source.height;
    -			
    +
     			PIXI.texturesToUpdate.push(this);
     		}
     		else
     		{
    -			
    +
     			var scope = this;
     			this.source.onload = function(){
    -				
    +
     				scope.hasLoaded = true;
     				scope.width = scope.source.width;
     				scope.height = scope.source.height;
    -			
    -				// add it to somewhere...
    +
    +				// add it to somewhere...
     				PIXI.texturesToUpdate.push(scope);
     				scope.dispatchEvent( { type: 'loaded', content: scope } );
     			}
    -			//	this.image.src = imageUrl;
    +			//	this.image.src = imageUrl;
     		}
     	}
     	else
    @@ -226,16 +259,20 @@ PIXI.BaseTexture = function(source)
     		this.hasLoaded = true;
     		this.width = this.source.width;
     		this.height = this.source.height;
    -			
    +
     		PIXI.texturesToUpdate.push(this);
     	}
    -	
    +
     	this._powerOf2 = false;
    -	
     }
     
    -PIXI.BaseTexture.constructor = PIXI.BaseTexture;
    +PIXI.BaseTexture.prototype.constructor = PIXI.BaseTexture;
     
    +/**
    + * Destroys this base texture
    + *
    + * @method destroy
    + */
     PIXI.BaseTexture.prototype.destroy = function()
     {
     	if(this.source instanceof Image)
    @@ -246,23 +283,23 @@ PIXI.BaseTexture.prototype.destroy = function()
     	PIXI.texturesToDestroy.push(this);
     }
     
    -/**
    - * 
    +/**
      * Helper function that returns a base texture based on an image url
      * If the image is not in the base texture cache it will be  created and loaded
    + *
      * @static
      * @method fromImage
      * @param imageUrl {String} The image url of the texture
      * @return BaseTexture
    - */
    + */
     PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin)
     {
     	var baseTexture = PIXI.BaseTextureCache[imageUrl];
     	if(!baseTexture)
     	{
    -		// new Image() breaks tex loading in some versions of Chrome.
    -		// See https://code.google.com/p/chromium/issues/detail?id=238071
    -		var image = new Image();//document.createElement('img'); 
    +		// new Image() breaks tex loading in some versions of Chrome.
    +		// See https://code.google.com/p/chromium/issues/detail?id=238071
    +		var image = new Image();//document.createElement('img');
     		if (crossorigin)
     		{
     			image.crossOrigin = '';
    @@ -284,13 +321,13 @@ PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin)
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_textures_RenderTexture.js.html b/docs/files/src_pixi_textures_RenderTexture.js.html index 0c25c6d..9fbba1c 100644 --- a/docs/files/src_pixi_textures_RenderTexture.js.html +++ b/docs/files/src_pixi_textures_RenderTexture.js.html @@ -2,12 +2,12 @@ - src/pixi/textures/RenderTexture.js - Pixi.JS - - - - - + src/pixi/textures/RenderTexture.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,15 +166,15 @@
    -

    File: src/pixi/textures/RenderTexture.js

    +

    File: src/pixi/textures/RenderTexture.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -/**
    +/**
      A RenderTexture is a special texture that allows any pixi displayObject to be rendered to it.
     
      __Hint__: All DisplayObjects (exmpl. Sprites) that renders on RenderTexture should be preloaded. 
    @@ -160,8 +184,8 @@
      
     	var renderTexture = new PIXI.RenderTexture(800, 600);
     	var sprite = PIXI.Sprite.fromImage("spinObj_01.png");
    -	sprite.position.x = 800/2;
    -	sprite.position.y = 600/2;
    +	sprite.position.x = 800/2;
    +	sprite.position.y = 600/2;
     	sprite.anchor.x = 0.5;
     	sprite.anchor.y = 0.5;
     	renderTexture.render(sprite);
    @@ -170,25 +194,25 @@
     
     	var doc = new PIXI.DisplayObjectContainer();
     	doc.addChild(sprite);
    -	renderTexture.render(doc);  // Renders to center of renderTexture
    +	renderTexture.render(doc);  // Renders to center of renderTexture
     
      @class RenderTexture
      @extends Texture
      @constructor
    - @param width {Number}
    - @param height {Number}
    - **/
    + @param width {Number} The width of the render texture
    + @param height {Number} The height of the render texture
    + */
     PIXI.RenderTexture = function(width, height)
     {
     	PIXI.EventTarget.call( this );
    -	
    +
     	this.width = width || 100;
     	this.height = height || 100;
     
     	this.indetityMatrix = PIXI.mat3.create();
    -	
    +
     	this.frame = new PIXI.Rectangle(0, 0, this.width, this.height);	
    -	
    +
     	if(PIXI.gl)
     	{
     		this.initWebGL();
    @@ -199,19 +223,25 @@ PIXI.RenderTexture = function(width, height)
     	}
     }
     
    -PIXI.RenderTexture.constructor = PIXI.RenderTexture;
     PIXI.RenderTexture.prototype = Object.create( PIXI.Texture.prototype );
    +PIXI.RenderTexture.prototype.constructor = PIXI.RenderTexture;
     
    +/**
    + * Initializes the webgl data for this texture
    + *
    + * @method initWebGL
    + * @private
    + */
     PIXI.RenderTexture.prototype.initWebGL = function()
     {
     	var gl = PIXI.gl;
     	this.glFramebuffer = gl.createFramebuffer();
    -	
    +
        	gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer );
     
         this.glFramebuffer.width = this.width;
         this.glFramebuffer.height = this.height;	
    -  
    +
     	this.baseTexture = new PIXI.BaseTexture();
     
     	this.baseTexture.width = this.width;
    @@ -219,120 +249,175 @@ PIXI.RenderTexture.prototype.initWebGL = function()
     
         this.baseTexture._glTexture = gl.createTexture();
         gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture);
    -	 	
    +
     	gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA,  this.width,  this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
    -	
    +
         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
     	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
     	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
     	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    -	
    +
     	this.baseTexture.isRender = true;
    -	
    +
     	gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer );
     	gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.baseTexture._glTexture, 0);
    -	
    -	// create a projection matrix..
    -	this.projection = new PIXI.Point(this.width/2 , this.height/2);
    -	
    -	this.projectionMatrix =  PIXI.mat4.create();
    -	
    -	this.projectionMatrix[5] = 2/this.height// * 0.5;
    -	this.projectionMatrix[13] = -1;
    -	
    -	this.projectionMatrix[0] = 2/this.width;
    -	this.projectionMatrix[12] = -1;
     
    -	// set the correct render function..
    +	// create a projection matrix..
    +	this.projection = new PIXI.Point(this.width/2 , -this.height/2);
    +
    +	// set the correct render function..
     	this.render = this.renderWebGL;
     }
     
    +
    +PIXI.RenderTexture.prototype.resize = function(width, height)
    +{
    +
    +	this.width = width;
    +	this.height = height;
    +	
    +	if(PIXI.gl)
    +	{
    +		this.projection.x = this.width/2
    +		this.projection.y = -this.height/2;
    +	
    +		var gl = PIXI.gl;
    +		gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture);
    +		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA,  this.width,  this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
    +	}
    +	else
    +	{
    +		
    +		this.frame.width = this.width
    +		this.frame.height = this.height;
    +		this.renderer.resize(this.width, this.height);
    +	}
    +}
    +
    +/**
    + * Initializes the canvas data for this texture
    + *
    + * @method initCanvas
    + * @private
    + */
     PIXI.RenderTexture.prototype.initCanvas = function()
     {
     	this.renderer = new PIXI.CanvasRenderer(this.width, this.height, null, 0);
    -	
    +
     	this.baseTexture = new PIXI.BaseTexture(this.renderer.view);
     	this.frame = new PIXI.Rectangle(0, 0, this.width, this.height);
    -	
    +
     	this.render = this.renderCanvas;
     }
     
    -/**
    +/**
      * This function will draw the display object to the texture.
    - * @method render
    - * @param displayObject {DisplayObject}
    + *
    + * @method renderWebGL
    + * @param displayObject {DisplayObject} The display object to render this texture on
      * @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn
    - */
    -PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, clear)
    + * @private
    + */
    +PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, clear)
     {
     	var gl = PIXI.gl;
    -	
    -	// enable the alpha color mask..
    +
    +	// enable the alpha color mask..
     	gl.colorMask(true, true, true, true); 
    -	
    +
     	gl.viewport(0, 0, this.width, this.height);	
    -	
    +
     	gl.bindFramebuffer(gl.FRAMEBUFFER, this.glFramebuffer );
    -	
    +
     	if(clear)
     	{
     		gl.clearColor(0,0,0, 0);     
     		gl.clear(gl.COLOR_BUFFER_BIT);
     	}
    -	
    -	// THIS WILL MESS WITH HIT TESTING!
    +
    +	// THIS WILL MESS WITH HIT TESTING!
     	var children = displayObject.children;
    -	
    -	//TODO -? create a new one??? dont think so!
    -	displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix;
    -	// modify to flip...
    +
    +	//TODO -? create a new one??? dont think so!
    +	var originalWorldTransform = displayObject.worldTransform;
    +	displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix;
    +	// modify to flip...
     	displayObject.worldTransform[4] = -1;
    -	displayObject.worldTransform[5] = this.projection.y * 2;
    +	displayObject.worldTransform[5] = this.projection.y * -2;
    +
    +	if(position)
    +	{
    +		displayObject.worldTransform[2] = position.x;
    +		displayObject.worldTransform[5] -= position.y;
    +	}
    +	
    +	PIXI.visibleCount++;
    +	displayObject.vcount = PIXI.visibleCount;
     	
     	for(var i=0,j=children.length; i<j; i++)
     	{
     		children[i].updateTransform();	
     	}
    -	
    +
     	var renderGroup = displayObject.__renderGroup;
     
     	if(renderGroup)
     	{
     		if(displayObject == renderGroup.root)
     		{
    -			renderGroup.render(this.projection);
    +			renderGroup.render(this.projection, this.glFramebuffer);
     		}
     		else
     		{
    -			renderGroup.renderSpecific(displayObject, this.projection);
    +			renderGroup.renderSpecific(displayObject, this.projection, this.glFramebuffer);
     		}
     	}
     	else
     	{
     		if(!this.renderGroup)this.renderGroup = new PIXI.WebGLRenderGroup(gl);
     		this.renderGroup.setRenderable(displayObject);
    -		this.renderGroup.render(this.projection);
    +		this.renderGroup.render(this.projection, this.glFramebuffer);
     	}
     	
    +	displayObject.worldTransform = originalWorldTransform;
     }
     
    -PIXI.RenderTexture.prototype.renderCanvas = function(displayObject, clear)
    +
    +/**
    + * This function will draw the display object to the texture.
    + *
    + * @method renderCanvas
    + * @param displayObject {DisplayObject} The display object to render this texture on
    + * @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn
    + * @private
    + */
    +PIXI.RenderTexture.prototype.renderCanvas = function(displayObject, position, clear)
     {
     	var children = displayObject.children;
    -	
    +
     	displayObject.worldTransform = PIXI.mat3.create();
     	
    +	if(position)
    +	{
    +		displayObject.worldTransform[2] = position.x;
    +		displayObject.worldTransform[5] = position.y;
    +	}
    +	
    +
     	for(var i=0,j=children.length; i<j; i++)
     	{
     		children[i].updateTransform();	
     	}
     
     	if(clear)this.renderer.context.clearRect(0,0, this.width, this.height);
    +	
         this.renderer.renderDisplayObject(displayObject);
         
    -    PIXI.texturesToUpdate.push(this.baseTexture);
    -}
    +    this.renderer.context.setTransform(1,0,0,1,0,0); 
    +    
     
    +  //  PIXI.texturesToUpdate.push(this.baseTexture);
    +}
     
         
    @@ -343,13 +428,13 @@ PIXI.RenderTexture.prototype.renderCanvas = function(displayObject, clear)
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_textures_Texture.js.html b/docs/files/src_pixi_textures_Texture.js.html index ac3027a..c60354b 100644 --- a/docs/files/src_pixi_textures_Texture.js.html +++ b/docs/files/src_pixi_textures_Texture.js.html @@ -2,12 +2,12 @@ - src/pixi/textures/Texture.js - Pixi.JS - - - - - + src/pixi/textures/Texture.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,63 +166,71 @@
    -

    File: src/pixi/textures/Texture.js

    +

    File: src/pixi/textures/Texture.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
     PIXI.TextureCache = {};
     PIXI.FrameCache = {};
     
    -/**
    - * A texture stores the information that represents an image or part of an image. It cannot be added to the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used
    +/**
    + * A texture stores the information that represents an image or part of an image. It cannot be added
    + * to the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used
    + *
      * @class Texture
    - * @extends EventTarget
    + * @uses EventTarget
      * @constructor
    - * @param baseTexture {BaseTexture}
    - * @param frmae {Rectangle}
    - */
    + * @param baseTexture {BaseTexture} The base texture source to create the texture from
    + * @param frame {Rectangle} The rectangle frame of the texture to show
    + */
     PIXI.Texture = function(baseTexture, frame)
     {
     	PIXI.EventTarget.call( this );
    -	
    +
     	if(!frame)
     	{
     		this.noFrame = true;
     		frame = new PIXI.Rectangle(0,0,1,1);
     	}
    -	
    -	this.trim = new PIXI.Point();
     
     	if(baseTexture instanceof PIXI.Texture)
     		baseTexture = baseTexture.baseTexture;
    -	
    -	/**
    +
    +	/**
     	 * The base texture of this texture
    +	 *
     	 * @property baseTexture
     	 * @type BaseTexture
    -	 */
    +	 */
     	this.baseTexture = baseTexture;
    -	
    -	
    -	
    -	/**
    +
    +	/**
     	 * The frame specifies the region of the base texture that this texture uses
    +	 *
     	 * @property frame
    -	 * @type #Rectangle
    -	 */
    +	 * @type Rectangle
    +	 */
     	this.frame = frame;
    -	
    +
    +	/**
    +	 * The trim point
    +	 *
    +	 * @property trim
    +	 * @type Point
    +	 */
    +	this.trim = new PIXI.Point();
    +
     	this.scope = this;
    -	
    +
     	if(baseTexture.hasLoaded)
     	{
     		if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height);
    -		//console.log(frame)
    -		
    +		//console.log(frame)
    +
     		this.setFrame(frame);
     	}
     	else
    @@ -208,78 +240,94 @@ PIXI.Texture = function(baseTexture, frame)
     	}
     }
     
    -PIXI.Texture.constructor = PIXI.Texture;
    +PIXI.Texture.prototype.constructor = PIXI.Texture;
     
    +/**
    + * Called when the base texture is loaded
    + *
    + * @method onBaseTextureLoaded
    + * @param event
    + * @private
    + */
     PIXI.Texture.prototype.onBaseTextureLoaded = function(event)
     {
     	var baseTexture = this.baseTexture;
     	baseTexture.removeEventListener( 'loaded', this.onLoaded );
    -	
    +
     	if(this.noFrame)this.frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height);
     	this.noFrame = false;
     	this.width = this.frame.width;
     	this.height = this.frame.height;
    -	
    +
     	this.scope.dispatchEvent( { type: 'update', content: this } );
     }
     
    +/**
    + * Destroys this texture
    + *
    + * @method destroy
    + * @param destroyBase {Boolean} Whether to destroy the base texture as well
    + */
     PIXI.Texture.prototype.destroy = function(destroyBase)
     {
     	if(destroyBase)this.baseTexture.destroy();
     }
     
    -/**
    +/**
      * Specifies the rectangle region of the baseTexture
    + *
      * @method setFrame
    - * @param frame {Rectangle}
    - */
    + * @param frame {Rectangle} The frame of the texture to set it to
    + */
     PIXI.Texture.prototype.setFrame = function(frame)
     {
     	this.frame = frame;
     	this.width = frame.width;
     	this.height = frame.height;
    -	
    +
     	if(frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height)
     	{
     		throw new Error("Texture Error: frame does not fit inside the base Texture dimensions " + this);
     	}
    -	
    +
     	this.updateFrame = true;
    -	
    +
     	PIXI.Texture.frameUpdates.push(this);
    -	//this.dispatchEvent( { type: 'update', content: this } );
    +	//this.dispatchEvent( { type: 'update', content: this } );
     }
     
    -/**
    - * 
    +/**
      * Helper function that returns a texture based on an image url
      * If the image is not in the texture cache it will be  created and loaded
    + *
      * @static
      * @method fromImage
      * @param imageUrl {String} The image url of the texture
    + * @param crossorigin {Boolean} Whether requests should be treated as crossorigin
      * @return Texture
    - */
    + */
     PIXI.Texture.fromImage = function(imageUrl, crossorigin)
     {
     	var texture = PIXI.TextureCache[imageUrl];
    -	
    +
     	if(!texture)
     	{
     		texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin));
     		PIXI.TextureCache[imageUrl] = texture;
     	}
    -	
    +
     	return texture;
     }
     
    -/**
    - * 
    +/**
      * Helper function that returns a texture based on a frame id
      * If the frame id is not in the texture cache an error will be thrown
    + *
    + * @static
      * @method fromFrame
      * @param frameId {String} The frame id of the texture
      * @return Texture
    - */
    + */
     PIXI.Texture.fromFrame = function(frameId)
     {
     	var texture = PIXI.TextureCache[frameId];
    @@ -287,15 +335,15 @@ PIXI.Texture.fromFrame = function(frameId)
     	return texture;
     }
     
    -/**
    - * 
    +/**
      * Helper function that returns a texture based on a canvas element
      * If the canvas is not in the texture cache it will be  created and loaded
    + *
      * @static
      * @method fromCanvas
      * @param canvas {Canvas} The canvas element source of the texture
      * @return Texture
    - */
    + */
     PIXI.Texture.fromCanvas = function(canvas)
     {
     	var	baseTexture = new PIXI.BaseTexture(canvas);
    @@ -303,27 +351,27 @@ PIXI.Texture.fromCanvas = function(canvas)
     }
     
     
    -/**
    - * 
    - * Adds a texture to the textureCache. 
    +/**
    + * Adds a texture to the textureCache.
    + *
      * @static
      * @method addTextureToCache
      * @param texture {Texture}
      * @param id {String} the id that the texture will be stored against.
    - */
    + */
     PIXI.Texture.addTextureToCache = function(texture, id)
     {
     	PIXI.TextureCache[id] = texture;
     }
     
    -/**
    - * 
    - * Remove a texture from the textureCache. 
    +/**
    + * Remove a texture from the textureCache.
    + *
      * @static
      * @method removeTextureFromCache
      * @param id {String} the id of the texture to be removed
      * @return {Texture} the texture that was removed
    - */
    + */
     PIXI.Texture.removeTextureFromCache = function(id)
     {
     	var texture = PIXI.TextureCache[id]
    @@ -331,7 +379,7 @@ PIXI.Texture.removeTextureFromCache = function(id)
     	return texture;
     }
     
    -// this is more for webGL.. it contains updated frames..
    +// this is more for webGL.. it contains updated frames..
     PIXI.Texture.frameUpdates = [];
     
     
    @@ -344,13 +392,13 @@ PIXI.Texture.frameUpdates = [];
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_utils_Detector.js.html b/docs/files/src_pixi_utils_Detector.js.html index 7dbe0d9..34e1f5a 100644 --- a/docs/files/src_pixi_utils_Detector.js.html +++ b/docs/files/src_pixi_utils_Detector.js.html @@ -2,12 +2,12 @@ - src/pixi/utils/Detector.js - Pixi.JS - - - - - + src/pixi/utils/Detector.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,37 +166,47 @@
    -

    File: src/pixi/utils/Detector.js

    +

    File: src/pixi/utils/Detector.js

    -/**
    - * @author Mat Groves http://matgroves.com/ @Doormat23
    - */
    +/**
    + * @author Mat Groves http://matgroves.com/ @Doormat23
    + */
     
    -/**
    +/**
      * This helper function will automatically detect which renderer you should be using.
    - * WebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by the browser then this function will return a canvas renderer
    + * WebGL is the preferred renderer as it is a lot fastest. If webGL is not supported by
    + * the browser then this function will return a canvas renderer
    + *
      * @method autoDetectRenderer
      * @static
      * @param width {Number} the width of the renderers view
      * @param height {Number} the height of the renderers view
      * @param view {Canvas} the canvas to use as a view, optional
    - * @param transparent {Boolean} the transparency of the render view, default false
    - * @default false
    - */
    -PIXI.autoDetectRenderer = function(width, height, view, transparent)
    + * @param transparent=false {Boolean} the transparency of the render view, default false
    + * @param antialias=false {Boolean} sets antialias (only applicable in webGL chrome at the moment)
    + *
    + * antialias
    + */
    +PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias)
     {
     	if(!width)width = 800;
     	if(!height)height = 600;
     
    -	// BORROWED from Mr Doob (mrdoob.com)
    -	var webgl = ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )();
    +	// BORROWED from Mr Doob (mrdoob.com)
    +	var webgl = ( function () { try { var canvas = document.createElement( 'canvas' ); return !! window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ); } catch( e ) { return false; } } )();
     
    -	//console.log(webgl);
    +	if(webgl)
    +	{
    +		var ie =  (navigator.userAgent.toLowerCase().indexOf('msie') != -1);
    +		 webgl = !ie;
    +	}
    +	
    +	//console.log(webgl);
     	if( webgl )
     	{
    -		return new PIXI.WebGLRenderer(width, height, view, transparent);
    +		return new PIXI.WebGLRenderer(width, height, view, transparent, antialias);
     	}
     
     	return	new PIXI.CanvasRenderer(width, height, view, transparent);
    @@ -189,13 +223,13 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent)
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_utils_EventTarget.js.html b/docs/files/src_pixi_utils_EventTarget.js.html index e49f174..63cb9dd 100644 --- a/docs/files/src_pixi_utils_EventTarget.js.html +++ b/docs/files/src_pixi_utils_EventTarget.js.html @@ -2,12 +2,12 @@ - src/pixi/utils/EventTarget.js - Pixi.JS - - - - - + src/pixi/utils/EventTarget.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,26 +166,38 @@
    -

    File: src/pixi/utils/EventTarget.js

    +

    File: src/pixi/utils/EventTarget.js

    -/**
    - * https://github.com/mrdoob/eventtarget.js/
    +/**
    + * https://github.com/mrdoob/eventtarget.js/
      * THankS mr DOob!
    - */
    + */
     
    +/**
    + * Adds event emitter functionality to a class
    + *
    + * @class EventTarget
    + * @example
    + *		function MyEmitter() {
    + *			PIXI.EventTarget.call(this); //mixes in event target stuff
    + *		}
    + *
    + *		var em = new MyEmitter();
    + *		em.emit({ type: 'eventName', data: 'some data' });
    + */
     PIXI.EventTarget = function () {
     
     	var listeners = {};
    -	
    +
     	this.addEventListener = this.on = function ( type, listener ) {
    -		
    -		
    +
    +
     		if ( listeners[ type ] === undefined ) {
     
     			listeners[ type ] = [];
    -			
    +
     		}
     
     		if ( listeners[ type ].indexOf( listener ) === - 1 ) {
    @@ -172,11 +208,17 @@ PIXI.EventTarget = function () {
     	};
     
     	this.dispatchEvent = this.emit = function ( event ) {
    -		
    -		for ( var listener in listeners[ event.type ] ) {
     
    -			listeners[ event.type ][ listener ]( event );
    -			
    +		if ( !listeners[ event.type ] || !listeners[ event.type ].length ) {
    +
    +			return;
    +
    +		}
    +
    +		for(var i = 0, l = listeners[ event.type ].length; i < l; i++) {
    +
    +			listeners[ event.type ][ i ]( event );
    +
     		}
     
     	};
    @@ -204,13 +246,13 @@ PIXI.EventTarget = function () {
             
    - + - - - - - - + + + + + + diff --git a/docs/files/src_pixi_utils_Polyk.js.html b/docs/files/src_pixi_utils_Polyk.js.html new file mode 100644 index 0000000..00d055c --- /dev/null +++ b/docs/files/src_pixi_utils_Polyk.js.html @@ -0,0 +1,341 @@ + + + + + src/pixi/utils/Polyk.js - Pixi.JS + + + + + + + + +
    +
    +
    + +

    + +
    +
    + API Docs for: 1.3.0 +
    +
    +
    + + +
    +
    + Show: + + + + + + + +
    + + +
    +
    +
    +

    File: src/pixi/utils/Polyk.js

    + +
    +
    +/*
    +	PolyK library
    +	url: http://polyk.ivank.net
    +	Released under MIT licence.
    +
    +	Copyright (c) 2012 Ivan Kuckir
    +
    +	Permission is hereby granted, free of charge, to any person
    +	obtaining a copy of this software and associated documentation
    +	files (the "Software"), to deal in the Software without
    +	restriction, including without limitation the rights to use,
    +	copy, modify, merge, publish, distribute, sublicense, and/or sell
    +	copies of the Software, and to permit persons to whom the
    +	Software is furnished to do so, subject to the following
    +	conditions:
    +
    +	The above copyright notice and this permission notice shall be
    +	included in all copies or substantial portions of the Software.
    +
    +	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
    +	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    +	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    +	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    +	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    +	OTHER DEALINGS IN THE SOFTWARE.
    +
    +	This is an amazing lib!
    +
    +	slightly modified by mat groves (matgroves.com);
    +*/
    +
    +PIXI.PolyK = {};
    +
    +/**
    + * Triangulates shapes for webGL graphic fills
    + *
    + * @method Triangulate
    + * @namespace PolyK
    + * @constructor
    + */
    +PIXI.PolyK.Triangulate = function(p)
    +{
    +	var sign = true;
    +
    +	var n = p.length>>1;
    +	if(n<3) return [];
    +	var tgs = [];
    +	var avl = [];
    +	for(var i=0; i<n; i++) avl.push(i);
    +
    +	var i = 0;
    +	var al = n;
    +	while(al > 3)
    +	{
    +		var i0 = avl[(i+0)%al];
    +		var i1 = avl[(i+1)%al];
    +		var i2 = avl[(i+2)%al];
    +
    +		var ax = p[2*i0],  ay = p[2*i0+1];
    +		var bx = p[2*i1],  by = p[2*i1+1];
    +		var cx = p[2*i2],  cy = p[2*i2+1];
    +
    +		var earFound = false;
    +		if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign))
    +		{
    +			earFound = true;
    +			for(var j=0; j<al; j++)
    +			{
    +				var vi = avl[j];
    +				if(vi==i0 || vi==i1 || vi==i2) continue;
    +				if(PIXI.PolyK._PointInTriangle(p[2*vi], p[2*vi+1], ax, ay, bx, by, cx, cy)) {earFound = false; break;}
    +			}
    +		}
    +		if(earFound)
    +		{
    +			tgs.push(i0, i1, i2);
    +			avl.splice((i+1)%al, 1);
    +			al--;
    +			i = 0;
    +		}
    +		else if(i++ > 3*al)
    +		{
    +			// need to flip flip reverse it!
    +			// reset!
    +			if(sign)
    +			{
    +				var tgs = [];
    +				avl = [];
    +				for(var i=0; i<n; i++) avl.push(i);
    +
    +				i = 0;
    +				al = n;
    +
    +				sign = false;
    +			}
    +			else
    +			{
    +				console.log("PIXI Warning: shape too complex to fill")
    +				return [];
    +			}
    +		}
    +	}
    +	tgs.push(avl[0], avl[1], avl[2]);
    +	return tgs;
    +}
    +
    +/**
    + * Checks if a point is within a triangle
    + *
    + * @class _PointInTriangle
    + * @namespace PolyK
    + * @private
    + */
    +PIXI.PolyK._PointInTriangle = function(px, py, ax, ay, bx, by, cx, cy)
    +{
    +	var v0x = cx-ax;
    +	var v0y = cy-ay;
    +	var v1x = bx-ax;
    +	var v1y = by-ay;
    +	var v2x = px-ax;
    +	var v2y = py-ay;
    +
    +	var dot00 = v0x*v0x+v0y*v0y;
    +	var dot01 = v0x*v1x+v0y*v1y;
    +	var dot02 = v0x*v2x+v0y*v2y;
    +	var dot11 = v1x*v1x+v1y*v1y;
    +	var dot12 = v1x*v2x+v1y*v2y;
    +
    +	var invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
    +	var u = (dot11 * dot02 - dot01 * dot12) * invDenom;
    +	var v = (dot00 * dot12 - dot01 * dot02) * invDenom;
    +
    +	// Check if point is in triangle
    +	return (u >= 0) && (v >= 0) && (u + v < 1);
    +}
    +
    +/**
    + * Checks if a shape is convex
    + *
    + * @class _convex
    + * @namespace PolyK
    + * @private
    + */
    +PIXI.PolyK._convex = function(ax, ay, bx, by, cx, cy, sign)
    +{
    +	return ((ay-by)*(cx-bx) + (bx-ax)*(cy-by) >= 0) == sign;
    +}
    +
    +    
    +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + diff --git a/docs/files/src_pixi_utils_Utils.js.html b/docs/files/src_pixi_utils_Utils.js.html index 0e7d63a..15fcb57 100644 --- a/docs/files/src_pixi_utils_Utils.js.html +++ b/docs/files/src_pixi_utils_Utils.js.html @@ -2,12 +2,12 @@ - src/pixi/utils/Utils.js - Pixi.JS - - - - - + src/pixi/utils/Utils.js - Pixi.JS + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -142,90 +166,113 @@
    -

    File: src/pixi/utils/Utils.js

    +

    File: src/pixi/utils/Utils.js

    -// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
    -// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
    +// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
    +// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
     
    -// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
    +// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
     
    -// MIT license
    +// MIT license
     
    +/**
    + * A polyfill for requestAnimationFrame
    + *
    + * @method requestAnimationFrame
    + */
    +/**
    + * A polyfill for cancelAnimationFrame
    + *
    + * @method cancelAnimationFrame
    + */
    +var lastTime = 0;
    +var vendors = ['ms', 'moz', 'webkit', 'o'];
    +for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
    +    window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
    +    window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
    +                               || window[vendors[x]+'CancelRequestAnimationFrame'];
    +}
     
    -    var lastTime = 0;
    -    var vendors = ['ms', 'moz', 'webkit', 'o'];
    -    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
    -        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
    -        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 
    -                                   || window[vendors[x]+'CancelRequestAnimationFrame'];
    -    }
    +if (!window.requestAnimationFrame)
    +    window.requestAnimationFrame = function(callback, element) {
    +        var currTime = new Date().getTime();
    +        var timeToCall = Math.max(0, 16 - (currTime - lastTime));
    +        var id = window.setTimeout(function() { callback(currTime + timeToCall); },
    +          timeToCall);
    +        lastTime = currTime + timeToCall;
    +        return id;
    +    };
     
    -    if (!window.requestAnimationFrame)
    -        window.requestAnimationFrame = function(callback, element) {
    -            var currTime = new Date().getTime();
    -            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
    -            var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 
    -              timeToCall);
    -            lastTime = currTime + timeToCall;
    -            return id;
    -        };
    -
    -    if (!window.cancelAnimationFrame)
    -        window.cancelAnimationFrame = function(id) {
    -            clearTimeout(id);
    -        };
    +if (!window.cancelAnimationFrame)
    +    window.cancelAnimationFrame = function(id) {
    +        clearTimeout(id);
    +    };
     
     window.requestAnimFrame = window.requestAnimationFrame;
     
    +/**
    + * Converts a hex color number to an [R, G, B] array
    + *
    + * @method HEXtoRGB
    + * @param hex {Number}
    + */
     function HEXtoRGB(hex) {
    -	return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255];
    +	return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255];
     }
     
    -/**
    - * Provides bind in a cross browser way.
    - */
    +/**
    + * A polyfill for Function.prototype.bind
    + *
    + * @method bind
    + */
     if (typeof Function.prototype.bind != 'function') {
       Function.prototype.bind = (function () {
         var slice = Array.prototype.slice;
         return function (thisArg) {
           var target = this, boundArgs = slice.call(arguments, 1);
    - 
    +
           if (typeof target != 'function') throw new TypeError();
    - 
    +
           function bound() {
     	var args = boundArgs.concat(slice.call(arguments));
     	target.apply(this instanceof bound ? this : thisArg, args);
           }
    - 
    +
           bound.prototype = (function F(proto) {
               proto && (F.prototype = proto);
    -          if (!(this instanceof F)) return new F;          
    +          if (!(this instanceof F)) return new F;
     	})(target.prototype);
    - 
    +
           return bound;
         };
       })();
     }
     
    +/**
    + * A wrapper for ajax requests to be handled cross browser
    + *
    + * @class AjaxRequest
    + * @constructor
    + */
     var AjaxRequest = PIXI.AjaxRequest = function()
     {
    -	var activexmodes = ["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"] //activeX versions to check for in IE
    -	
    +	var activexmodes = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Microsoft.XMLHTTP"] //activeX versions to check for in IE
    +
     	if (window.ActiveXObject)
    -	{ //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken)
    +	{ //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken)
     		for (var i=0; i<activexmodes.length; i++)
     		{
     			try{
     				return new ActiveXObject(activexmodes[i])
     			}
        			catch(e){
    -    			//suppress error
    +    			//suppress error
        			}
     		}
     	}
    -	else if (window.XMLHttpRequest) // if Mozilla, Safari etc
    +	else if (window.XMLHttpRequest) // if Mozilla, Safari etc
       	{
       		return new XMLHttpRequest()
      	}
    @@ -235,9 +282,9 @@ var AjaxRequest = PIXI.AjaxRequest = function()
      	}
     }
     
    -/*
    +/*
      * DEBUGGING ONLY
    - */
    + */
     PIXI.runList = function(item)
     {
     	console.log(">>>>>>>>>")
    @@ -245,21 +292,20 @@ PIXI.runList = function(item)
     	var safe = 0;
     	var tmp = item.first;
     	console.log(tmp);
    -	
    +
     	while(tmp._iNext)
     	{
     		safe++;
    -//		console.log(tmp.childIndex + tmp);
     		tmp = tmp._iNext;
    -		console.log(tmp);//.childIndex);
    -	//	console.log(tmp);
    -	
    +		console.log(tmp);
    +	//	console.log(tmp);
    +
     		if(safe > 100)
     		{
     			console.log("BREAK")
     			break
     		}
    -	}	
    +	}
     }
     
     
    @@ -276,13 +322,13 @@ PIXI.runList = function(item)
             
    - + - - - - - - + + + + + + diff --git a/docs/index.html b/docs/index.html index 6de3004..1b0f5e0 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3,11 +3,11 @@ Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    - + - - - - - - + + + + + + diff --git a/docs/modules/PIXI.html b/docs/modules/PIXI.html index 52f88e4..9a9e653 100644 --- a/docs/modules/PIXI.html +++ b/docs/modules/PIXI.html @@ -3,11 +3,11 @@ PIXI - Pixi.JS - - - - - + + + + + @@ -15,7 +15,7 @@
    -

    +

    @@ -41,71 +41,95 @@ @@ -150,7 +174,7 @@ @@ -173,181 +197,253 @@
    - + - - - - - - + + + + + + diff --git a/src/pixi/display/DisplayObject.js b/src/pixi/display/DisplayObject.js index 59e2b54..256c8ca 100644 --- a/src/pixi/display/DisplayObject.js +++ b/src/pixi/display/DisplayObject.js @@ -316,13 +316,11 @@ Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', { }); /** - * Sets the filters for the displayObject. Currently there's a few limitations. - * 1: At the moment only one filter can be applied at a time.. - * 2: They cannot be nested. - * 3: There's no padding yet. - * 4: this is a webGL only feature. + * Sets the filters for the displayObject. + * * IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer. + * To remove filters simply set this property to 'null' * @property filters - * @type Array + * @type Array An array of filters */ Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', { get: function() { diff --git a/src/pixi/filters/AbstractFilter.js b/src/pixi/filters/AbstractFilter.js index 33bde01..c1e22b4 100644 --- a/src/pixi/filters/AbstractFilter.js +++ b/src/pixi/filters/AbstractFilter.js @@ -3,14 +3,33 @@ */ - +/** + * This is the base class for creating a pixi.js filter. Currently only webGL supports filters. + * If you want to make a custom filter this should be your base class. + * @class AbstractFilter + * @constructor + * @param fragmentSrc + * @param unifroms + */ PIXI.AbstractFilter = function(fragmentSrc, unifroms) { + /** + * An array of passes - some filters contain a few steps this array simply stores the steps in a liniear fashion. + * For example the blur filter has two passes blurX and blurY. + * @property passes + * @type Array an array of filter objects + * @private + */ this.passes = [this]; + + this.dirty = true; this.padding = 0; - // set the uniforms + /** + @property uniforms + @private + */ this.uniforms = unifroms || {}; this.fragmentSrc = fragmentSrc || []; diff --git a/src/pixi/filters/BlurFilter.js b/src/pixi/filters/BlurFilter.js index 46560ff..bf2c07d 100644 --- a/src/pixi/filters/BlurFilter.js +++ b/src/pixi/filters/BlurFilter.js @@ -3,7 +3,14 @@ */ - +/** + * + * The BlurFilter applies a Gaussian blur to an object. + * The strength of the blur can be set for x- and y-axis separately (always relative to the stage). + * + * @class BlurFilter + * @contructor + */ PIXI.BlurFilter = function() { @@ -14,6 +21,13 @@ PIXI.BlurFilter = function() } +/** + * Sets the strength of both the blurX and blurY properties simultaneously + * + * @property blur + * @type Number the strength of the blur + * @default 2 + */ Object.defineProperty(PIXI.BlurFilter.prototype, 'blur', { get: function() { return this.blurX.blur; @@ -23,7 +37,13 @@ Object.defineProperty(PIXI.BlurFilter.prototype, 'blur', { } }); - +/** + * Sets the strength of the blurX property simultaneously + * + * @property blurX + * @type Number the strength of the blurX + * @default 2 + */ Object.defineProperty(PIXI.BlurFilter.prototype, 'blurX', { get: function() { return this.blurXFilter.blur; @@ -33,6 +53,13 @@ Object.defineProperty(PIXI.BlurFilter.prototype, 'blurX', { } }); +/** + * Sets the strength of the blurX property simultaneously + * + * @property blurY + * @type Number the strength of the blurY + * @default 2 + */ Object.defineProperty(PIXI.BlurFilter.prototype, 'blurY', { get: function() { return this.blurYFilter.blur; diff --git a/src/pixi/filters/ColorMatrixFilter.js b/src/pixi/filters/ColorMatrixFilter.js index feeaf53..1386f8b 100644 --- a/src/pixi/filters/ColorMatrixFilter.js +++ b/src/pixi/filters/ColorMatrixFilter.js @@ -2,6 +2,14 @@ * @author Mat Groves http://matgroves.com/ @Doormat23 */ +/** + * + * The ColorMatrixFilter class lets you apply a 4x4 matrix transformation on the RGBA + * color and alpha values of every pixel on your displayObject to produce a result + * with a new set of RGBA color and alpha values. Its pretty powerful! + * @class ColorMatrixFilter + * @contructor + */ PIXI.ColorMatrixFilter = function() { PIXI.AbstractFilter.call( this ); @@ -34,6 +42,13 @@ PIXI.ColorMatrixFilter = function() PIXI.ColorMatrixFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); PIXI.ColorMatrixFilter.prototype.constructor = PIXI.ColorMatrixFilter; +/** + * Sets the matrix of the color matrix filter + * + * @property matrix + * @type Array and array of 26 numbers + * @default [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1] + */ Object.defineProperty(PIXI.ColorMatrixFilter.prototype, 'matrix', { get: function() { return this.uniforms.matrix.value; diff --git a/src/pixi/filters/DisplacementFilter.js b/src/pixi/filters/DisplacementFilter.js index dec7b27..6c05498 100644 --- a/src/pixi/filters/DisplacementFilter.js +++ b/src/pixi/filters/DisplacementFilter.js @@ -3,7 +3,15 @@ */ - +/** + * + * The DisplacementFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object. + * You can use this filter to apply all manor of crazy warping effects + * Currently the r property of the texture is used offset the x and the g propery of the texture is used to offset the y. + * @class DisplacementFilter + * @contructor + * @param texture {Texture} The texture used for the displacemtent map * must be power of 2 texture at the moment + */ PIXI.DisplacementFilter = function(texture) { PIXI.AbstractFilter.call( this ); @@ -11,7 +19,6 @@ PIXI.DisplacementFilter = function(texture) this.passes = [this]; texture.baseTexture._powerOf2 = true; - // set the uniforms //console.log() this.uniforms = { @@ -82,6 +89,12 @@ PIXI.DisplacementFilter.prototype.onTextureLoaded = function() } +/** + * The texture used for the displacemtent map * must be power of 2 texture at the moment + * + * @property map + * @type Texture + */ Object.defineProperty(PIXI.DisplacementFilter.prototype, 'map', { get: function() { return this.uniforms.displacementMap.value; @@ -91,6 +104,12 @@ Object.defineProperty(PIXI.DisplacementFilter.prototype, 'map', { } }); +/** + * The multiplier used to scale the displacement result from the map calculation. + * + * @property scale + * @type Point + */ Object.defineProperty(PIXI.DisplacementFilter.prototype, 'scale', { get: function() { return this.uniforms.scale.value; @@ -100,6 +119,12 @@ Object.defineProperty(PIXI.DisplacementFilter.prototype, 'scale', { } }); +/** + * The offset used to move the displacement map. + * + * @property offset + * @type Point + */ Object.defineProperty(PIXI.DisplacementFilter.prototype, 'offset', { get: function() { return this.uniforms.offset.value; diff --git a/src/pixi/filters/GreyFilter.js b/src/pixi/filters/GreyFilter.js index c30cb18..d182975 100644 --- a/src/pixi/filters/GreyFilter.js +++ b/src/pixi/filters/GreyFilter.js @@ -3,7 +3,12 @@ */ - +/** + * + * This turns your displayObjects to black and white. + * @class GreyFilter + * @contructor + */ PIXI.GreyFilter = function() { PIXI.AbstractFilter.call( this ); @@ -32,6 +37,10 @@ PIXI.GreyFilter = function() PIXI.GreyFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); PIXI.GreyFilter.prototype.constructor = PIXI.GreyFilter; +/** +The strength of the grey. 1 will make the object black and white, 0 will make the object its normal color +@property grey +*/ Object.defineProperty(PIXI.GreyFilter.prototype, 'grey', { get: function() { return this.uniforms.grey.value; diff --git a/src/pixi/filters/InvertFilter.js b/src/pixi/filters/InvertFilter.js index 368cc7d..4566786 100644 --- a/src/pixi/filters/InvertFilter.js +++ b/src/pixi/filters/InvertFilter.js @@ -2,6 +2,12 @@ * @author Mat Groves http://matgroves.com/ @Doormat23 */ +/** + * + * This inverts your displayObjects colors. + * @class InvertFilter + * @contructor + */ PIXI.InvertFilter = function() { PIXI.AbstractFilter.call( this ); @@ -32,6 +38,10 @@ PIXI.InvertFilter = function() PIXI.InvertFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); PIXI.InvertFilter.prototype.constructor = PIXI.InvertFilter; +/** +The strength of the invert. 1 will fully invert the colors, 0 will make the object its normal color +@property invert +*/ Object.defineProperty(PIXI.InvertFilter.prototype, 'invert', { get: function() { return this.uniforms.invert.value; diff --git a/src/pixi/filters/PixelateFilter.js b/src/pixi/filters/PixelateFilter.js index 3303ac4..bc6eb35 100644 --- a/src/pixi/filters/PixelateFilter.js +++ b/src/pixi/filters/PixelateFilter.js @@ -2,6 +2,12 @@ * @author Mat Groves http://matgroves.com/ @Doormat23 */ +/** + * + * This filter applies a pixlate effect making display objects appear "blocky" + * @class PixelateFilter + * @contructor + */ PIXI.PixelateFilter = function() { PIXI.AbstractFilter.call( this ); @@ -26,11 +32,9 @@ PIXI.PixelateFilter = function() "void main(void) {", "vec2 coord = vTextureCoord;", - // "vec2 dim = testDim;", "vec2 size = dimensions.xy/pixelSize;", "vec2 color = floor( ( vTextureCoord * size ) ) / size + pixelSize/dimensions.xy * 0.5;", - // "color += (mod(dimensions.xy, size)/dimensions.zw;", "gl_FragColor = texture2D(uSampler, color);", "}" ]; @@ -41,6 +45,12 @@ PIXI.PixelateFilter = function() PIXI.PixelateFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); PIXI.PixelateFilter.prototype.constructor = PIXI.PixelateFilter; +/** + * + * This a point that describes the size of the blocs. x is the width of the block and y is the the height + * @property size + * @type Point + */ Object.defineProperty(PIXI.PixelateFilter.prototype, 'size', { get: function() { return this.uniforms.pixelSize.value; diff --git a/src/pixi/filters/SepiaFilter.js b/src/pixi/filters/SepiaFilter.js index bba9b88..b320933 100644 --- a/src/pixi/filters/SepiaFilter.js +++ b/src/pixi/filters/SepiaFilter.js @@ -4,7 +4,12 @@ */ - +/** + * + * This applies a sepia effect to your displayObjects. + * @class SepiaFilter + * @contructor + */ PIXI.SepiaFilter = function() { PIXI.AbstractFilter.call( this ); @@ -36,6 +41,10 @@ PIXI.SepiaFilter = function() PIXI.SepiaFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); PIXI.SepiaFilter.prototype.constructor = PIXI.SepiaFilter; +/** +The strength of the sepia. 1 will apply the full sepia effect, 0 will make the object its normal color +@property sepia +*/ Object.defineProperty(PIXI.SepiaFilter.prototype, 'sepia', { get: function() { return this.uniforms.sepia.value; From 932ca800329278988e18e26043b5b4305931a544 Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Sat, 2 Nov 2013 15:51:02 +0000 Subject: [PATCH 64/96] All Filter Exampls Added Example 16 removed as no longer required added Color step filter added Twist filter added Dot screen --- Gruntfile.js | 4 + bin/pixi.dev.js | 247 +++++++++++++++++- bin/pixi.dev.js.map | 5 +- bin/pixi.js | 3 +- examples/example 15 - Filters/dat.gui.min.js | 94 +++++++ examples/example 15 - Filters/indexAll.html | 95 ++++++- .../example 16 - Displacement/BGrotate.jpg | Bin 139735 -> 0 bytes .../LightRotate1.png | Bin 213699 -> 0 bytes .../LightRotate2.png | Bin 173189 -> 0 bytes .../example 16 - Displacement/SceneRotate.jpg | Bin 113742 -> 0 bytes examples/example 16 - Displacement/index.html | 213 --------------- examples/example 16 - Displacement/map.png | Bin 96515 -> 0 bytes examples/example 16 - Displacement/map2.png | Bin 72052 -> 0 bytes examples/example 16 - Displacement/panda.png | Bin 69177 -> 0 bytes src/pixi/filters/BlurFilter.js | 2 +- src/pixi/filters/ColorStepFilter.js | 51 ++++ src/pixi/filters/DotScreenFilter.js | 86 ++++++ src/pixi/filters/InvertFilter.js | 4 +- src/pixi/filters/TwistFilter.js | 103 ++++++++ 19 files changed, 685 insertions(+), 222 deletions(-) create mode 100644 examples/example 15 - Filters/dat.gui.min.js delete mode 100644 examples/example 16 - Displacement/BGrotate.jpg delete mode 100644 examples/example 16 - Displacement/LightRotate1.png delete mode 100644 examples/example 16 - Displacement/LightRotate2.png delete mode 100644 examples/example 16 - Displacement/SceneRotate.jpg delete mode 100644 examples/example 16 - Displacement/index.html delete mode 100644 examples/example 16 - Displacement/map.png delete mode 100644 examples/example 16 - Displacement/map2.png delete mode 100644 examples/example 16 - Displacement/panda.png create mode 100644 src/pixi/filters/ColorStepFilter.js create mode 100644 src/pixi/filters/DotScreenFilter.js create mode 100644 src/pixi/filters/TwistFilter.js diff --git a/Gruntfile.js b/Gruntfile.js index 4d2ffee..3ec1587 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -68,6 +68,10 @@ module.exports = function(grunt) { '<%= dirs.src %>/filters/BlurFilter.js', '<%= dirs.src %>/filters/InvertFilter.js', '<%= dirs.src %>/filters/SepiaFilter.js', + '<%= dirs.src %>/filters/TwistFilter.js', + '<%= dirs.src %>/filters/ColorStepFilter.js', + '<%= dirs.src %>/filters/DotScreenFilter.js', + '<%= dirs.src %>/Outro.js' ], banner = [ '/**', diff --git a/bin/pixi.dev.js b/bin/pixi.dev.js index 067124e..c51a9d0 100644 --- a/bin/pixi.dev.js +++ b/bin/pixi.dev.js @@ -11713,7 +11713,7 @@ PIXI.BlurFilter = function() */ Object.defineProperty(PIXI.BlurFilter.prototype, 'blur', { get: function() { - return this.blurX.blur; + return this.blurXFilter.blur; }, set: function(value) { this.blurXFilter.blur = this.blurYFilter.blur = value; @@ -11770,7 +11770,7 @@ PIXI.InvertFilter = function() // set the uniforms this.uniforms = { - invert: {type: 'f', value: 0}, + invert: {type: 'f', value: 1}, }; this.fragmentSrc = [ @@ -11781,7 +11781,7 @@ PIXI.InvertFilter = function() "uniform sampler2D uSampler;", "void main(void) {", "gl_FragColor = texture2D(uSampler, vTextureCoord);", - "gl_FragColor.rgb = mix( (vec3(1)-gl_FragColor.rgb) * gl_FragColor.a, gl_FragColor.rgb, invert);", + "gl_FragColor.rgb = mix( (vec3(1)-gl_FragColor.rgb) * gl_FragColor.a, gl_FragColor.rgb, 1.0 - invert);", //"gl_FragColor.rgb = gl_FragColor.rgb * gl_FragColor.a;", "gl_FragColor = gl_FragColor * vColor;", "}" @@ -11860,6 +11860,247 @@ Object.defineProperty(PIXI.SepiaFilter.prototype, 'sepia', { } }); +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + +/** + * + * This filter applies a pixlate effect making display objects appear "blocky" + * @class PixelateFilter + * @contructor + */ +PIXI.TwistFilter = function() +{ + PIXI.AbstractFilter.call( this ); + + this.passes = [this]; + + // set the uniforms + this.uniforms = { + radius: {type: 'f', value:0.5}, + angle: {type: 'f', value:5}, + offset: {type: 'f2', value:{x:0.5, y:0.5}}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform vec4 dimensions;", + "uniform sampler2D uSampler;", + + "uniform float radius;", + "uniform float angle;", + "uniform vec2 offset;", + + "void main(void) {", + "vec2 coord = vTextureCoord - offset;", + "float distance = length(coord);", + + "if (distance < radius){", + + "float ratio = (radius - distance) / radius;", + "float angleMod = ratio * ratio * angle;", + "float s = sin(angleMod);", + "float c = cos(angleMod);", + "coord = vec2(coord.x * c - coord.y * s, coord.x * s + coord.y * c);", + + "}", + + "gl_FragColor = texture2D(uSampler, coord+offset);", + "}" + ]; +} + +PIXI.TwistFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); +PIXI.TwistFilter.prototype.constructor = PIXI.TwistFilter; + +/** + * + * This point describes the the offset of the twist + * @property size + * @type Point + */ +Object.defineProperty(PIXI.TwistFilter.prototype, 'offset', { + get: function() { + return this.uniforms.offset.value; + }, + set: function(value) { + this.dirty = true; + this.uniforms.offset.value = value; + } +}); + +/** + * + * This radius describes size of the twist + * @property size + * @type Number + */ +Object.defineProperty(PIXI.TwistFilter.prototype, 'radius', { + get: function() { + return this.uniforms.radius.value; + }, + set: function(value) { + this.dirty = true; + this.uniforms.radius.value = value; + } +}); + +/** + * + * This radius describes angle of the twist + * @property angle + * @type Number + */ +Object.defineProperty(PIXI.TwistFilter.prototype, 'angle', { + get: function() { + return this.uniforms.angle.value; + }, + set: function(value) { + this.dirty = true; + this.uniforms.angle.value = value; + } +}); +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + */ + + +/** + * + * This turns your displayObjects to black and white. + * @class GreyFilter + * @contructor + */ +PIXI.ColorStepFilter = function() +{ + PIXI.AbstractFilter.call( this ); + + this.passes = [this]; + + // set the uniforms + this.uniforms = { + step: {type: 'f', value: 5}, + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform sampler2D uSampler;", + "uniform float step;", + "void main(void) {", + "vec4 color = texture2D(uSampler, vTextureCoord);", + "color = floor(color * step) / step;", + "gl_FragColor = color * vColor;", + "}" + ]; +} + +PIXI.ColorStepFilter.prototype = Object.create( PIXI.AbstractFilter.prototype ); +PIXI.ColorStepFilter.prototype.constructor = PIXI.ColorStepFilter; + +/** +The number of steps. +@property step +*/ +Object.defineProperty(PIXI.ColorStepFilter.prototype, 'step', { + get: function() { + return this.uniforms.step.value; + }, + set: function(value) { + this.uniforms.step.value = value; + } +}); + +/** + * @author Mat Groves http://matgroves.com/ @Doormat23 + * original filter: https://github.com/evanw/glfx.js/blob/master/src/filters/fun/dotscreen.js + */ + +/** + * + * This filter applies a pixlate effect making display objects appear "blocky" + * @class PixelateFilter + * @contructor + */ +PIXI.DotScreenFilter = function() +{ + PIXI.AbstractFilter.call( this ); + + this.passes = [this]; + + // set the uniforms + this.uniforms = { + scale: {type: 'f', value:1}, + angle: {type: 'f', value:5}, + dimensions: {type: 'f4', value:[0,0,0,0]} + }; + + this.fragmentSrc = [ + "precision mediump float;", + "varying vec2 vTextureCoord;", + "varying float vColor;", + "uniform vec4 dimensions;", + "uniform sampler2D uSampler;", + + "uniform float angle;", + "uniform float scale;", + + "float pattern() {", + "float s = sin(angle), c = cos(angle);", + "vec2 tex = vTextureCoord * dimensions.xy;", + "vec2 point = vec2(", + "c * tex.x - s * tex.y,", + "s * tex.x + c * tex.y", + ") * scale;", + "return (sin(point.x) * sin(point.y)) * 4.0;", + "}", + + "void main() {", + "vec4 color = texture2D(uSampler, vTextureCoord);", + "float average = (color.r + color.g + color.b) / 3.0;", + "gl_FragColor = vec4(vec3(average * 10.0 - 5.0 + pattern()), color.a);", + "}", + ]; +} + +PIXI.DotScreenFilter.prototype = Object.create( PIXI.DotScreenFilter.prototype ); +PIXI.DotScreenFilter.prototype.constructor = PIXI.DotScreenFilter; + +/** + * + * This describes the the scale + * @property scale + * @type Number + */ +Object.defineProperty(PIXI.DotScreenFilter.prototype, 'scale', { + get: function() { + return this.uniforms.scale.value; + }, + set: function(value) { + this.dirty = true; + this.uniforms.scale.value = value; + } +}); + +/** + * + * This radius describes angle + * @property angle + * @type Number + */ +Object.defineProperty(PIXI.DotScreenFilter.prototype, 'angle', { + get: function() { + return this.uniforms.angle.value; + }, + set: function(value) { + this.dirty = true; + this.uniforms.angle.value = value; + } +}); /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ diff --git a/bin/pixi.dev.js.map b/bin/pixi.dev.js.map index 9706f9a..9c4ccbc 100644 --- a/bin/pixi.dev.js.map +++ b/bin/pixi.dev.js.map @@ -59,9 +59,12 @@ "src/pixi/filters/BlurFilter.js", "src/pixi/filters/InvertFilter.js", "src/pixi/filters/SepiaFilter.js", + "src/pixi/filters/TwistFilter.js", + "src/pixi/filters/ColorStepFilter.js", + "src/pixi/filters/DotScreenFilter.js", "src/pixi/Outro.js" ], "names": [], - "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sB;AC5jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACngBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5+BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACpgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACn7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACpKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,c", + "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sB;AC5jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACnWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACngBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5+BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACpgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACn7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACpKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,E;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,G;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,c", "sourceRoot": "../" } \ No newline at end of file diff --git a/bin/pixi.js b/bin/pixi.js index 4af7eaf..46d5683 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -12,4 +12,5 @@ !function(){function c(){return f.Matrix="undefined"!=typeof Float32Array?Float32Array:Array,f.Matrix}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}function d(a){return[(255&a>>16)/255,(255&a>>8)/255,(255&a)/255]}var e=this,f=f||{};f.Point=function(a,b){this.x=a||0,this.y=b||0},f.Point.prototype.clone=function(){return new f.Point(this.x,this.y)},f.Point.prototype.constructor=f.Point,f.Rectangle=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Rectangle.prototype.clone=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Rectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},f.Rectangle.prototype.constructor=f.Rectangle,f.Polygon=function(a){if(a instanceof Array||(a=Array.prototype.slice.call(arguments)),"number"==typeof a[0]){for(var b=[],c=0,d=a.length;d>c;c+=2)b.push(new f.Point(a[c],a[c+1]));a=b}this.points=a},f.Polygon.prototype.clone=function(){for(var a=[],b=0;bb!=i>b&&(h-f)*(b-g)/(i-g)+f>a;j&&(c=!c)}return c},f.Polygon.prototype.constructor=f.Polygon,f.Circle=function(a,b,c){this.x=a||0,this.y=b||0,this.radius=c||0},f.Circle.prototype.clone=function(){return new f.Circle(this.x,this.y,this.radius)},f.Circle.prototype.contains=function(a,b){if(this.radius<=0)return!1;var c=this.x-a,d=this.y-b,e=this.radius*this.radius;return c*=c,d*=d,e>=c+d},f.Circle.prototype.constructor=f.Circle,f.Ellipse=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},f.Ellipse.prototype.clone=function(){return new f.Ellipse(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=(a-this.x)/this.width-.5,d=(b-this.y)/this.height-.5;return c*=c,d*=d,.25>c+d},f.Ellipse.getBounds=function(){return new f.Rectangle(this.x,this.y,this.width,this.height)},f.Ellipse.prototype.constructor=f.Ellipse,c(),f.mat3={},f.mat3.create=function(){var a=new f.Matrix(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat3.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},f.mat4={},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat3.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=b[0],n=b[1],o=b[2],p=b[3],q=b[4],r=b[5],s=b[6],t=b[7],u=b[8];return c[0]=m*d+n*g+o*j,c[1]=m*e+n*h+o*k,c[2]=m*f+n*i+o*l,c[3]=p*d+q*g+r*j,c[4]=p*e+q*h+r*k,c[5]=p*f+q*i+r*l,c[6]=s*d+t*g+u*j,c[7]=s*e+t*h+u*k,c[8]=s*f+t*i+u*l,c},f.mat3.clone=function(a){var b=new f.Matrix(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},f.mat3.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[5];return a[1]=a[3],a[2]=a[6],a[3]=c,a[5]=a[7],a[6]=d,a[7]=e,a}return b[0]=a[0],b[1]=a[3],b[2]=a[6],b[3]=a[1],b[4]=a[4],b[5]=a[7],b[6]=a[2],b[7]=a[5],b[8]=a[8],b},f.mat3.toMat4=function(a,b){return b||(b=f.mat4.create()),b[15]=1,b[14]=0,b[13]=0,b[12]=0,b[11]=0,b[10]=a[8],b[9]=a[7],b[8]=a[6],b[7]=0,b[6]=a[5],b[5]=a[4],b[4]=a[3],b[3]=0,b[2]=a[2],b[1]=a[1],b[0]=a[0],b},f.mat4.create=function(){var a=new f.Matrix(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},f.mat4.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[3],f=a[6],g=a[7],h=a[11];return a[1]=a[4],a[2]=a[8],a[3]=a[12],a[4]=c,a[6]=a[9],a[7]=a[13],a[8]=d,a[9]=f,a[11]=a[14],a[12]=e,a[13]=g,a[14]=h,a}return b[0]=a[0],b[1]=a[4],b[2]=a[8],b[3]=a[12],b[4]=a[1],b[5]=a[5],b[6]=a[9],b[7]=a[13],b[8]=a[2],b[9]=a[6],b[10]=a[10],b[11]=a[14],b[12]=a[3],b[13]=a[7],b[14]=a[11],b[15]=a[15],b},f.mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],m=a[9],n=a[10],o=a[11],p=a[12],q=a[13],r=a[14],s=a[15],t=b[0],u=b[1],v=b[2],w=b[3];return c[0]=t*d+u*h+v*l+w*p,c[1]=t*e+u*i+v*m+w*q,c[2]=t*f+u*j+v*n+w*r,c[3]=t*g+u*k+v*o+w*s,t=b[4],u=b[5],v=b[6],w=b[7],c[4]=t*d+u*h+v*l+w*p,c[5]=t*e+u*i+v*m+w*q,c[6]=t*f+u*j+v*n+w*r,c[7]=t*g+u*k+v*o+w*s,t=b[8],u=b[9],v=b[10],w=b[11],c[8]=t*d+u*h+v*l+w*p,c[9]=t*e+u*i+v*m+w*q,c[10]=t*f+u*j+v*n+w*r,c[11]=t*g+u*k+v*o+w*s,t=b[12],u=b[13],v=b[14],w=b[15],c[12]=t*d+u*h+v*l+w*p,c[13]=t*e+u*i+v*m+w*q,c[14]=t*f+u*j+v*n+w*r,c[15]=t*g+u*k+v*o+w*s,c},f.DisplayObject=function(){this.last=this,this.first=this,this.position=new f.Point,this.scale=new f.Point(1,1),this.pivot=new f.Point(0,0),this.rotation=0,this.alpha=1,this.visible=!0,this.hitArea=null,this.buttonMode=!1,this.renderable=!1,this.parent=null,this.stage=null,this.worldAlpha=1,this._interactive=!1,this.worldTransform=f.mat3.create(),this.localTransform=f.mat3.create(),this.color=[],this.dynamic=!0,this._sr=0,this._cr=1,this.filterArea=new f.Rectangle(0,0,1,1)},f.DisplayObject.prototype.constructor=f.DisplayObject,f.DisplayObject.prototype.setInteractive=function(a){this.interactive=a},Object.defineProperty(f.DisplayObject.prototype,"interactive",{get:function(){return this._interactive},set:function(a){this._interactive=a,this.stage&&(this.stage.dirty=!0)}}),Object.defineProperty(f.DisplayObject.prototype,"mask",{get:function(){return this._mask},set:function(a){a?this._mask?(a.start=this._mask.start,a.end=this._mask.end):(this.addFilter(a),a.renderable=!1):(this.removeFilter(this._mask),this._mask.renderable=!0),this._mask=a}}),Object.defineProperty(f.DisplayObject.prototype,"filters",{get:function(){return this._filters},set:function(a){if(a){this._filters&&this.removeFilter(this._filters),this.addFilter(a);for(var b=[],c=0;c=0&&b<=this.children.length))throw new Error(a+" The index "+b+" supplied is out of bounds "+this.children.length);if(void 0!=a.parent&&a.parent.removeChild(a),a.parent=this,this.stage){var c=a;do c.interactive&&(this.stage.dirty=!0),c.stage=this.stage,c=c._iNext;while(c)}var d,e,f=a.first,g=a.last;if(b==this.children.length){e=this.last;for(var h=this,i=this.last;h;)h.last==i&&(h.last=a.last),h=h.parent}else e=0==b?this:this.children[b-1].last;d=e._iNext,d&&(d._iPrev=g,g._iNext=d),f._iPrev=e,e._iNext=f,this.children.splice(b,0,a),this.__renderGroup&&(a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a),this.__renderGroup.addDisplayObjectAndChildren(a))},f.DisplayObjectContainer.prototype.swapChildren=function(){},f.DisplayObjectContainer.prototype.getChildAt=function(a){if(a>=0&&aa;a++)this.children[a].updateTransform()}},f.blendModes={},f.blendModes.NORMAL=0,f.blendModes.SCREEN=1,f.Sprite=function(a){f.DisplayObjectContainer.call(this),this.anchor=new f.Point,this.texture=a,this.blendMode=f.blendModes.NORMAL,this._width=0,this._height=0,a.baseTexture.hasLoaded?this.updateFrame=!0:(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Sprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Sprite.prototype.constructor=f.Sprite,Object.defineProperty(f.Sprite.prototype,"width",{get:function(){return this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(f.Sprite.prototype,"height",{get:function(){return this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),f.Sprite.prototype.setTexture=function(a){this.texture.baseTexture!=a.baseTexture?(this.textureChange=!0,this.texture=a,this.__renderGroup&&this.__renderGroup.updateTexture(this)):this.texture=a,this.updateFrame=!0},f.Sprite.prototype.onTextureUpdate=function(){this._width&&(this.scale.x=this._width/this.texture.frame.width),this._height&&(this.scale.y=this._height/this.texture.frame.height),this.updateFrame=!0},f.Sprite.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache"+this);return new f.Sprite(b)},f.Sprite.fromImage=function(a){var b=f.Texture.fromImage(a);return new f.Sprite(b)},f.MovieClip=function(a){f.Sprite.call(this,a[0]),this.textures=a,this.animationSpeed=1,this.loop=!0,this.onComplete=null,this.currentFrame=0,this.playing=!1},f.MovieClip.prototype=Object.create(f.Sprite.prototype),f.MovieClip.prototype.constructor=f.MovieClip,Object.defineProperty(f.MovieClip.prototype,"totalFrames",{get:function(){return this.textures.length}}),f.MovieClip.prototype.stop=function(){this.playing=!1},f.MovieClip.prototype.play=function(){this.playing=!0},f.MovieClip.prototype.gotoAndStop=function(a){this.playing=!1,this.currentFrame=a;var b=0|this.currentFrame+.5;this.setTexture(this.textures[b%this.textures.length])},f.MovieClip.prototype.gotoAndPlay=function(a){this.currentFrame=a,this.playing=!0},f.MovieClip.prototype.updateTransform=function(){if(f.Sprite.prototype.updateTransform.call(this),this.playing){this.currentFrame+=this.animationSpeed;var a=0|this.currentFrame+.5;this.loop||a=this.textures.length&&(this.gotoAndStop(this.textures.length-1),this.onComplete&&this.onComplete())}},f.FilterBlock=function(){this.visible=!0,this.renderable=!0},f.Text=function(a,b){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),f.Sprite.call(this,f.Texture.fromCanvas(this.canvas)),this.setText(a),this.setStyle(b),this.updateText(),this.dirty=!1},f.Text.prototype=Object.create(f.Sprite.prototype),f.Text.prototype.constructor=f.Text,f.Text.prototype.setStyle=function(a){a=a||{},a.font=a.font||"bold 20pt Arial",a.fill=a.fill||"black",a.align=a.align||"left",a.stroke=a.stroke||"black",a.strokeThickness=a.strokeThickness||0,a.wordWrap=a.wordWrap||!1,a.wordWrapWidth=a.wordWrapWidth||100,this.style=a,this.dirty=!0},f.Text.prototype.setText=function(a){this.text=a.toString()||" ",this.dirty=!0},f.Text.prototype.updateText=function(){this.context.font=this.style.font;var a=this.text;this.style.wordWrap&&(a=this.wordWrap(this.text));for(var b=a.split(/(?:\r\n|\r|\n)/),c=[],d=0,e=0;ee?f:arguments.callee(a,b,f,d,e):arguments.callee(a,b,c,f,e)},c=function(a,c,d){if(a.measureText(c).width<=d||c.length<1)return c;var e=b(a,c,0,c.length,d);return c.substring(0,e)+"\n"+arguments.callee(a,c.substring(e),d)},d="",e=a.split("\n"),f=0;f=2?parseInt(b[b.length-2],10):f.BitmapText.fonts[this.fontName].size,this.dirty=!0},f.BitmapText.prototype.updateText=function(){for(var a=f.BitmapText.fonts[this.fontName],b=new f.Point,c=null,d=[],e=0,g=[],h=0,i=this.fontSize/a.size,j=0;j=j;j++){var n=0;"right"==this.style.align?n=e-g[j]:"center"==this.style.align&&(n=(e-g[j])/2),m.push(n)}for(j=0;j0;)this.removeChild(this.getChildAt(0));this.updateText(),this.dirty=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.BitmapText.fonts={},f.InteractionManager=function(a){this.stage=a,this.mouse=new f.InteractionData,this.touchs={},this.tempPoint=new f.Point,this.mouseoverEnabled=!0,this.pool=[],this.interactiveItems=[],this.interactionDOMElement=null,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseOut=this.onMouseOut.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.last=0},f.InteractionManager.prototype.constructor=f.InteractionManager,f.InteractionManager.prototype.collectInteractiveSprite=function(a,b){for(var c=a.children,d=c.length,e=d-1;e>=0;e--){var f=c[e];f.interactive?(b.interactiveChildren=!0,this.interactiveItems.push(f),f.children.length>0&&this.collectInteractiveSprite(f,f)):(f.__iParent=null,f.children.length>0&&this.collectInteractiveSprite(f,b))}},f.InteractionManager.prototype.setTarget=function(a){this.target=a,null===this.interactionDOMElement&&this.setTargetDomElement(a.view),document.body.addEventListener("mouseup",this.onMouseUp,!0)},f.InteractionManager.prototype.setTargetDomElement=function(a){null!==this.interactionDOMElement&&(this.interactionDOMElement.style["-ms-content-zooming"]="",this.interactionDOMElement.style["-ms-touch-action"]="",this.interactionDOMElement.removeEventListener("mousemove",this.onMouseMove,!0),this.interactionDOMElement.removeEventListener("mousedown",this.onMouseDown,!0),this.interactionDOMElement.removeEventListener("mouseout",this.onMouseOut,!0),this.interactionDOMElement.removeEventListener("touchstart",this.onTouchStart,!0),this.interactionDOMElement.removeEventListener("touchend",this.onTouchEnd,!0),this.interactionDOMElement.removeEventListener("touchmove",this.onTouchMove,!0)),window.navigator.msPointerEnabled&&(a.style["-ms-content-zooming"]="none",a.style["-ms-touch-action"]="none"),this.interactionDOMElement=a,a.addEventListener("mousemove",this.onMouseMove,!0),a.addEventListener("mousedown",this.onMouseDown,!0),a.addEventListener("mouseout",this.onMouseOut,!0),a.addEventListener("touchstart",this.onTouchStart,!0),a.addEventListener("touchend",this.onTouchEnd,!0),a.addEventListener("touchmove",this.onTouchMove,!0)},f.InteractionManager.prototype.update=function(){if(this.target){var a=Date.now(),b=a-this.last;if(b=30*b/1e3,!(1>b)){if(this.last=a,this.dirty){this.dirty=!1;for(var c=this.interactiveItems.length,d=0;c>d;d++)this.interactiveItems[d].interactiveChildren=!1;this.interactiveItems=[],this.stage.interactive&&this.interactiveItems.push(this.stage),this.collectInteractiveSprite(this.stage,this.stage)}var e=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var d=0;e>d;d++){var f=this.interactiveItems[d];(f.mouseover||f.mouseout||f.buttonMode)&&(f.__hit=this.hitTest(f,this.mouse),this.mouse.target=f,f.__hit?(f.buttonMode&&(this.interactionDOMElement.style.cursor="pointer"),f.__isOver||(f.mouseover&&f.mouseover(this.mouse),f.__isOver=!0)):f.__isOver&&(f.mouseout&&f.mouseout(this.mouse),f.__isOver=!1))}}}},f.InteractionManager.prototype.onMouseMove=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactionDOMElement.getBoundingClientRect();this.mouse.global.x=(a.clientX-b.left)*(this.target.width/b.width),this.mouse.global.y=(a.clientY-b.top)*(this.target.height/b.height);var c=this.interactiveItems.length;this.mouse.global;for(var d=0;c>d;d++){var e=this.interactiveItems[d];e.mousemove&&e.mousemove(this.mouse)}},f.InteractionManager.prototype.onMouseDown=function(a){this.mouse.originalEvent=a||window.event;var b=this.interactiveItems.length;this.mouse.global,this.stage;for(var c=0;b>c;c++){var d=this.interactiveItems[c];if((d.mousedown||d.click)&&(d.__mouseIsDown=!0,d.__hit=this.hitTest(d,this.mouse),d.__hit&&(d.mousedown&&d.mousedown(this.mouse),d.__isDown=!0,!d.interactiveChildren)))break}},f.InteractionManager.prototype.onMouseOut=function(){var a=this.interactiveItems.length;this.interactionDOMElement.style.cursor="default";for(var b=0;a>b;b++){var c=this.interactiveItems[b];c.__isOver&&(this.mouse.target=c,c.mouseout&&c.mouseout(this.mouse),c.__isOver=!1)}},f.InteractionManager.prototype.onMouseUp=function(a){this.mouse.originalEvent=a||window.event,this.mouse.global;for(var b=this.interactiveItems.length,c=!1,d=0;b>d;d++){var e=this.interactiveItems[d];(e.mouseup||e.mouseupoutside||e.click)&&(e.__hit=this.hitTest(e,this.mouse),e.__hit&&!c?(e.mouseup&&e.mouseup(this.mouse),e.__isDown&&e.click&&e.click(this.mouse),e.interactiveChildren||(c=!0)):e.__isDown&&e.mouseupoutside&&e.mouseupoutside(this.mouse),e.__isDown=!1)}},f.InteractionManager.prototype.hitTest=function(a,b){var c=b.global;if(a.vcount!==f.visibleCount)return!1;var d=a instanceof f.Sprite,e=a.worldTransform,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=1/(g*k+h*-j),n=k*m*c.x+-h*m*c.y+(l*h-i*k)*m,o=g*m*c.y+-j*m*c.x+(-l*g+i*j)*m;if(b.target=a,a.hitArea&&a.hitArea.contains)return a.hitArea.contains(n,o)?(b.target=a,!0):!1;if(d){var p,q=a.texture.frame.width,r=a.texture.frame.height,s=-q*a.anchor.x;if(n>s&&s+q>n&&(p=-r*a.anchor.y,o>p&&p+r>o))return b.target=a,!0}for(var t=a.children.length,u=0;t>u;u++){var v=a.children[u],w=this.hitTest(v,b);if(w)return b.target=a,!0}return!1},f.InteractionManager.prototype.onTouchMove=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;dd;d++){var h=this.interactiveItems[d];h.touchmove&&h.touchmove(f)}},f.InteractionManager.prototype.onTouchStart=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i];if((j.touchstart||j.tap)&&(j.__hit=this.hitTest(j,g),j.__hit&&(j.touchstart&&j.touchstart(g),j.__isDown=!0,j.__touchData=g,!j.interactiveChildren)))break}}},f.InteractionManager.prototype.onTouchEnd=function(a){for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;di;i++){var j=this.interactiveItems[i],k=j.__touchData;j.__hit=this.hitTest(j,f),k==f&&(f.originalEvent=a||window.event,(j.touchend||j.tap)&&(j.__hit&&!g?(j.touchend&&j.touchend(f),j.__isDown&&j.tap&&j.tap(f),j.interactiveChildren||(g=!0)):j.__isDown&&j.touchendoutside&&j.touchendoutside(f),j.__isDown=!1),j.__touchData=null)}this.pool.push(f),this.touchs[e.identifier]=null}},f.InteractionData=function(){this.global=new f.Point,this.local=new f.Point,this.target,this.originalEvent},f.InteractionData.prototype.getLocalPosition=function(a){var b=a.worldTransform,c=this.global,d=b[0],e=b[1],g=b[2],h=b[3],i=b[4],j=b[5],k=1/(d*i+e*-h);return new f.Point(i*k*c.x+-e*k*c.y+(j*e-g*i)*k,d*k*c.y+-h*k*c.x+(-j*d+g*h)*k)},f.InteractionData.prototype.constructor=f.InteractionData,f.Stage=function(a){f.DisplayObjectContainer.call(this),this.worldTransform=f.mat3.create(),this.interactive=!0,this.interactionManager=new f.InteractionManager(this),this.dirty=!0,this.__childrenAdded=[],this.__childrenRemoved=[],this.stage=this,this.stage.hitArea=new f.Rectangle(0,0,1e5,1e5),this.setBackgroundColor(a),this.worldVisible=!0},f.Stage.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Stage.prototype.constructor=f.Stage,f.Stage.prototype.setInteractionDelegate=function(a){this.interactionManager.setTargetDomElement(a)},f.Stage.prototype.updateTransform=function(){this.worldAlpha=1,this.vcount=f.visibleCount;for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform();this.dirty&&(this.dirty=!1,this.interactionManager.dirty=!0),this.interactive&&this.interactionManager.update()},f.Stage.prototype.setBackgroundColor=function(a){this.backgroundColor=a||0,this.backgroundColorSplit=d(this.backgroundColor);var b=this.backgroundColor.toString(16);b="000000".substr(0,6-b.length)+b,this.backgroundColorString="#"+b},f.Stage.prototype.getMousePosition=function(){return this.interactionManager.mouse.global};for(var h=0,i=["ms","moz","webkit","o"],j=0;j>>>>>>>>"),console.log("_");var b=0,c=a.first;for(console.log(c);c._iNext;)if(b++,c=c._iNext,console.log(c),b>100){console.log("BREAK");break}},f.EventTarget=function(){var a={};this.addEventListener=this.on=function(b,c){void 0===a[b]&&(a[b]=[]),-1===a[b].indexOf(c)&&a[b].push(c)},this.dispatchEvent=this.emit=function(b){if(a[b.type]&&a[b.type].length)for(var c=0,d=a[b.type].length;d>c;c++)a[b.type][c](b)},this.removeEventListener=this.off=function(b,c){var d=a[b].indexOf(c);-1!==d&&a[b].splice(d,1)}},f.autoDetectRenderer=function(a,b,c,d,e){a||(a=800),b||(b=600);var g=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}();if(g){var h=-1!=navigator.userAgent.toLowerCase().indexOf("msie");g=!h}return g?new f.WebGLRenderer(a,b,c,d,e):new f.CanvasRenderer(a,b,c,d)},f.PolyK={},f.PolyK.Triangulate=function(a){var b=!0,c=a.length>>1;if(3>c)return[];for(var d=[],e=[],g=0;c>g;g++)e.push(g);for(var g=0,h=c;h>3;){var i=e[(g+0)%h],j=e[(g+1)%h],k=e[(g+2)%h],l=a[2*i],m=a[2*i+1],n=a[2*j],o=a[2*j+1],p=a[2*k],q=a[2*k+1],r=!1;if(f.PolyK._convex(l,m,n,o,p,q,b)){r=!0;for(var s=0;h>s;s++){var t=e[s];if(t!=i&&t!=j&&t!=k&&f.PolyK._PointInTriangle(a[2*t],a[2*t+1],l,m,n,o,p,q)){r=!1;break}}}if(r)d.push(i,j,k),e.splice((g+1)%h,1),h--,g=0;else if(g++>3*h){if(!b)return console.log("PIXI Warning: shape too complex to fill"),[];var d=[];e=[];for(var g=0;c>g;g++)e.push(g);g=0,h=c,b=!1}}return d.push(e[0],e[1],e[2]),d},f.PolyK._PointInTriangle=function(a,b,c,d,e,f,g,h){var i=g-c,j=h-d,k=e-c,l=f-d,m=a-c,n=b-d,o=i*i+j*j,p=i*k+j*l,q=i*m+j*n,r=k*k+l*l,s=k*m+l*n,t=1/(o*r-p*p),u=(r*q-p*s)*t,v=(o*s-p*q)*t;return u>=0&&v>=0&&1>u+v},f.PolyK._convex=function(a,b,c,d,e,f,g){return(b-d)*(e-c)+(c-a)*(f-d)>=0==g},f.initDefaultShaders=function(){f.primitiveShader=new f.PrimitiveShader,f.primitiveShader.init(),f.stripShader=new f.StripShader,f.stripShader.init(),f.defaultShader=new f.PixiShader,f.defaultShader.init();var a=f.gl,b=f.defaultShader.program;a.useProgram(b),a.enableVertexAttribArray(f.defaultShader.aVertexPosition),a.enableVertexAttribArray(f.defaultShader.colorAttribute),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.primitiveShader.program),a.disableVertexAttribArray(f.defaultShader.aTextureCoord)},f.deactivatePrimitiveShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program),a.enableVertexAttribArray(f.defaultShader.aTextureCoord)},f.activateStripShader=function(){var a=f.gl;a.useProgram(f.stripShader.program)},f.deactivateStripShader=function(){var a=f.gl;a.useProgram(f.defaultShader.program)},f.CompileVertexShader=function(a,b){return f._CompileShader(a,b,a.VERTEX_SHADER)},f.CompileFragmentShader=function(a,b){return f._CompileShader(a,b,a.FRAGMENT_SHADER)},f._CompileShader=function(a,b,c){var d=b.join("\n"),e=a.createShader(c);return a.shaderSource(e,d),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)?e:(console.log(a.getShaderInfoLog(e)),null)},f.compileProgram=function(a,b){var c=f.gl,d=f.CompileFragmentShader(c,b),e=f.CompileVertexShader(c,a),g=c.createProgram();return c.attachShader(g,e),c.attachShader(g,d),c.linkProgram(g),c.getProgramParameter(g,c.LINK_STATUS)||console.log("Could not initialise shaders"),g},f.PixiShader=function(){this.program,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;","}"]},f.PixiShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc||f.PixiShader.defaultVertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"); for(var c in this.uniforms)a[c]=b.getUniformLocation(a,c);this.program=a},f.PixiShader.prototype.syncUniforms=function(){var a=f.gl;for(var b in this.uniforms){var c=this.uniforms[b].type;if("f"==c&&a.uniform1f(this.program[b],this.uniforms[b].value),"f2"==c)a.uniform2f(this.program[b],this.uniforms[b].value.x,this.uniforms[b].value.y);else if("f4"==c)a.uniform4fv(this.program[b],this.uniforms[b].value);else if("mat4"==c)a.uniformMatrix4fv(this.program[b],!1,this.uniforms[b].value);else if("sampler2D"==c){var d=this.uniforms[b].value;a.activeTexture(a.TEXTURE1),a.bindTexture(a.TEXTURE_2D,d.baseTexture._glTexture),a.uniform1i(this.program[b],1)}}},f.PixiShader.defaultVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","varying float vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"],f.StripShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying float vColor;","uniform float alpha;","uniform sampler2D uSampler;","void main(void) {","gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));","gl_FragColor = gl_FragColor * alpha;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","varying vec2 vTextureCoord;","varying vec2 offsetVector;","varying float vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);","vTextureCoord = aTextureCoord;","vColor = aColor;","}"]},f.StripShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.uSampler=b.getUniformLocation(a,"uSampler"),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.aTextureCoord=b.getAttribLocation(a,"aTextureCoord"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.PrimitiveShader=function(){this.program,this.fragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","gl_FragColor = vColor;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec4 aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform float alpha;","varying vec4 vColor;","void main(void) {","vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","v -= offsetVector.xyx;","gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","vColor = aColor * alpha;","}"]},f.PrimitiveShader.prototype.init=function(){var a=f.compileProgram(this.vertexSrc,this.fragmentSrc),b=f.gl;b.useProgram(a),this.projectionVector=b.getUniformLocation(a,"projectionVector"),this.offsetVector=b.getUniformLocation(a,"offsetVector"),this.colorAttribute=b.getAttribLocation(a,"aColor"),this.aVertexPosition=b.getAttribLocation(a,"aVertexPosition"),this.translationMatrix=b.getUniformLocation(a,"translationMatrix"),this.alpha=b.getUniformLocation(a,"alpha"),this.program=a},f.WebGLGraphics=function(){},f.WebGLGraphics.renderGraphics=function(a,b){var c=f.gl;a._webGL||(a._webGL={points:[],indices:[],lastIndex:0,buffer:c.createBuffer(),indexBuffer:c.createBuffer()}),a.dirty&&(a.dirty=!1,a.clearDirty&&(a.clearDirty=!1,a._webGL.lastIndex=0,a._webGL.points=[],a._webGL.indices=[]),f.WebGLGraphics.updateGraphics(a)),f.activatePrimitiveShader();var d=f.mat3.clone(a.worldTransform);f.mat3.transpose(d),c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA),c.uniformMatrix3fv(f.primitiveShader.translationMatrix,!1,d),c.uniform2f(f.primitiveShader.projectionVector,b.x,-b.y),c.uniform2f(f.primitiveShader.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(f.primitiveShader.alpha,a.worldAlpha),c.bindBuffer(c.ARRAY_BUFFER,a._webGL.buffer),c.vertexAttribPointer(f.primitiveShader.aVertexPosition,2,c.FLOAT,!1,24,0),c.vertexAttribPointer(f.primitiveShader.colorAttribute,4,c.FLOAT,!1,24,8),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),c.drawElements(c.TRIANGLE_STRIP,a._webGL.indices.length,c.UNSIGNED_SHORT,0),f.deactivatePrimitiveShader()},f.WebGLGraphics.updateGraphics=function(a){for(var b=a._webGL.lastIndex;b3&&f.WebGLGraphics.buildPoly(c,a._webGL),c.lineWidth>0&&f.WebGLGraphics.buildLine(c,a._webGL)):c.type==f.Graphics.RECT?f.WebGLGraphics.buildRectangle(c,a._webGL):(c.type==f.Graphics.CIRC||c.type==f.Graphics.ELIP)&&f.WebGLGraphics.buildCircle(c,a._webGL)}a._webGL.lastIndex=a.graphicsData.length;var d=f.gl;a._webGL.glPoints=new Float32Array(a._webGL.points),d.bindBuffer(d.ARRAY_BUFFER,a._webGL.buffer),d.bufferData(d.ARRAY_BUFFER,a._webGL.glPoints,d.STATIC_DRAW),a._webGL.glIndicies=new Uint16Array(a._webGL.indices),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,a._webGL.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,a._webGL.glIndicies,d.STATIC_DRAW)},f.WebGLGraphics.buildRectangle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3];if(a.fill){var j=d(a.fillColor),k=a.fillAlpha,l=j[0]*k,m=j[1]*k,n=j[2]*k,o=b.points,p=b.indices,q=o.length/6;o.push(e,g),o.push(l,m,n,k),o.push(e+h,g),o.push(l,m,n,k),o.push(e,g+i),o.push(l,m,n,k),o.push(e+h,g+i),o.push(l,m,n,k),p.push(q,q,q+1,q+2,q+3,q+3)}a.lineWidth&&(a.points=[e,g,e+h,g,e+h,g+i,e,g+i,e,g],f.WebGLGraphics.buildLine(a,b))},f.WebGLGraphics.buildCircle=function(a,b){var c=a.points,e=c[0],g=c[1],h=c[2],i=c[3],j=40,k=2*Math.PI/j;if(a.fill){var l=d(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=b.points,r=b.indices,s=q.length/6;r.push(s);for(var t=0;j+1>t;t++)q.push(e,g,n,o,p,m),q.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){a.points=[];for(var t=0;j+1>t;t++)a.points.push(e+Math.sin(k*t)*h,g+Math.cos(k*t)*i);f.WebGLGraphics.buildLine(a,b)}},f.WebGLGraphics.buildLine=function(a,b){var c=a.points;if(0!=c.length){var e=new f.Point(c[0],c[1]),g=new f.Point(c[c.length-2],c[c.length-1]);if(e.x==g.x&&e.y==g.y){c.pop(),c.pop(),g=new f.Point(c[c.length-2],c[c.length-1]);var h=g.x+.5*(e.x-g.x),i=g.y+.5*(e.y-g.y);c.unshift(h,i),c.push(h,i)}var j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E=b.points,F=b.indices,G=c.length/2,H=c.length,I=E.length/6,J=a.lineWidth/2,K=d(a.lineColor),L=a.lineAlpha,M=K[0]*L,N=K[1]*L,O=K[2]*L;j=c[0],k=c[1],l=c[2],m=c[3],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,E.push(j-p,k-q,M,N,O,L),E.push(j+p,k+q,M,N,O,L);for(var P=1;G-1>P;P++)j=c[2*(P-1)],k=c[2*(P-1)+1],l=c[2*P],m=c[2*P+1],n=c[2*(P+1)],o=c[2*(P+1)+1],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,r=-(m-o),s=l-n,D=Math.sqrt(r*r+s*s),r/=D,s/=D,r*=J,s*=J,v=-q+k-(-q+m),w=-p+l-(-p+j),x=(-p+j)*(-q+m)-(-p+l)*(-q+k),y=-s+o-(-s+m),z=-r+l-(-r+n),A=(-r+n)*(-s+m)-(-r+l)*(-s+o),B=v*z-y*w,0==B&&(B+=1),px=(w*A-z*x)/B,py=(y*x-v*A)/B,C=(px-l)*(px-l)+(py-m)+(py-m),C>19600?(t=p-r,u=q-s,D=Math.sqrt(t*t+u*u),t/=D,u/=D,t*=J,u*=J,E.push(l-t,m-u),E.push(M,N,O,L),E.push(l+t,m+u),E.push(M,N,O,L),E.push(l-t,m-u),E.push(M,N,O,L),H++):(E.push(px,py),E.push(M,N,O,L),E.push(l-(px-l),m-(py-m)),E.push(M,N,O,L));j=c[2*(G-2)],k=c[2*(G-2)+1],l=c[2*(G-1)],m=c[2*(G-1)+1],p=-(k-m),q=j-l,D=Math.sqrt(p*p+q*q),p/=D,q/=D,p*=J,q*=J,E.push(l-p,m-q),E.push(M,N,O,L),E.push(l+p,m+q),E.push(M,N,O,L),F.push(I);for(var P=0;H>P;P++)F.push(I++);F.push(I-1)}},f.WebGLGraphics.buildPoly=function(a,b){var c=a.points;if(!(c.length<6)){for(var e=b.points,g=b.indices,h=c.length/2,i=d(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=f.PolyK.Triangulate(c),o=e.length/6,p=0;pp;p++)e.push(c[2*p],c[2*p+1],k,l,m,j)}},f._defaultFrame=new f.Rectangle(0,0,1,1),f.gl,f.WebGLRenderer=function(a,b,c,d,e){this.transparent=!!d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.view.width=this.width,this.view.height=this.height;var g=this;this.view.addEventListener("webglcontextlost",function(a){g.handleContextLost(a)},!1),this.view.addEventListener("webglcontextrestored",function(a){g.handleContextRestored(a)},!1),this.batchs=[];var h={alpha:this.transparent,antialias:!!e,premultipliedAlpha:!1,stencil:!0};try{f.gl=this.gl=this.view.getContext("experimental-webgl",h)}catch(i){try{f.gl=this.gl=this.view.getContext("webgl",h)}catch(i){throw new Error(" This browser does not support webGL. Try using the canvas renderer"+this)}}f.initDefaultShaders();var j=this.gl;j.useProgram(f.defaultShader.program),f.WebGLRenderer.gl=j,this.batch=new f.WebGLBatch(j),j.disable(j.DEPTH_TEST),j.disable(j.CULL_FACE),j.enable(j.BLEND),j.colorMask(!0,!0,!0,this.transparent),f.projection=new f.Point(400,300),f.offset=new f.Point(0,0),this.resize(this.width,this.height),this.contextLost=!1,this.stageRenderGroup=new f.WebGLRenderGroup(this.gl)},f.WebGLRenderer.prototype.constructor=f.WebGLRenderer,f.WebGLRenderer.getBatch=function(){return 0==f._batchs.length?new f.WebGLBatch(f.WebGLRenderer.gl):f._batchs.pop()},f.WebGLRenderer.returnBatch=function(a){a.clean(),f._batchs.push(a)},f.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(this.__stage=a,this.stageRenderGroup.setRenderable(a)),f.WebGLRenderer.updateTextures(),f.visibleCount++,a.updateTransform();var b=this.gl;if(b.colorMask(!0,!0,!0,this.transparent),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],!this.transparent),b.clear(b.COLOR_BUFFER_BIT),this.stageRenderGroup.backgroundColor=a.backgroundColorSplit,f.projection.x=this.width/2,f.projection.y=-this.height/2,this.stageRenderGroup.render(f.projection),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0){for(var c=0;cc;c++){var d=6*c,e=4*c;this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3}a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW)},f.WebGLBatch.prototype.refresh=function(){this.gl,this.dynamicSizen;n++)renderable=this.batchs[n],renderable instanceof f.WebGLBatch?this.batchs[n].render():this.renderSpecial(renderable,b);endBatch instanceof f.WebGLBatch?endBatch.render(0,h+1):this.renderSpecial(endBatch,b)},f.WebGLRenderGroup.prototype.renderSpecial=function(a,b){var c=a.vcount===f.visibleCount;a instanceof f.TilingSprite?c&&this.renderTilingSprite(a,b):a instanceof f.Strip?c&&this.renderStrip(a,b):a instanceof f.CustomRenderable?c&&a.renderWebGL(this,b):a instanceof f.Graphics?c&&a.renderable&&f.WebGLGraphics.renderGraphics(a,b):a instanceof f.FilterBlock&&this.handleFilterBlock(a,b)},f.WebGLRenderGroup.prototype.handleFilterBlock=function(a,b){var c=f.gl;a.open?a.data instanceof Array?this.filterManager.pushFilter(a):(c.enable(c.STENCIL_TEST),c.colorMask(!1,!1,!1,!1),c.stencilFunc(c.ALWAYS,1,255),c.stencilOp(c.KEEP,c.KEEP,c.REPLACE),f.WebGLGraphics.renderGraphics(a.data,b),c.colorMask(!0,!0,!0,!0),c.stencilFunc(c.NOTEQUAL,0,255),c.stencilOp(c.KEEP,c.KEEP,c.KEEP)):a.data instanceof Array?this.filterManager.popFilter():c.disable(c.STENCIL_TEST)},f.WebGLRenderGroup.prototype.updateTexture=function(a){this.removeObject(a);for(var b=a.first;b!=this.root&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););this.insertObject(a,b,c)},f.WebGLRenderGroup.prototype.addFilterBlocks=function(a,b){a.__renderGroup=this,b.__renderGroup=this;for(var c=a;c!=this.root.first&&(c=c._iPrev,!c.renderable||!c.__renderGroup););this.insertAfter(a,c);for(var d=b;d!=this.root.first&&(d=d._iPrev,!d.renderable||!d.__renderGroup););this.insertAfter(b,d)},f.WebGLRenderGroup.prototype.removeFilterBlocks=function(a,b){this.removeObject(a),this.removeObject(b)},f.WebGLRenderGroup.prototype.addDisplayObjectAndChildren=function(a){a.__renderGroup&&a.__renderGroup.removeDisplayObjectAndChildren(a);for(var b=a.first;b!=this.root.first&&(b=b._iPrev,!b.renderable||!b.__renderGroup););for(var c=a.last;c._iNext&&(c=c._iNext,!c.renderable||!c.__renderGroup););var d=a.first,e=a.last._iNext;do d.__renderGroup=this,d.renderable&&(this.insertObject(d,b,c),b=d),d=d._iNext;while(d!=e)},f.WebGLRenderGroup.prototype.removeDisplayObjectAndChildren=function(a){if(a.__renderGroup==this){a.last;do a.__renderGroup=null,a.renderable&&this.removeObject(a),a=a._iNext;while(a)}},f.WebGLRenderGroup.prototype.insertObject=function(a,b,c){var d=b,e=c;if(a instanceof f.Sprite){var g,h;if(d instanceof f.Sprite){if(g=d.batch,g&&g.texture==a.texture.baseTexture&&g.blendMode==a.blendMode)return g.insertAfter(a,d),void 0}else g=d;if(e)if(e instanceof f.Sprite){if(h=e.batch){if(h.texture==a.texture.baseTexture&&h.blendMode==a.blendMode)return h.insertBefore(a,e),void 0;if(h==g){var i=g.split(e),j=f.WebGLRenderer.getBatch(),k=this.batchs.indexOf(g);return j.init(a),this.batchs.splice(k+1,0,j,i),void 0}}}else h=e;var j=f.WebGLRenderer.getBatch();if(j.init(a),g){var k=this.batchs.indexOf(g);this.batchs.splice(k+1,0,j)}else this.batchs.push(j)}else a instanceof f.TilingSprite?this.initTilingSprite(a):a instanceof f.Strip&&this.initStrip(a),this.insertAfter(a,d)},f.WebGLRenderGroup.prototype.insertAfter=function(a,b){if(b instanceof f.Sprite){var c=b.batch;if(c)if(c.tail==b){var d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a)}else{var e=c.split(b.__next),d=this.batchs.indexOf(c);this.batchs.splice(d+1,0,a,e)}else this.batchs.push(a)}else{var d=this.batchs.indexOf(b);this.batchs.splice(d+1,0,a)}},f.WebGLRenderGroup.prototype.removeObject=function(a){var b;if(a instanceof f.Sprite){var c=a.batch;if(!c)return;c.remove(a),0==c.size&&(b=c)}else b=a;if(b){var d=this.batchs.indexOf(b);if(-1==d)return;if(0==d||d==this.batchs.length-1)return this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),void 0;if(this.batchs[d-1]instanceof f.WebGLBatch&&this.batchs[d+1]instanceof f.WebGLBatch&&this.batchs[d-1].texture==this.batchs[d+1].texture&&this.batchs[d-1].blendMode==this.batchs[d+1].blendMode)return this.batchs[d-1].merge(this.batchs[d+1]),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b),f.WebGLRenderer.returnBatch(this.batchs[d+1]),this.batchs.splice(d,2),void 0;this.batchs.splice(d,1),b instanceof f.WebGLBatch&&f.WebGLRenderer.returnBatch(b)}},f.WebGLRenderGroup.prototype.initTilingSprite=function(a){var b=this.gl;a.verticies=new Float32Array([0,0,a.width,0,a.width,a.height,0,a.height]),a.uvs=new Float32Array([0,0,1,0,1,1,0,1]),a.colors=new Float32Array([1,1,1,1]),a.indices=new Uint16Array([0,1,3,2]),a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW),a.texture.baseTexture._glTexture?(b.bindTexture(b.TEXTURE_2D,a.texture.baseTexture._glTexture),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.REPEAT),a.texture.baseTexture._powerOf2=!0):a.texture.baseTexture._powerOf2=!0},f.WebGLRenderGroup.prototype.renderStrip=function(a,b){var c=this.gl;f.activateStripShader();var d=f.stripShader;d.program;var e=f.mat3.clone(a.worldTransform);f.mat3.transpose(e),c.uniformMatrix3fv(d.translationMatrix,!1,e),c.uniform2f(d.projectionVector,b.x,b.y),c.uniform2f(d.offsetVector,-f.offset.x,-f.offset.y),c.uniform1f(d.alpha,a.worldAlpha),a.dirty?(a.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,a.verticies,c.STATIC_DRAW),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferData(c.ARRAY_BUFFER,a.uvs,c.STATIC_DRAW),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.bufferData(c.ARRAY_BUFFER,a.colors,c.STATIC_DRAW),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,a.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,a._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.verticies),c.vertexAttribPointer(d.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.vertexAttribPointer(d.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),c.bindTexture(c.TEXTURE_2D,a.texture.baseTexture._glTexture),c.bindBuffer(c.ARRAY_BUFFER,a._colorBuffer),c.vertexAttribPointer(d.colorAttribute,1,c.FLOAT,!1,0,0),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,a._indexBuffer)),c.drawElements(c.TRIANGLE_STRIP,a.indices.length,c.UNSIGNED_SHORT,0),f.deactivateStripShader()},f.WebGLRenderGroup.prototype.renderTilingSprite=function(a,b){var c=this.gl;f.shaderProgram;var d=a.tilePosition,e=a.tileScale,g=d.x/a.texture.baseTexture.width,h=d.y/a.texture.baseTexture.height,i=a.width/a.texture.baseTexture.width/e.x,j=a.height/a.texture.baseTexture.height/e.y;a.uvs[0]=0-g,a.uvs[1]=0-h,a.uvs[2]=1*i-g,a.uvs[3]=0-h,a.uvs[4]=1*i-g,a.uvs[5]=1*j-h,a.uvs[6]=0-g,a.uvs[7]=1*j-h,c.bindBuffer(c.ARRAY_BUFFER,a._uvBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,a.uvs),this.renderStrip(a,b)},f.WebGLRenderGroup.prototype.initStrip=function(a){var b=this.gl;this.shaderProgram,a._vertexBuffer=b.createBuffer(),a._indexBuffer=b.createBuffer(),a._uvBuffer=b.createBuffer(),a._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,a._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,a.verticies,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._uvBuffer),b.bufferData(b.ARRAY_BUFFER,a.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,a._colorBuffer),b.bufferData(b.ARRAY_BUFFER,a.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,a._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,a.indices,b.STATIC_DRAW)},f.WebGLFilterManager=function(){this.filterStack=[],this.texturePool=[],this.offsetX=0,this.offsetY=0,this.initShaderBuffers()},f.WebGLFilterManager.prototype.begin=function(a,b){this.width=2*a.x,this.height=2*-a.y,this.buffer=b},f.WebGLFilterManager.prototype.pushFilter=function(a){var b=f.gl;this.filterStack.push(a);var c=a.filterPasses[0];this.offsetX+=a.target.filterArea.x,this.offsetY+=a.target.filterArea.y;var d=this.texturePool.pop();d||(d=new f.FilterTexture(this.width,this.height)),b.bindTexture(b.TEXTURE_2D,d.texture),this.getBounds(a.target);var e=a.target.filterArea,g=c.padding;e.x-=g,e.y-=g,e.width+=2*g,e.height+=2*g,e.x<0&&(e.x=0),e.width>this.width&&(e.width=this.width),e.y<0&&(e.y=0),e.height>this.height&&(e.height=this.height),b.bindFramebuffer(b.FRAMEBUFFER,d.frameBuffer),b.viewport(0,0,e.width,e.height),f.projection.x=e.width/2,f.projection.y=-e.height/2,f.offset.x=-e.x,f.offset.y=-e.y,b.uniform2f(f.defaultShader.projectionVector,e.width/2,-e.height/2),b.uniform2f(f.defaultShader.offsetVector,-e.x,-e.y),b.colorMask(!0,!0,!0,!0),b.clearColor(0,0,0,0),b.clear(b.COLOR_BUFFER_BIT),a._glFilterTexture=d},f.WebGLFilterManager.prototype.popFilter=function(){var a=f.gl,b=this.filterStack.pop(),c=b.target.filterArea,d=b._glFilterTexture;if(b.filterPasses.length>1){a.viewport(0,0,c.width,c.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=c.height,this.vertexArray[2]=c.width,this.vertexArray[3]=c.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=c.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=c.width/this.width,this.uvArray[5]=c.height/this.height,this.uvArray[6]=c.width/this.width,this.uvArray[7]=c.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var e=d,g=this.texturePool.pop();g||(g=new f.FilterTexture(this.width,this.height)),a.bindFramebuffer(a.FRAMEBUFFER,g.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var h=0;hs?s:E,E=E>t?t:E,E=E>u?u:E,E=E>v?v:E,F=F>w?w:F,F=F>x?x:F,F=F>y?y:F,F=F>z?z:F,C=s>C?s:C,C=t>C?t:C,C=u>C?u:C,C=v>C?v:C,D=w>D?w:D,D=x>D?x:D,D=y>D?y:D,D=z>D?z:D),l=!1,A=A._iNext}while(A!=B);a.filterArea.x=E,a.filterArea.y=F,a.filterArea.width=C-E,a.filterArea.height=D-F},f.FilterTexture=function(a,b){var c=f.gl;this.frameBuffer=c.createFramebuffer(),this.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,this.texture),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.bindFramebuffer(c.FRAMEBUFFER,this.framebuffer),c.bindFramebuffer(c.FRAMEBUFFER,this.frameBuffer),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,this.texture,0),this.resize(a,b)},f.FilterTexture.prototype.resize=function(a,b){this.width=a,this.height=b;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a,b,0,c.RGBA,c.UNSIGNED_BYTE,null)},f.CanvasRenderer=function(a,b,c,d){this.transparent=d,this.width=a||800,this.height=b||600,this.view=c||document.createElement("canvas"),this.context=this.view.getContext("2d"),this.refresh=!0,this.view.width=this.width,this.view.height=this.height,this.count=0},f.CanvasRenderer.prototype.constructor=f.CanvasRenderer,f.CanvasRenderer.prototype.render=function(a){f.texturesToUpdate=[],f.texturesToDestroy=[],f.visibleCount++,a.updateTransform(),this.view.style.backgroundColor==a.backgroundColorString||this.transparent||(this.view.style.backgroundColor=a.backgroundColorString),this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.width,this.height),this.renderDisplayObject(a),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this))),f.Texture.frameUpdates.length>0&&(f.Texture.frameUpdates=[])},f.CanvasRenderer.prototype.resize=function(a,b){this.width=a,this.height=b,this.view.width=a,this.view.height=b},f.CanvasRenderer.prototype.renderDisplayObject=function(a){var b,c=this.context;c.globalCompositeOperation="source-over";var d=a.last._iNext;a=a.first;do if(b=a.worldTransform,a.visible)if(a.renderable){if(a instanceof f.Sprite){var e=a.texture.frame;e&&e.width&&e.height&&(c.globalAlpha=a.worldAlpha,c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),c.drawImage(a.texture.baseTexture.source,e.x,e.y,e.width,e.height,a.anchor.x*-e.width,a.anchor.y*-e.height,e.width,e.height))}else if(a instanceof f.Strip)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderStrip(a);else if(a instanceof f.TilingSprite)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),this.renderTilingSprite(a);else if(a instanceof f.CustomRenderable)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),a.renderCanvas(this);else if(a instanceof f.Graphics)c.setTransform(b[0],b[3],b[1],b[4],b[2],b[5]),f.CanvasGraphics.renderGraphics(a,c);else if(a instanceof f.FilterBlock&&a.data instanceof f.Graphics){var g=a.data;if(a.open){c.save();var h=g.alpha,i=g.worldTransform;c.setTransform(i[0],i[3],i[1],i[4],i[2],i[5]),g.worldAlpha=.5,c.worldAlpha=0,f.CanvasGraphics.renderGraphicsMask(g,c),c.clip(),g.worldAlpha=h}else c.restore()}a=a._iNext}else a=a._iNext;else a=a.last._iNext;while(a!=d)},f.CanvasRenderer.prototype.renderStripFlat=function(a){var b=this.context,c=a.verticies;a.uvs;var d=c.length/2;this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},f.CanvasRenderer.prototype.renderTilingSprite=function(a){var b=this.context;b.globalAlpha=a.worldAlpha,a.__tilePattern||(a.__tilePattern=b.createPattern(a.texture.baseTexture.source,"repeat")),b.beginPath();var c=a.tilePosition,d=a.tileScale;b.scale(d.x,d.y),b.translate(c.x,c.y),b.fillStyle=a.__tilePattern,b.fillRect(-c.x,-c.y,a.width/d.x,a.height/d.y),b.scale(1/d.x,1/d.y),b.translate(-c.x,-c.y),b.closePath()},f.CanvasRenderer.prototype.renderStrip=function(a){var b=this.context,c=a.verticies,d=a.uvs,e=c.length/2;this.count++;for(var f=1;e-2>f;f++){var g=2*f,h=c[g],i=c[g+2],j=c[g+4],k=c[g+1],l=c[g+3],m=c[g+5],n=d[g]*a.texture.width,o=d[g+2]*a.texture.width,p=d[g+4]*a.texture.width,q=d[g+1]*a.texture.height,r=d[g+3]*a.texture.height,s=d[g+5]*a.texture.height;b.save(),b.beginPath(),b.moveTo(h,k),b.lineTo(i,l),b.lineTo(j,m),b.closePath(),b.clip();var t=n*r+q*p+o*s-r*p-q*o-n*s,u=h*r+q*j+i*s-r*j-q*i-h*s,v=n*i+h*p+o*j-i*p-h*o-n*j,w=n*r*j+q*i*p+h*o*s-h*r*p-q*o*j-n*i*s,x=k*r+q*m+l*s-r*m-q*l-k*s,y=n*l+k*p+o*m-l*p-k*o-n*m,z=n*r*m+q*l*p+k*o*s-k*r*p-q*o*m-n*l*s;b.transform(u/t,x/t,v/t,y/t,w/t,z/t),b.drawImage(a.texture.baseTexture.source,0,0),b.restore()}},f.CanvasGraphics=function(){},f.CanvasGraphics.renderGraphics=function(a,b){for(var c=a.worldAlpha,d=0;d1&&(c=1,console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var d=0;1>d;d++){var e=a.graphicsData[d],g=e.points;if(e.type==f.Graphics.POLY){b.beginPath(),b.moveTo(g[0],g[1]);for(var h=1;hb?b:d,e=b+m>e?b+m:e,g=g>c?b:g,h=c+n>h?c+n:h}else if(k===f.Graphics.CIRC||k===f.Graphics.ELIP){b=a.x,c=a.y;var o=a.radius+l/2;d=d>b-o?b-o:d,e=b+o>e?b+o:e,g=g>c-o?c-o:g,h=c+o>h?c+o:h}else for(var p=0;pb-l?b-l:d,e=b+l>e?b+l:e,g=g>c-l?c-l:g,h=c+l>h?c+l:h}this.bounds=new f.Rectangle(d,g,e-d,h-g)}},f.Graphics.POLY=0,f.Graphics.RECT=1,f.Graphics.CIRC=2,f.Graphics.ELIP=3,f.Strip=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.blendMode=f.blendModes.NORMAL;try{this.uvs=new Float32Array([0,1,1,1,1,0,0,1]),this.verticies=new Float32Array([0,0,0,0,0,0,0,0,0]),this.colors=new Float32Array([1,1,1,1]),this.indices=new Uint16Array([0,1,2,3])}catch(d){this.uvs=[0,1,1,1,1,0,0,1],this.verticies=[0,0,0,0,0,0,0,0,0],this.colors=[1,1,1,1],this.indices=[0,1,2,3]}this.width=b,this.height=c,a.baseTexture.hasLoaded?(this.width=this.texture.frame.width,this.height=this.texture.frame.height,this.updateFrame=!0):(this.onTextureUpdateBind=this.onTextureUpdate.bind(this),this.texture.addEventListener("update",this.onTextureUpdateBind)),this.renderable=!0},f.Strip.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Strip.prototype.constructor=f.Strip,f.Strip.prototype.setTexture=function(a){this.texture=a,this.width=a.frame.width,this.height=a.frame.height,this.updateFrame=!0},f.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Rope=function(a,b){f.Strip.call(this,a),this.points=b;try{this.verticies=new Float32Array(4*b.length),this.uvs=new Float32Array(4*b.length),this.colors=new Float32Array(2*b.length),this.indices=new Uint16Array(2*b.length)}catch(c){this.verticies=verticies,this.uvs=uvs,this.colors=colors,this.indices=indices}this.refresh()},f.Rope.prototype=Object.create(f.Strip.prototype),f.Rope.prototype.constructor=f.Rope,f.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=this.indices,d=this.colors,e=a[0],f=a[0];this.count-=.2,b[0]=0,b[1]=1,b[2]=0,b[3]=1,d[0]=1,d[1]=1,c[0]=0,c[1]=1;for(var g=a.length,h=1;g>h;h++){var f=a[h],i=4*h,j=h/(g-1);h%2?(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1):(b[i]=j,b[i+1]=0,b[i+2]=j,b[i+3]=1),i=2*h,d[i]=1,d[i+1]=1,i=2*h,c[i]=i,c[i+1]=i+1,e=f}}},f.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var b,c=this.verticies,d=a[0],e={x:0,y:0},g=a[0];this.count-=.2,c[0]=g.x+e.x,c[1]=g.y+e.y,c[2]=g.x-e.x,c[3]=g.y-e.y;for(var h=a.length,i=1;h>i;i++){var g=a[i],j=4*i;b=i1&&(k=1);var l=Math.sqrt(e.x*e.x+e.y*e.y),m=this.texture.height/2;e.x/=l,e.y/=l,e.x*=m,e.y*=m,c[j]=g.x+e.x,c[j+1]=g.y+e.y,c[j+2]=g.x-e.x,c[j+3]=g.y-e.y,d=g}f.DisplayObjectContainer.prototype.updateTransform.call(this)}},f.Rope.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite=function(a,b,c){f.DisplayObjectContainer.call(this),this.texture=a,this.width=b,this.height=c,this.tileScale=new f.Point(1,1),this.tilePosition=new f.Point(0,0),this.renderable=!0,this.blendMode=f.blendModes.NORMAL},f.TilingSprite.prototype=Object.create(f.DisplayObjectContainer.prototype),f.TilingSprite.prototype.constructor=f.TilingSprite,f.TilingSprite.prototype.setTexture=function(a){this.texture=a,this.updateFrame=!0},f.TilingSprite.prototype.onTextureUpdate=function(){this.updateFrame=!0},f.Spine=function(a){if(f.DisplayObjectContainer.call(this),this.spineData=f.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new l.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new l.AnimationStateData(this.spineData),this.state=new l.AnimationState(this.stateData),this.slotContainers=[];for(var b=0,c=this.skeleton.drawOrder.length;c>b;b++){var d=this.skeleton.drawOrder[b],e=d.attachment,g=new f.DisplayObjectContainer;if(this.slotContainers.push(g),this.addChild(g),e instanceof l.RegionAttachment){var h=e.rendererObject.name,i=this.createSprite(d,e.rendererObject);d.currentSprite=i,d.currentSpriteName=h,g.addChild(i)}}},f.Spine.prototype=Object.create(f.DisplayObjectContainer.prototype),f.Spine.prototype.constructor=f.Spine,f.Spine.prototype.updateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var b=this.skeleton.drawOrder,c=0,d=b.length;d>c;c++){var e=b[c],g=e.attachment,h=this.slotContainers[c];if(g instanceof l.RegionAttachment){if(g.rendererObject&&(!e.currentSpriteName||e.currentSpriteName!=g.name)){var i=g.rendererObject.name;if(void 0!==e.currentSprite&&(e.currentSprite.visible=!1),e.sprites=e.sprites||{},void 0!==e.sprites[i])e.sprites[i].visible=!0;else{var j=this.createSprite(e,g.rendererObject);h.addChild(j)}e.currentSprite=e.sprites[i],e.currentSpriteName=i}h.visible=!0;var k=e.bone;h.position.x=k.worldX+g.x*k.m00+g.y*k.m01,h.position.y=k.worldY+g.x*k.m10+g.y*k.m11,h.scale.x=k.worldScaleX,h.scale.y=k.worldScaleY,h.rotation=-(e.bone.worldRotation*Math.PI/180)}else h.visible=!1}f.DisplayObjectContainer.prototype.updateTransform.call(this)},f.Spine.prototype.createSprite=function(a,b){var c=f.TextureCache[b.name]?b.name:b.name+".png",d=new f.Sprite(f.Texture.fromFrame(c));return d.scale=b.scale,d.rotation=b.rotation,d.anchor.x=d.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[b.name]=d,d};var l={};l.BoneData=function(a,b){this.name=a,this.parent=b},l.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1},l.SlotData=function(a,b){this.name=a,this.boneData=b},l.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null},l.Bone=function(a,b){this.data=a,this.parent=b,this.setToSetupPose()},l.Bone.yDown=!1,l.Bone.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,updateWorldTransform:function(a,b){var c=this.parent;null!=c?(this.worldX=this.x*c.m00+this.y*c.m01+c.worldX,this.worldY=this.x*c.m10+this.y*c.m11+c.worldY,this.worldScaleX=c.worldScaleX*this.scaleX,this.worldScaleY=c.worldScaleY*this.scaleY,this.worldRotation=c.worldRotation+this.rotation):(this.worldX=this.x,this.worldY=this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotation);var d=this.worldRotation*Math.PI/180,e=Math.cos(d),f=Math.sin(d);this.m00=e*this.worldScaleX,this.m10=f*this.worldScaleX,this.m01=-f*this.worldScaleY,this.m11=e*this.worldScaleY,a&&(this.m00=-this.m00,this.m01=-this.m01),b&&(this.m10=-this.m10,this.m11=-this.m11),l.Bone.yDown&&(this.m10=-this.m10,this.m11=-this.m11)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY}},l.Slot=function(a,b,c){this.data=a,this.skeleton=b,this.bone=c,this.setToSetupPose()},l.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,setAttachment:function(a){this.attachment=a,this._attachmentTime=this.skeleton.time},setAttachmentTime:function(a){this._attachmentTime=this.skeleton.time-a},getAttachmentTime:function(){return this.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},l.Skin=function(a){this.name=a,this.attachments={}},l.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},l.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},l.Animation.prototype={apply:function(a,b,c){c&&0!=this.duration&&(b%=this.duration);for(var d=this.timelines,e=0,f=d.length;f>e;e++)d[e].apply(a,b,1)},mix:function(a,b,c,d){c&&0!=this.duration&&(b%=this.duration);for(var e=this.timelines,f=0,g=e.length;g>f;f++)e[f].apply(a,b,d)}},l.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(0==e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},l.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},l.Curves=function(a){this.curves=[],this.curves.length=6*(a-1)},l.Curves.prototype={setLinear:function(a){this.curves[6*a]=0},setStepped:function(a){this.curves[6*a]=-1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=6*a,r=this.curves;r[q]=b*i+m*j+o*h,r[q+1]=c*i+n*j+p*h,r[q+2]=m*k+o*l,r[q+3]=n*k+p*l,r[q+4]=o*l,r[q+5]=p*l},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=6*a,d=this.curves,e=d[c];if(!e)return b;if(-1==e)return 0;for(var f=d[c+1],g=d[c+2],h=d[c+3],i=d[c+4],j=d[c+5],k=e,l=f,m=8;;){if(k>=b){var n=k-e,o=l-f;return o+(l-o)*(b-n)/(k-n)}if(0==m)break;m--,e+=g,f+=h,g+=i,h+=j,k+=e,l+=f}return l+(1-l)*(b-k)/(1-k)}},l.RotateTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=2*a},l.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-2]){for(var f=e.data.rotation+d[d.length-1]-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;return e.rotation+=f*c,void 0}var g=l.binarySearch(d,b,2),h=d[g-1],i=d[g],j=1-(b-i)/(d[g-2]-i);j=this.curves.getCurvePercent(g/2-1,j);for(var f=d[g+1]-h;f>180;)f-=360;for(;-180>f;)f+=360;for(f=e.data.rotation+(h+f*j)-e.rotation;f>180;)f-=360;for(;-180>f;)f+=360;e.rotation+=f*c}}},l.TranslateTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=3*a},l.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.x+=(e.data.x+d[d.length-2]-e.x)*c,e.y+=(e.data.y+d[d.length-1]-e.y)*c,void 0;var f=l.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.x+=(e.data.x+g+(d[f+1]-g)*j-e.x)*c,e.y+=(e.data.y+h+(d[f+2]-h)*j-e.y)*c}}},l.ScaleTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=3*a},l.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-3])return e.scaleX+=(e.data.scaleX-1+d[d.length-2]-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+d[d.length-1]-e.scaleY)*c,void 0;var f=l.binarySearch(d,b,3),g=d[f-2],h=d[f-1],i=d[f],j=1-(b-i)/(d[f+-3]-i);j=this.curves.getCurvePercent(f/3-1,j),e.scaleX+=(e.data.scaleX-1+g+(d[f+1]-g)*j-e.scaleX)*c,e.scaleY+=(e.data.scaleY-1+h+(d[f+2]-h)*j-e.scaleY)*c}}},l.ColorTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=5*a},l.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(c,d){c*=5,this.frames[c]=d,this.frames[c+1]=r,this.frames[c+2]=g,this.frames[c+3]=b,this.frames[c+4]=a},apply:function(a,b,c){var d=this.frames;if(!(b=d[d.length-5]){var f=d.length-1;return e.r=d[f-3],e.g=d[f-2],e.b=d[f-1],e.a=d[f],void 0}var g=l.binarySearch(d,b,5),h=d[g-4],i=d[g-3],j=d[g-2],k=d[g-1],m=d[g],n=1-(b-m)/(d[g-5]-m);n=this.curves.getCurvePercent(g/5-1,n);var o=h+(d[g+1]-h)*n,p=i+(d[g+2]-i)*n,q=j+(d[g+3]-j)*n,r=k+(d[g+4]-k)*n;1>c?(e.r+=(o-e.r)*c,e.g+=(p-e.g)*c,e.b+=(q-e.b)*c,e.a+=(r-e.a)*c):(e.r=o,e.g=p,e.b=q,e.a=r)}}},l.AttachmentTimeline=function(a){this.curves=new l.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},l.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b){var c=this.frames;if(!(b=c[c.length-1]?c.length-1:l.binarySearch(c,b,1)-1;var e=this.attachmentNames[d];a.slots[this.slotIndex].setAttachment(e?a.getAttachmentBySlotIndex(this.slotIndex,e):null)}}},l.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.animations=[]},l.SkeletonData.prototype={defaultSkin:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},l.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,c=a.bones.length;c>b;b++){var d=a.bones[b],e=d.parent?this.bones[a.bones.indexOf(d.parent)]:null;this.bones.push(new l.Bone(d,e))}this.slots=[],this.drawOrder=[];for(var b=0,c=a.slots.length;c>b;b++){var f=a.slots[b],g=this.bones[a.bones.indexOf(f.boneData)],h=new l.Slot(f,this,g);this.slots.push(h),this.drawOrder.push(h)}},l.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateWorldTransform:function(){for(var a=this.flipX,b=this.flipY,c=this.bones,d=0,e=c.length;e>d;d++)c[d].updateWorldTransform(a,b)},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose()},setSlotsToSetupPose:function(){for(var a=this.slots,b=0,c=a.length;c>b;b++)a[b].setToSetupPose(b)},getRootBone:function(){return 0==this.bones.length?null:this.bones[0]},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a);if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){this.skin&&a&&a._attachAll(this,this.skin),this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.size;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachment(d,b),null==g))throw"Attachment not found: "+b+", for slot: "+a;return f.setAttachment(g),void 0}}throw"Slot not found: "+a},update:function(a){time+=a}},l.AttachmentType={region:0},l.RegionAttachment=function(){this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},l.RegionAttachment.prototype={x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,c=-this.width/2*this.scaleX+this.regionOffsetX*a,d=-this.height/2*this.scaleY+this.regionOffsetY*b,e=c+this.regionWidth*a,f=d+this.regionHeight*b,g=this.rotation*Math.PI/180,h=Math.cos(g),i=Math.sin(g),j=c*h+this.x,k=c*i,l=d*h+this.y,m=d*i,n=e*h+this.x,o=e*i,p=f*h+this.y,q=f*i,r=this.offset;r[0]=j-m,r[1]=l+k,r[2]=j-q,r[3]=p+k,r[4]=n-q,r[5]=p+o,r[6]=n-m,r[7]=l+o},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},l.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},l.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=this.animationToMixTime[a.name+":"+b.name];return c?c:this.defaultMix}},l.AnimationState=function(a){this.data=a,this.queue=[]},l.AnimationState.prototype={current:null,previous:null,currentTime:0,previousTime:0,currentLoop:!1,previousLoop:!1,mixTime:0,mixDuration:0,update:function(a){if(this.currentTime+=a,this.previousTime+=a,this.mixTime+=a,this.queue.length>0){var b=this.queue[0];this.currentTime>=b.delay&&(this._setAnimation(b.animation,b.loop),this.queue.shift())}},apply:function(a){if(this.current)if(this.previous){this.previous.apply(a,this.previousTime,this.previousLoop);var b=this.mixTime/this.mixDuration;b>=1&&(b=1,this.previous=null),this.current.mix(a,this.currentTime,this.currentLoop,b)}else this.current.apply(a,this.currentTime,this.currentLoop)},clearAnimation:function(){this.previous=null,this.current=null,this.queue.length=0},_setAnimation:function(a,b){this.previous=null,a&&this.current&&(this.mixDuration=this.data.getMix(this.current,a),this.mixDuration>0&&(this.mixTime=0,this.previous=this.current,this.previousTime=this.currentTime,this.previousLoop=this.currentLoop)),this.current=a,this.currentLoop=b,this.currentTime=0},setAnimationByName:function(a,b){var c=this.data.skeletonData.findAnimation(a);if(!c)throw"Animation not found: "+a;this.setAnimation(c,b)},setAnimation:function(a,b){this.queue.length=0,this._setAnimation(a,b)},addAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;this.addAnimation(d,b,c)},addAnimation:function(a,b,c){var d={};if(d.animation=a,d.loop=b,!c||0>=c){var e=0==this.queue.length?this.current:this.queue[this.queue.length-1].animation;c=null!=e?e.duration-this.data.getMix(e,a)+(c||0):0}d.delay=c,this.queue.push(d)},isComplete:function(){return!this.current||this.currentTime>=this.current.duration}},l.SkeletonJson=function(a){this.attachmentLoader=a},l.SkeletonJson.prototype={scale:1,readSkeletonData:function(a){for(var b=new l.SkeletonData,c=a.bones,d=0,e=c.length;e>d;d++){var f=c[d],g=null;if(f.parent&&(g=b.findBone(f.parent),!g))throw"Parent bone not found: "+f.parent;var h=new l.BoneData(f.name,g);h.length=(f.length||0)*this.scale,h.x=(f.x||0)*this.scale,h.y=(f.y||0)*this.scale,h.rotation=f.rotation||0,h.scaleX=f.scaleX||1,h.scaleY=f.scaleY||1,b.bones.push(h)}for(var i=a.slots,d=0,e=i.length;e>d;d++){var j=i[d],h=b.findBone(j.bone);if(!h)throw"Slot bone not found: "+j.bone;var k=new l.SlotData(j.name,h),m=j.color;m&&(k.r=l.SkeletonJson.toColor(m,0),k.g=l.SkeletonJson.toColor(m,1),k.b=l.SkeletonJson.toColor(m,2),k.a=l.SkeletonJson.toColor(m,3)),k.attachmentName=j.attachment,b.slots.push(k)}var n=a.skins;for(var o in n)if(n.hasOwnProperty(o)){var p=n[o],q=new l.Skin(o);for(var r in p)if(p.hasOwnProperty(r)){var s=b.findSlotIndex(r),t=p[r];for(var u in t)if(t.hasOwnProperty(u)){var v=this.readAttachment(q,u,t[u]);null!=v&&q.addAttachment(s,u,v)}}b.skins.push(q),"default"==q.name&&(b.defaultSkin=q)}var w=a.animations;for(var x in w)w.hasOwnProperty(x)&&this.readAnimation(x,w[x],b);return b},readAttachment:function(a,b,c){b=c.name||b;var d=l.AttachmentType[c.type||"region"];if(d==l.AttachmentType.region){var e=new l.RegionAttachment;return e.x=(c.x||0)*this.scale,e.y=(c.y||0)*this.scale,e.scaleX=c.scaleX||1,e.scaleY=c.scaleY||1,e.rotation=c.rotation||0,e.width=(c.width||32)*this.scale,e.height=(c.height||32)*this.scale,e.updateOffset(),e.rendererObject={},e.rendererObject.name=b,e.rendererObject.scale={},e.rendererObject.scale.x=e.scaleX,e.rendererObject.scale.y=e.scaleY,e.rendererObject.rotation=-e.rotation*Math.PI/180,e -}throw"Unknown attachment type: "+d},readAnimation:function(a,b,c){var d=[],e=0,f=b.bones;for(var g in f)if(f.hasOwnProperty(g)){var h=c.findBoneIndex(g);if(-1==h)throw"Bone not found: "+g;var i=f[g];for(var j in i)if(i.hasOwnProperty(j)){var k=i[j];if("rotate"==j){var m=new l.RotateTimeline(k.length);m.boneIndex=h;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o];m.setFrame(n,q.time,q.angle),l.SkeletonJson.readCurve(m,n,q),n++}d.push(m),e=Math.max(e,m.frames[2*m.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var m,r=1;"scale"==j?m=new l.ScaleTimeline(k.length):(m=new l.TranslateTimeline(k.length),r=this.scale),m.boneIndex=h;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;m.setFrame(n,q.time,s,t),l.SkeletonJson.readCurve(m,n,q),n++}d.push(m),e=Math.max(e,m.frames[3*m.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var m=new l.ColorTimeline(k.length);m.slotIndex=x;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=l.SkeletonJson.toColor(y,0),A=l.SkeletonJson.toColor(y,1),B=l.SkeletonJson.toColor(y,2),C=l.SkeletonJson.toColor(y,3);m.setFrame(n,q.time,z,A,B,C),l.SkeletonJson.readCurve(m,n,q),n++}d.push(m),e=Math.max(e,m.frames[5*m.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var m=new l.AttachmentTimeline(k.length);m.slotIndex=x;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o];m.setFrame(n++,q.time,q.name)}d.push(m),e=Math.max(e,m.frames[m.getFrameCount()-1])}}}c.animations.push(new l.Animation(a,d,e))}},l.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},l.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},l.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new l.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new l.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new l.AtlasPage,e.name=f,e.format=l.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=l.Atlas.TextureFilter[d[0]],e.magFilter=l.Atlas.TextureFilter[d[1]];var m=c.readValue();e.uWrap=l.Atlas.TextureWrap.clampToEdge,e.vWrap=l.Atlas.TextureWrap.clampToEdge,"x"==m?e.uWrap=l.Atlas.TextureWrap.repeat:"y"==m?e.vWrap=l.Atlas.TextureWrap.repeat:"xy"==m&&(e.uWrap=e.vWrap=l.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},l.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},l.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},l.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},l.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},l.AtlasPage=function(){},l.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},l.AtlasRegion=function(){},l.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},l.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},l.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},l.AtlasAttachmentLoader=function(a){this.atlas=a},l.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case l.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new l.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},l.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;ho;o++){var q=k[o];m.setFrame(n,q.time,q.angle),l.SkeletonJson.readCurve(m,n,q),n++}d.push(m),e=Math.max(e,m.frames[2*m.getFrameCount()-2])}else{if("translate"!=j&&"scale"!=j)throw"Invalid timeline type for a bone: "+j+" ("+g+")";var m,r=1;"scale"==j?m=new l.ScaleTimeline(k.length):(m=new l.TranslateTimeline(k.length),r=this.scale),m.boneIndex=h;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o],s=(q.x||0)*r,t=(q.y||0)*r;m.setFrame(n,q.time,s,t),l.SkeletonJson.readCurve(m,n,q),n++}d.push(m),e=Math.max(e,m.frames[3*m.getFrameCount()-3])}}}var u=b.slots;for(var v in u)if(u.hasOwnProperty(v)){var w=u[v],x=c.findSlotIndex(v);for(var j in w)if(w.hasOwnProperty(j)){var k=w[j];if("color"==j){var m=new l.ColorTimeline(k.length);m.slotIndex=x;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o],y=q.color,z=l.SkeletonJson.toColor(y,0),A=l.SkeletonJson.toColor(y,1),B=l.SkeletonJson.toColor(y,2),C=l.SkeletonJson.toColor(y,3);m.setFrame(n,q.time,z,A,B,C),l.SkeletonJson.readCurve(m,n,q),n++}d.push(m),e=Math.max(e,m.frames[5*m.getFrameCount()-5])}else{if("attachment"!=j)throw"Invalid timeline type for a slot: "+j+" ("+v+")";var m=new l.AttachmentTimeline(k.length);m.slotIndex=x;for(var n=0,o=0,p=k.length;p>o;o++){var q=k[o];m.setFrame(n++,q.time,q.name)}d.push(m),e=Math.max(e,m.frames[m.getFrameCount()-1])}}}c.animations.push(new l.Animation(a,d,e))}},l.SkeletonJson.readCurve=function(a,b,c){var d=c.curve;d&&("stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]))},l.SkeletonJson.toColor=function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2),16)/255},l.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var c=new l.AtlasReader(a),d=[];d.length=4;for(var e=null;;){var f=c.readLine();if(null==f)break;if(f=c.trim(f),0==f.length)e=null;else if(e){var g=new l.AtlasRegion;g.name=f,g.page=e,g.rotate="true"==c.readValue(),c.readTuple(d);var h=parseInt(d[0]),i=parseInt(d[1]);c.readTuple(d);var j=parseInt(d[0]),k=parseInt(d[1]);g.u=h/e.width,g.v=i/e.height,g.rotate?(g.u2=(h+k)/e.width,g.v2=(i+j)/e.height):(g.u2=(h+j)/e.width,g.v2=(i+k)/e.height),g.x=h,g.y=i,g.width=Math.abs(j),g.height=Math.abs(k),4==c.readTuple(d)&&(g.splits=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],4==c.readTuple(d)&&(g.pads=[parseInt(d[0]),parseInt(d[1]),parseInt(d[2]),parseInt(d[3])],c.readTuple(d))),g.originalWidth=parseInt(d[0]),g.originalHeight=parseInt(d[1]),c.readTuple(d),g.offsetX=parseInt(d[0]),g.offsetY=parseInt(d[1]),g.index=parseInt(c.readValue()),this.regions.push(g)}else{e=new l.AtlasPage,e.name=f,e.format=l.Atlas.Format[c.readValue()],c.readTuple(d),e.minFilter=l.Atlas.TextureFilter[d[0]],e.magFilter=l.Atlas.TextureFilter[d[1]];var m=c.readValue();e.uWrap=l.Atlas.TextureWrap.clampToEdge,e.vWrap=l.Atlas.TextureWrap.clampToEdge,"x"==m?e.uWrap=l.Atlas.TextureWrap.repeat:"y"==m?e.vWrap=l.Atlas.TextureWrap.repeat:"xy"==m&&(e.uWrap=e.vWrap=l.Atlas.TextureWrap.repeat),b.load(e,f),this.pages.push(e)}}},l.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},l.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},l.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},l.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},l.AtlasPage=function(){},l.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},l.AtlasRegion=function(){},l.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},l.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},l.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f){if(0==d)throw"Invalid line: "+b;break}a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},l.AtlasAttachmentLoader=function(a){this.atlas=a},l.AtlasAttachmentLoader.prototype={newAttachment:function(a,b,c){switch(b){case l.AttachmentType.region:var d=this.atlas.findRegion(c);if(!d)throw"Region not found in atlas: "+c+" ("+b+")";var e=new l.RegionAttachment(c);return e.rendererObject=d,e.setUVs(d.u,d.v,d.u2,d.v2,d.rotate),e.regionOffsetX=d.offsetX,e.regionOffsetY=d.offsetY,e.regionWidth=d.width,e.regionHeight=d.height,e.regionOriginalWidth=d.originalWidth,e.regionOriginalHeight=d.originalHeight,e}throw"Unknown attachment type: "+b}},f.AnimCache={},l.Bone.yDown=!0,f.CustomRenderable=function(){f.DisplayObject.call(this),this.renderable=!0},f.CustomRenderable.prototype=Object.create(f.DisplayObject.prototype),f.CustomRenderable.prototype.constructor=f.CustomRenderable,f.CustomRenderable.prototype.renderCanvas=function(){},f.CustomRenderable.prototype.initWebGL=function(){},f.CustomRenderable.prototype.renderWebGL=function(){},f.BaseTextureCache={},f.texturesToUpdate=[],f.texturesToDestroy=[],f.BaseTexture=function(a){if(f.EventTarget.call(this),this.width=100,this.height=100,this.hasLoaded=!1,this.source=a,a){if(this.source instanceof Image||this.source instanceof HTMLImageElement)if(this.source.complete)this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);else{var b=this;this.source.onload=function(){b.hasLoaded=!0,b.width=b.source.width,b.height=b.source.height,f.texturesToUpdate.push(b),b.dispatchEvent({type:"loaded",content:b})}}else this.hasLoaded=!0,this.width=this.source.width,this.height=this.source.height,f.texturesToUpdate.push(this);this._powerOf2=!1}},f.BaseTexture.prototype.constructor=f.BaseTexture,f.BaseTexture.prototype.destroy=function(){this.source instanceof Image&&(this.source.src=null),this.source=null,f.texturesToDestroy.push(this)},f.BaseTexture.fromImage=function(a,b){var c=f.BaseTextureCache[a];if(!c){var d=new Image;b&&(d.crossOrigin=""),d.src=a,c=new f.BaseTexture(d),f.BaseTextureCache[a]=c}return c},f.TextureCache={},f.FrameCache={},f.Texture=function(a,b){if(f.EventTarget.call(this),b||(this.noFrame=!0,b=new f.Rectangle(0,0,1,1)),a instanceof f.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=b,this.trim=new f.Point,this.scope=this,a.hasLoaded)this.noFrame&&(b=new f.Rectangle(0,0,a.width,a.height)),this.setFrame(b);else{var c=this;a.addEventListener("loaded",function(){c.onBaseTextureLoaded()})}},f.Texture.prototype.constructor=f.Texture,f.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new f.Rectangle(0,0,a.width,a.height)),this.noFrame=!1,this.width=this.frame.width,this.height=this.frame.height,this.scope.dispatchEvent({type:"update",content:this})},f.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy()},f.Texture.prototype.setFrame=function(a){if(this.frame=a,this.width=a.width,this.height=a.height,a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height)throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.updateFrame=!0,f.Texture.frameUpdates.push(this)},f.Texture.fromImage=function(a,b){var c=f.TextureCache[a];return c||(c=new f.Texture(f.BaseTexture.fromImage(a,b)),f.TextureCache[a]=c),c},f.Texture.fromFrame=function(a){var b=f.TextureCache[a];if(!b)throw new Error("The frameId '"+a+"' does not exist in the texture cache "+this);return b},f.Texture.fromCanvas=function(a){var b=new f.BaseTexture(a);return new f.Texture(b)},f.Texture.addTextureToCache=function(a,b){f.TextureCache[b]=a},f.Texture.removeTextureFromCache=function(a){var b=f.TextureCache[a];return f.TextureCache[a]=null,b},f.Texture.frameUpdates=[],f.RenderTexture=function(a,b){f.EventTarget.call(this),this.width=a||100,this.height=b||100,this.indetityMatrix=f.mat3.create(),this.frame=new f.Rectangle(0,0,this.width,this.height),f.gl?this.initWebGL():this.initCanvas()},f.RenderTexture.prototype=Object.create(f.Texture.prototype),f.RenderTexture.prototype.constructor=f.RenderTexture,f.RenderTexture.prototype.initWebGL=function(){var a=f.gl;this.glFramebuffer=a.createFramebuffer(),a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),this.glFramebuffer.width=this.width,this.glFramebuffer.height=this.height,this.baseTexture=new f.BaseTexture,this.baseTexture.width=this.width,this.baseTexture.height=this.height,this.baseTexture._glTexture=a.createTexture(),a.bindTexture(a.TEXTURE_2D,this.baseTexture._glTexture),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,this.width,this.height,0,a.RGBA,a.UNSIGNED_BYTE,null),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),this.baseTexture.isRender=!0,a.bindFramebuffer(a.FRAMEBUFFER,this.glFramebuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.baseTexture._glTexture,0),this.projection=new f.Point(this.width/2,-this.height/2),this.render=this.renderWebGL},f.RenderTexture.prototype.resize=function(a,b){if(this.width=a,this.height=b,f.gl){this.projection.x=this.width/2,this.projection.y=-this.height/2;var c=f.gl;c.bindTexture(c.TEXTURE_2D,this.baseTexture._glTexture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,this.width,this.height,0,c.RGBA,c.UNSIGNED_BYTE,null)}else this.frame.width=this.width,this.frame.height=this.height,this.renderer.resize(this.width,this.height)},f.RenderTexture.prototype.initCanvas=function(){this.renderer=new f.CanvasRenderer(this.width,this.height,null,0),this.baseTexture=new f.BaseTexture(this.renderer.view),this.frame=new f.Rectangle(0,0,this.width,this.height),this.render=this.renderCanvas},f.RenderTexture.prototype.renderWebGL=function(a,b,c){var d=f.gl;d.colorMask(!0,!0,!0,!0),d.viewport(0,0,this.width,this.height),d.bindFramebuffer(d.FRAMEBUFFER,this.glFramebuffer),c&&(d.clearColor(0,0,0,0),d.clear(d.COLOR_BUFFER_BIT));var e=a.children,g=a.worldTransform;a.worldTransform=f.mat3.create(),a.worldTransform[4]=-1,a.worldTransform[5]=-2*this.projection.y,b&&(a.worldTransform[2]=b.x,a.worldTransform[5]-=b.y),f.visibleCount++,a.vcount=f.visibleCount;for(var h=0,i=e.length;i>h;h++)e[h].updateTransform();var j=a.__renderGroup;j?a==j.root?j.render(this.projection,this.glFramebuffer):j.renderSpecific(a,this.projection,this.glFramebuffer):(this.renderGroup||(this.renderGroup=new f.WebGLRenderGroup(d)),this.renderGroup.setRenderable(a),this.renderGroup.render(this.projection,this.glFramebuffer)),a.worldTransform=g},f.RenderTexture.prototype.renderCanvas=function(a,b,c){var d=a.children;a.worldTransform=f.mat3.create(),b&&(a.worldTransform[2]=b.x,a.worldTransform[5]=b.y);for(var e=0,g=d.length;g>e;e++)d[e].updateTransform();c&&this.renderer.context.clearRect(0,0,this.width,this.height),this.renderer.renderDisplayObject(a),this.renderer.context.setTransform(1,0,0,1,0,0)},f.AssetLoader=function(a,b){f.EventTarget.call(this),this.assetURLs=a,this.crossorigin=b,this.loadersByType={jpg:f.ImageLoader,jpeg:f.ImageLoader,png:f.ImageLoader,gif:f.ImageLoader,json:f.JsonLoader,anim:f.SpineLoader,xml:f.BitmapFontLoader,fnt:f.BitmapFontLoader}},f.AssetLoader.prototype.constructor=f.AssetLoader,f.AssetLoader.prototype.load=function(){var a=this;this.loadCount=this.assetURLs.length;for(var b=0;bh;h++)for(var i=0;d>i;i++,g++){var j=new f.Texture(this.texture,{x:i*a,y:h*b,width:a,height:b});this.frames.push(j),c&&(f.TextureCache[c+"-"+g]=j)}if(this.texture.baseTexture.hasLoaded)this.onLoaded();else{var k=this;this.texture.baseTexture.addEventListener("loaded",function(){k.onLoaded()})}},f.BitmapFontLoader=function(a,b){f.EventTarget.call(this),this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},f.BitmapFontLoader.prototype.constructor=f.BitmapFontLoader,f.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new XMLHttpRequest;var a=this;this.ajaxRequest.onreadystatechange=function(){a.onXMLLoaded()},this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},f.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4==this.ajaxRequest.readyState&&(200==this.ajaxRequest.status||-1==window.location.href.indexOf("http"))){var a=this.baseUrl+this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue,b=new f.ImageLoader(a,this.crossorigin);this.texture=b.texture.baseTexture;var c={},d=this.ajaxRequest.responseXML.getElementsByTagName("info")[0],e=this.ajaxRequest.responseXML.getElementsByTagName("common")[0];c.font=d.attributes.getNamedItem("face").nodeValue,c.size=parseInt(d.attributes.getNamedItem("size").nodeValue,10),c.lineHeight=parseInt(e.attributes.getNamedItem("lineHeight").nodeValue,10),c.chars={};for(var g=this.ajaxRequest.responseXML.getElementsByTagName("char"),h=0;h=0;f--)d=[c[f].apply(this,d)];return d[0]}}, +each:function(a,d,f){if(e&&a.forEach===e)a.forEach(d,f);else if(a.length===a.length+0)for(var b=0,n=a.length;b-1?d.length-d.indexOf(".")-1:0};c.superclass=e;a.extend(c.prototype,e.prototype,{setValue:function(a){if(this.__min!==void 0&&athis.__max)a=this.__max;this.__step!==void 0&&a%this.__step!=0&&(a=Math.round(a/this.__step)*this.__step);return c.superclass.prototype.setValue.call(this,a)},min:function(a){this.__min=a;return this},max:function(a){this.__max=a;return this},step:function(a){this.__step=a;return this}});return c}(dat.controllers.Controller,dat.utils.common); +dat.controllers.NumberControllerBox=function(e,a,c){var d=function(f,b,e){function h(){var a=parseFloat(l.__input.value);c.isNaN(a)||l.setValue(a)}function j(a){var b=o-a.clientY;l.setValue(l.getValue()+b*l.__impliedStep);o=a.clientY}function m(){a.unbind(window,"mousemove",j);a.unbind(window,"mouseup",m)}this.__truncationSuspended=false;d.superclass.call(this,f,b,e);var l=this,o;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"change",h); +a.bind(this.__input,"blur",function(){h();l.__onFinishChange&&l.__onFinishChange.call(l,l.getValue())});a.bind(this.__input,"mousedown",function(b){a.bind(window,"mousemove",j);a.bind(window,"mouseup",m);o=b.clientY});a.bind(this.__input,"keydown",function(a){if(a.keyCode===13)l.__truncationSuspended=true,this.blur(),l.__truncationSuspended=false});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;c.extend(d.prototype,e.prototype,{updateDisplay:function(){var a=this.__input, +b;if(this.__truncationSuspended)b=this.getValue();else{b=this.getValue();var c=Math.pow(10,this.__precision);b=Math.round(b*c)/c}a.value=b;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.NumberController,dat.dom.dom,dat.utils.common); +dat.controllers.NumberControllerSlider=function(e,a,c,d,f){var b=function(d,c,f,e,l){function o(b){b.preventDefault();var d=a.getOffset(g.__background),c=a.getWidth(g.__background);g.setValue(g.__min+(g.__max-g.__min)*((b.clientX-d.left)/(d.left+c-d.left)));return false}function y(){a.unbind(window,"mousemove",o);a.unbind(window,"mouseup",y);g.__onFinishChange&&g.__onFinishChange.call(g,g.getValue())}b.superclass.call(this,d,c,{min:f,max:e,step:l});var g=this;this.__background=document.createElement("div"); +this.__foreground=document.createElement("div");a.bind(this.__background,"mousedown",function(b){a.bind(window,"mousemove",o);a.bind(window,"mouseup",y);o(b)});a.addClass(this.__background,"slider");a.addClass(this.__foreground,"slider-fg");this.updateDisplay();this.__background.appendChild(this.__foreground);this.domElement.appendChild(this.__background)};b.superclass=e;b.useDefaultStyles=function(){c.inject(f)};d.extend(b.prototype,e.prototype,{updateDisplay:function(){this.__foreground.style.width= +(this.getValue()-this.__min)/(this.__max-this.__min)*100+"%";return b.superclass.prototype.updateDisplay.call(this)}});return b}(dat.controllers.NumberController,dat.dom.dom,dat.utils.css,dat.utils.common,".slider {\n box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);\n height: 1em;\n border-radius: 1em;\n background-color: #eee;\n padding: 0 0.5em;\n overflow: hidden;\n}\n\n.slider-fg {\n padding: 1px 0 2px 0;\n background-color: #aaa;\n height: 1em;\n margin-left: -0.5em;\n padding-right: 0.5em;\n border-radius: 1em 0 0 1em;\n}\n\n.slider-fg:after {\n display: inline-block;\n border-radius: 1em;\n background-color: #fff;\n border: 1px solid #aaa;\n content: '';\n float: right;\n margin-right: -1em;\n margin-top: -1px;\n height: 0.9em;\n width: 0.9em;\n}"); +dat.controllers.FunctionController=function(e,a,c){var d=function(c,b,e){d.superclass.call(this,c,b);var h=this;this.__button=document.createElement("div");this.__button.innerHTML=e===void 0?"Fire":e;a.bind(this.__button,"click",function(a){a.preventDefault();h.fire();return false});a.addClass(this.__button,"button");this.domElement.appendChild(this.__button)};d.superclass=e;c.extend(d.prototype,e.prototype,{fire:function(){this.__onChange&&this.__onChange.call(this);this.__onFinishChange&&this.__onFinishChange.call(this, +this.getValue());this.getValue().call(this.object)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common); +dat.controllers.BooleanController=function(e,a,c){var d=function(c,b){d.superclass.call(this,c,b);var e=this;this.__prev=this.getValue();this.__checkbox=document.createElement("input");this.__checkbox.setAttribute("type","checkbox");a.bind(this.__checkbox,"change",function(){e.setValue(!e.__prev)},false);this.domElement.appendChild(this.__checkbox);this.updateDisplay()};d.superclass=e;c.extend(d.prototype,e.prototype,{setValue:function(a){a=d.superclass.prototype.setValue.call(this,a);this.__onFinishChange&& +this.__onFinishChange.call(this,this.getValue());this.__prev=this.getValue();return a},updateDisplay:function(){this.getValue()===true?(this.__checkbox.setAttribute("checked","checked"),this.__checkbox.checked=true):this.__checkbox.checked=false;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common); +dat.color.toString=function(e){return function(a){if(a.a==1||e.isUndefined(a.a)){for(a=a.hex.toString(16);a.length<6;)a="0"+a;return"#"+a}else return"rgba("+Math.round(a.r)+","+Math.round(a.g)+","+Math.round(a.b)+","+a.a+")"}}(dat.utils.common); +dat.color.interpret=function(e,a){var c,d,f=[{litmus:a.isString,conversions:{THREE_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i);return a===null?false:{space:"HEX",hex:parseInt("0x"+a[1].toString()+a[1].toString()+a[2].toString()+a[2].toString()+a[3].toString()+a[3].toString())}},write:e},SIX_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9]{6})$/i);return a===null?false:{space:"HEX",hex:parseInt("0x"+a[1].toString())}},write:e},CSS_RGB:{read:function(a){a=a.match(/^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/); +return a===null?false:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3])}},write:e},CSS_RGBA:{read:function(a){a=a.match(/^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\,\s*(.+)\s*\)/);return a===null?false:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3]),a:parseFloat(a[4])}},write:e}}},{litmus:a.isNumber,conversions:{HEX:{read:function(a){return{space:"HEX",hex:a,conversionName:"HEX"}},write:function(a){return a.hex}}}},{litmus:a.isArray,conversions:{RGB_ARRAY:{read:function(a){return a.length!= +3?false:{space:"RGB",r:a[0],g:a[1],b:a[2]}},write:function(a){return[a.r,a.g,a.b]}},RGBA_ARRAY:{read:function(a){return a.length!=4?false:{space:"RGB",r:a[0],g:a[1],b:a[2],a:a[3]}},write:function(a){return[a.r,a.g,a.b,a.a]}}}},{litmus:a.isObject,conversions:{RGBA_OBJ:{read:function(b){return a.isNumber(b.r)&&a.isNumber(b.g)&&a.isNumber(b.b)&&a.isNumber(b.a)?{space:"RGB",r:b.r,g:b.g,b:b.b,a:b.a}:false},write:function(a){return{r:a.r,g:a.g,b:a.b,a:a.a}}},RGB_OBJ:{read:function(b){return a.isNumber(b.r)&& +a.isNumber(b.g)&&a.isNumber(b.b)?{space:"RGB",r:b.r,g:b.g,b:b.b}:false},write:function(a){return{r:a.r,g:a.g,b:a.b}}},HSVA_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)&&a.isNumber(b.a)?{space:"HSV",h:b.h,s:b.s,v:b.v,a:b.a}:false},write:function(a){return{h:a.h,s:a.s,v:a.v,a:a.a}}},HSV_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)?{space:"HSV",h:b.h,s:b.s,v:b.v}:false},write:function(a){return{h:a.h,s:a.s,v:a.v}}}}}];return function(){d= +false;var b=arguments.length>1?a.toArray(arguments):arguments[0];a.each(f,function(e){if(e.litmus(b))return a.each(e.conversions,function(e,f){c=e.read(b);if(d===false&&c!==false)return d=c,c.conversionName=f,c.conversion=e,a.BREAK}),a.BREAK});return d}}(dat.color.toString,dat.utils.common); +dat.GUI=dat.gui.GUI=function(e,a,c,d,f,b,n,h,j,m,l,o,y,g,i){function q(a,b,r,c){if(b[r]===void 0)throw Error("Object "+b+' has no property "'+r+'"');c.color?b=new l(b,r):(b=[b,r].concat(c.factoryArgs),b=d.apply(a,b));if(c.before instanceof f)c.before=c.before.__li;t(a,b);g.addClass(b.domElement,"c");r=document.createElement("span");g.addClass(r,"property-name");r.innerHTML=b.property;var e=document.createElement("div");e.appendChild(r);e.appendChild(b.domElement);c=s(a,e,c.before);g.addClass(c,k.CLASS_CONTROLLER_ROW); +g.addClass(c,typeof b.getValue());p(a,c,b);a.__controllers.push(b);return b}function s(a,b,d){var c=document.createElement("li");b&&c.appendChild(b);d?a.__ul.insertBefore(c,params.before):a.__ul.appendChild(c);a.onResize();return c}function p(a,d,c){c.__li=d;c.__gui=a;i.extend(c,{options:function(b){if(arguments.length>1)return c.remove(),q(a,c.object,c.property,{before:c.__li.nextElementSibling,factoryArgs:[i.toArray(arguments)]});if(i.isArray(b)||i.isObject(b))return c.remove(),q(a,c.object,c.property, +{before:c.__li.nextElementSibling,factoryArgs:[b]})},name:function(a){c.__li.firstElementChild.firstElementChild.innerHTML=a;return c},listen:function(){c.__gui.listen(c);return c},remove:function(){c.__gui.remove(c);return c}});if(c instanceof j){var e=new h(c.object,c.property,{min:c.__min,max:c.__max,step:c.__step});i.each(["updateDisplay","onChange","onFinishChange"],function(a){var b=c[a],H=e[a];c[a]=e[a]=function(){var a=Array.prototype.slice.call(arguments);b.apply(c,a);return H.apply(e,a)}}); +g.addClass(d,"has-slider");c.domElement.insertBefore(e.domElement,c.domElement.firstElementChild)}else if(c instanceof h){var f=function(b){return i.isNumber(c.__min)&&i.isNumber(c.__max)?(c.remove(),q(a,c.object,c.property,{before:c.__li.nextElementSibling,factoryArgs:[c.__min,c.__max,c.__step]})):b};c.min=i.compose(f,c.min);c.max=i.compose(f,c.max)}else if(c instanceof b)g.bind(d,"click",function(){g.fakeEvent(c.__checkbox,"click")}),g.bind(c.__checkbox,"click",function(a){a.stopPropagation()}); +else if(c instanceof n)g.bind(d,"click",function(){g.fakeEvent(c.__button,"click")}),g.bind(d,"mouseover",function(){g.addClass(c.__button,"hover")}),g.bind(d,"mouseout",function(){g.removeClass(c.__button,"hover")});else if(c instanceof l)g.addClass(d,"color"),c.updateDisplay=i.compose(function(a){d.style.borderLeftColor=c.__color.toString();return a},c.updateDisplay),c.updateDisplay();c.setValue=i.compose(function(b){a.getRoot().__preset_select&&c.isModified()&&B(a.getRoot(),true);return b},c.setValue)} +function t(a,b){var c=a.getRoot(),d=c.__rememberedObjects.indexOf(b.object);if(d!=-1){var e=c.__rememberedObjectIndecesToControllers[d];e===void 0&&(e={},c.__rememberedObjectIndecesToControllers[d]=e);e[b.property]=b;if(c.load&&c.load.remembered){c=c.load.remembered;if(c[a.preset])c=c[a.preset];else if(c[w])c=c[w];else return;if(c[d]&&c[d][b.property]!==void 0)d=c[d][b.property],b.initialValue=d,b.setValue(d)}}}function I(a){var b=a.__save_row=document.createElement("li");g.addClass(a.domElement, +"has-save");a.__ul.insertBefore(b,a.__ul.firstChild);g.addClass(b,"save-row");var c=document.createElement("span");c.innerHTML=" ";g.addClass(c,"button gears");var d=document.createElement("span");d.innerHTML="Save";g.addClass(d,"button");g.addClass(d,"save");var e=document.createElement("span");e.innerHTML="New";g.addClass(e,"button");g.addClass(e,"save-as");var f=document.createElement("span");f.innerHTML="Revert";g.addClass(f,"button");g.addClass(f,"revert");var m=a.__preset_select=document.createElement("select"); +a.load&&a.load.remembered?i.each(a.load.remembered,function(b,c){C(a,c,c==a.preset)}):C(a,w,false);g.bind(m,"change",function(){for(var b=0;b0){a.preset=this.preset;if(!a.remembered)a.remembered={};a.remembered[this.preset]=z(this)}a.folders={};i.each(this.__folders,function(b, +c){a.folders[c]=b.getSaveObject()});return a},save:function(){if(!this.load.remembered)this.load.remembered={};this.load.remembered[this.preset]=z(this);B(this,false)},saveAs:function(a){if(!this.load.remembered)this.load.remembered={},this.load.remembered[w]=z(this,true);this.load.remembered[a]=z(this);this.preset=a;C(this,a,true)},revert:function(a){i.each(this.__controllers,function(b){this.getRoot().load.remembered?t(a||this.getRoot(),b):b.setValue(b.initialValue)},this);i.each(this.__folders, +function(a){a.revert(a)});a||B(this.getRoot(),false)},listen:function(a){var b=this.__listening.length==0;this.__listening.push(a);b&&E(this.__listening)}});return k}(dat.utils.css,'
    \n\n Here\'s the new load parameter for your GUI\'s constructor:\n\n \n\n
    \n\n Automatically save\n values to localStorage on exit.\n\n
    The values saved to localStorage will\n override those passed to dat.GUI\'s constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n \n
    \n \n
    \n\n
    ', +".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{-webkit-transition:opacity 0.1s linear;-o-transition:opacity 0.1s linear;-moz-transition:opacity 0.1s linear;transition:opacity 0.1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1 !important}.dg.main:hover .close-button,.dg.main .close-button.drag{opacity:1}.dg.main .close-button{-webkit-transition:opacity 0.1s linear;-o-transition:opacity 0.1s linear;-moz-transition:opacity 0.1s linear;transition:opacity 0.1s linear;border:0;position:absolute;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-x:hidden}.dg.a.has-save ul{margin-top:27px}.dg.a.has-save ul.closed{margin-top:0}.dg.a .save-row{position:fixed;top:0;z-index:1002}.dg li{-webkit-transition:height 0.1s ease-out;-o-transition:height 0.1s ease-out;-moz-transition:height 0.1s ease-out;transition:height 0.1s ease-out}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;overflow:hidden;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid rgba(0,0,0,0)}.dg li.title{cursor:pointer;margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li > *{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .c{float:left;width:60%}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:9px}.dg .c select{margin-top:5px}.dg .cr.function,.dg .cr.function .property-name,.dg .cr.function *,.dg .cr.boolean,.dg .cr.boolean *{cursor:pointer}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0px 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco, monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px 'Lucida Grande', sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px 4px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid rgba(255,255,255,0.2)}.dg .closed li.title{background-image:url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==)}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2fa1d6}.dg .cr.number input[type=text]{color:#2fa1d6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.function:hover,.dg .cr.boolean:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2fa1d6}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}\n", +dat.controllers.factory=function(e,a,c,d,f,b,n){return function(h,j,m,l){var o=h[j];if(n.isArray(m)||n.isObject(m))return new e(h,j,m);if(n.isNumber(o))return n.isNumber(m)&&n.isNumber(l)?new c(h,j,m,l):new a(h,j,{min:m,max:l});if(n.isString(o))return new d(h,j);if(n.isFunction(o))return new f(h,j,"");if(n.isBoolean(o))return new b(h,j)}}(dat.controllers.OptionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.StringController=function(e,a,c){var d= +function(c,b){function e(){h.setValue(h.__input.value)}d.superclass.call(this,c,b);var h=this;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"keyup",e);a.bind(this.__input,"change",e);a.bind(this.__input,"blur",function(){h.__onFinishChange&&h.__onFinishChange.call(h,h.getValue())});a.bind(this.__input,"keydown",function(a){a.keyCode===13&&this.blur()});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;c.extend(d.prototype, +e.prototype,{updateDisplay:function(){if(!a.isActive(this.__input))this.__input.value=this.getValue();return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common),dat.controllers.FunctionController,dat.controllers.BooleanController,dat.utils.common),dat.controllers.Controller,dat.controllers.BooleanController,dat.controllers.FunctionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.OptionController, +dat.controllers.ColorController=function(e,a,c,d,f){function b(a,b,c,d){a.style.background="";f.each(j,function(e){a.style.cssText+="background: "+e+"linear-gradient("+b+", "+c+" 0%, "+d+" 100%); "})}function n(a){a.style.background="";a.style.cssText+="background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);";a.style.cssText+="background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"; +a.style.cssText+="background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"}var h=function(e,l){function o(b){q(b);a.bind(window,"mousemove",q);a.bind(window, +"mouseup",j)}function j(){a.unbind(window,"mousemove",q);a.unbind(window,"mouseup",j)}function g(){var a=d(this.value);a!==false?(p.__color.__state=a,p.setValue(p.__color.toOriginal())):this.value=p.__color.toString()}function i(){a.unbind(window,"mousemove",s);a.unbind(window,"mouseup",i)}function q(b){b.preventDefault();var c=a.getWidth(p.__saturation_field),d=a.getOffset(p.__saturation_field),e=(b.clientX-d.left+document.body.scrollLeft)/c,b=1-(b.clientY-d.top+document.body.scrollTop)/c;b>1?b= +1:b<0&&(b=0);e>1?e=1:e<0&&(e=0);p.__color.v=b;p.__color.s=e;p.setValue(p.__color.toOriginal());return false}function s(b){b.preventDefault();var c=a.getHeight(p.__hue_field),d=a.getOffset(p.__hue_field),b=1-(b.clientY-d.top+document.body.scrollTop)/c;b>1?b=1:b<0&&(b=0);p.__color.h=b*360;p.setValue(p.__color.toOriginal());return false}h.superclass.call(this,e,l);this.__color=new c(this.getValue());this.__temp=new c(0);var p=this;this.domElement=document.createElement("div");a.makeSelectable(this.domElement, +false);this.__selector=document.createElement("div");this.__selector.className="selector";this.__saturation_field=document.createElement("div");this.__saturation_field.className="saturation-field";this.__field_knob=document.createElement("div");this.__field_knob.className="field-knob";this.__field_knob_border="2px solid ";this.__hue_knob=document.createElement("div");this.__hue_knob.className="hue-knob";this.__hue_field=document.createElement("div");this.__hue_field.className="hue-field";this.__input= +document.createElement("input");this.__input.type="text";this.__input_textShadow="0 1px 1px ";a.bind(this.__input,"keydown",function(a){a.keyCode===13&&g.call(this)});a.bind(this.__input,"blur",g);a.bind(this.__selector,"mousedown",function(){a.addClass(this,"drag").bind(window,"mouseup",function(){a.removeClass(p.__selector,"drag")})});var t=document.createElement("div");f.extend(this.__selector.style,{width:"122px",height:"102px",padding:"3px",backgroundColor:"#222",boxShadow:"0px 1px 3px rgba(0,0,0,0.3)"}); +f.extend(this.__field_knob.style,{position:"absolute",width:"12px",height:"12px",border:this.__field_knob_border+(this.__color.v<0.5?"#fff":"#000"),boxShadow:"0px 1px 3px rgba(0,0,0,0.5)",borderRadius:"12px",zIndex:1});f.extend(this.__hue_knob.style,{position:"absolute",width:"15px",height:"2px",borderRight:"4px solid #fff",zIndex:1});f.extend(this.__saturation_field.style,{width:"100px",height:"100px",border:"1px solid #555",marginRight:"3px",display:"inline-block",cursor:"pointer"});f.extend(t.style, +{width:"100%",height:"100%",background:"none"});b(t,"top","rgba(0,0,0,0)","#000");f.extend(this.__hue_field.style,{width:"15px",height:"100px",display:"inline-block",border:"1px solid #555",cursor:"ns-resize"});n(this.__hue_field);f.extend(this.__input.style,{outline:"none",textAlign:"center",color:"#fff",border:0,fontWeight:"bold",textShadow:this.__input_textShadow+"rgba(0,0,0,0.7)"});a.bind(this.__saturation_field,"mousedown",o);a.bind(this.__field_knob,"mousedown",o);a.bind(this.__hue_field,"mousedown", +function(b){s(b);a.bind(window,"mousemove",s);a.bind(window,"mouseup",i)});this.__saturation_field.appendChild(t);this.__selector.appendChild(this.__field_knob);this.__selector.appendChild(this.__saturation_field);this.__selector.appendChild(this.__hue_field);this.__hue_field.appendChild(this.__hue_knob);this.domElement.appendChild(this.__input);this.domElement.appendChild(this.__selector);this.updateDisplay()};h.superclass=e;f.extend(h.prototype,e.prototype,{updateDisplay:function(){var a=d(this.getValue()); +if(a!==false){var e=false;f.each(c.COMPONENTS,function(b){if(!f.isUndefined(a[b])&&!f.isUndefined(this.__color.__state[b])&&a[b]!==this.__color.__state[b])return e=true,{}},this);e&&f.extend(this.__color.__state,a)}f.extend(this.__temp.__state,this.__color.__state);this.__temp.a=1;var h=this.__color.v<0.5||this.__color.s>0.5?255:0,j=255-h;f.extend(this.__field_knob.style,{marginLeft:100*this.__color.s-7+"px",marginTop:100*(1-this.__color.v)-7+"px",backgroundColor:this.__temp.toString(),border:this.__field_knob_border+ +"rgb("+h+","+h+","+h+")"});this.__hue_knob.style.marginTop=(1-this.__color.h/360)*100+"px";this.__temp.s=1;this.__temp.v=1;b(this.__saturation_field,"left","#fff",this.__temp.toString());f.extend(this.__input.style,{backgroundColor:this.__input.value=this.__color.toString(),color:"rgb("+h+","+h+","+h+")",textShadow:this.__input_textShadow+"rgba("+j+","+j+","+j+",.7)"})}});var j=["-moz-","-o-","-webkit-","-ms-",""];return h}(dat.controllers.Controller,dat.dom.dom,dat.color.Color=function(e,a,c,d){function f(a, +b,c){Object.defineProperty(a,b,{get:function(){if(this.__state.space==="RGB")return this.__state[b];n(this,b,c);return this.__state[b]},set:function(a){if(this.__state.space!=="RGB")n(this,b,c),this.__state.space="RGB";this.__state[b]=a}})}function b(a,b){Object.defineProperty(a,b,{get:function(){if(this.__state.space==="HSV")return this.__state[b];h(this);return this.__state[b]},set:function(a){if(this.__state.space!=="HSV")h(this),this.__state.space="HSV";this.__state[b]=a}})}function n(b,c,e){if(b.__state.space=== +"HEX")b.__state[c]=a.component_from_hex(b.__state.hex,e);else if(b.__state.space==="HSV")d.extend(b.__state,a.hsv_to_rgb(b.__state.h,b.__state.s,b.__state.v));else throw"Corrupted color state";}function h(b){var c=a.rgb_to_hsv(b.r,b.g,b.b);d.extend(b.__state,{s:c.s,v:c.v});if(d.isNaN(c.h)){if(d.isUndefined(b.__state.h))b.__state.h=0}else b.__state.h=c.h}var j=function(){this.__state=e.apply(this,arguments);if(this.__state===false)throw"Failed to interpret color arguments";this.__state.a=this.__state.a|| +1};j.COMPONENTS="r,g,b,h,s,v,hex,a".split(",");d.extend(j.prototype,{toString:function(){return c(this)},toOriginal:function(){return this.__state.conversion.write(this)}});f(j.prototype,"r",2);f(j.prototype,"g",1);f(j.prototype,"b",0);b(j.prototype,"h");b(j.prototype,"s");b(j.prototype,"v");Object.defineProperty(j.prototype,"a",{get:function(){return this.__state.a},set:function(a){this.__state.a=a}});Object.defineProperty(j.prototype,"hex",{get:function(){if(!this.__state.space!=="HEX")this.__state.hex= +a.rgb_to_hex(this.r,this.g,this.b);return this.__state.hex},set:function(a){this.__state.space="HEX";this.__state.hex=a}});return j}(dat.color.interpret,dat.color.math=function(){var e;return{hsv_to_rgb:function(a,c,d){var e=a/60-Math.floor(a/60),b=d*(1-c),n=d*(1-e*c),c=d*(1-(1-e)*c),a=[[d,c,b],[n,d,b],[b,d,c],[b,n,d],[c,b,d],[d,b,n]][Math.floor(a/60)%6];return{r:a[0]*255,g:a[1]*255,b:a[2]*255}},rgb_to_hsv:function(a,c,d){var e=Math.min(a,c,d),b=Math.max(a,c,d),e=b-e;if(b==0)return{h:NaN,s:0,v:0}; +a=a==b?(c-d)/e:c==b?2+(d-a)/e:4+(a-c)/e;a/=6;a<0&&(a+=1);return{h:a*360,s:e/b,v:b/255}},rgb_to_hex:function(a,c,d){a=this.hex_with_component(0,2,a);a=this.hex_with_component(a,1,c);return a=this.hex_with_component(a,0,d)},component_from_hex:function(a,c){return a>>c*8&255},hex_with_component:function(a,c,d){return d<<(e=c*8)|a&~(255< + + @@ -22,12 +24,96 @@ renderer.view.style.height = window.innerHeight + "px"; renderer.view.style.display = "block"; + var filtersSwitchs = [false, false, false, false, false, false, false, false]; + // add render view to DOM document.body.appendChild(renderer.view); + var gui = new dat.GUI({ + //height : 5 * 32 - 1, + + width : 350 + }); + + var blurFilter = new PIXI.BlurFilter(); + + var blurFolder = gui.addFolder('Blur'); + blurFolder.add(filtersSwitchs, '0').name("apply"); + blurFolder.add(blurFilter, 'blurX', 0, 32).name("blurX"); + blurFolder.add(blurFilter, 'blurY', 0, 32).name("blurY"); + + //// + + var pixelateFilter = new PIXI.PixelateFilter(); + + var pixelateFolder = gui.addFolder('Pixelate'); + pixelateFolder.add(filtersSwitchs, '1').name("apply"); + pixelateFolder.add(pixelateFilter.size, 'x', 1, 32).name("PixelSizeX"); + pixelateFolder.add(pixelateFilter.size, 'y', 1, 32).name("PixelSizeY"); + + //// + + var invertFilter = new PIXI.InvertFilter(); + + var invertFolder = gui.addFolder('Invert'); + invertFolder.add(filtersSwitchs, '2').name("apply"); + invertFolder.add(invertFilter, 'invert', 0, 1).name("Invert"); + + //// + + var greyFilter = new PIXI.GreyFilter(); + + var greyFolder = gui.addFolder('Grey'); + greyFolder.add(filtersSwitchs, '3').name("apply"); + greyFolder.add(greyFilter, 'grey', 0, 1).name("Grey"); + + //// + + var sepiaFilter = new PIXI.SepiaFilter(); + + var sepiaFolder = gui.addFolder('Sepia'); + sepiaFolder.add(filtersSwitchs, '4').name("apply"); + sepiaFolder.add(sepiaFilter, 'sepia', 0, 1).name("Sepia"); + + //// + + var twistFilter = new PIXI.TwistFilter(); + + var twistFolder = gui.addFolder('Twist'); + twistFolder.add(filtersSwitchs, '5').name("apply"); + twistFolder.add(twistFilter, 'angle', 0, 10).name("Angle"); + twistFolder.add(twistFilter, 'radius', 0, 1).name("Radius"); + + twistFolder.add(twistFilter.offset, 'x', 0, 1).name("offset.x");; + twistFolder.add(twistFilter.offset, 'y', 0, 1).name("offset.y");; + + //// + + var dotScreenFilter = new PIXI.DotScreenFilter(); + + var dotScreenFolder = gui.addFolder('DotScreen'); + dotScreenFolder.add(filtersSwitchs, '6').name("apply"); + dotScreenFolder.add(dotScreenFilter, 'angle', 0, 10); + dotScreenFolder.add(dotScreenFilter, 'scale', 0, 1); + + //// + + var colorStepFilter = new PIXI.ColorStepFilter(); + + var colorStepFolder = gui.addFolder('ColorStep'); + colorStepFolder.add(filtersSwitchs, '7').name("apply"); + + colorStepFolder.add(colorStepFilter, 'step', 1, 100); + colorStepFolder.add(colorStepFilter, 'step', 1, 100); + + var filterCollection = [blurFilter, pixelateFilter, invertFilter, greyFilter, sepiaFilter, twistFilter, dotScreenFilter, colorStepFilter]; + + // create an new instance of a pixi stage var stage = new PIXI.Stage(0xFFFFFF, true); + + var pondContainer = new PIXI.DisplayObjectContainer(); stage.addChild(pondContainer); @@ -123,7 +209,14 @@ var blurAmount = Math.cos(count) ; var blurAmount2 = Math.sin(count * 0.8) ; - + var filtersToApply = []; + + for (var i = 0; i < filterCollection.length; i++) { + + if(filtersSwitchs[i])filtersToApply.push(filterCollection[i]); + }; + + stage.filters = filtersToApply.length > 0 ? filtersToApply : null; for (var i = 0; i < fishs.length; i++) { diff --git a/examples/example 16 - Displacement/BGrotate.jpg b/examples/example 16 - Displacement/BGrotate.jpg deleted file mode 100644 index f33f7d453d124f40054115760a0415a21b04e70b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 139735 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 dr^rzERs0CKwGPZu<1Cv z-EZ+!WhXcCEmcun-uGyBdv{#UeM^^$Lk|*vf~&Q&8X=!wLR)T)aXB{Sdw02AKH}xY z^E~6pqmWpYOzfMoU0Idf+V1KL>Ao)%c=Kv6PO5!Omd@6ACyG|QVV@DjU3GSWCnnz{ zrb5~@d5%iEfYeJE4HV3r%BeJVP1;=^EycV-t0?4BM!(f?r<7t)nu?@m;V z_ZYrglF3LJ`I?1oYh_?DtA9omE*mQYtKoiqg<>}~+BKBRzBxeB9OH4rf)NRJvh02( zYkINsPZ-30<9{`*@%vp92kz>3F7#EWBzS9y$gQ@t%!b7PjyiBgpt1^*!v~f08nPpb zw+M)Vwbj*kn}W3%ip?DLVlfaJSt!y@O4K4KE|T(Jl5)tw20~y}=Nwtet`F zg|4a)j%(61Gj-es&uGR#HSQNb4%RL@zftT6!dT&TImtyiOQIL*Z%OTLoz_d%#uG?*2CgT49Q**lblgM~fc}H@y2)t#Uhp%#sRep#Y zak*^HaR!VT5yd)Fz*%%Fw=b7bEOkdBqV7y{iffPuTsVH?eW6PgkX8D=sE#>CzgJZr z4~Mdfd;^?ZPM6bNK;6m)#Uu3JLI$tq11As7O0d=+LrUWhDMxGn0J|0c0Mw41(%oZq zv`PRW(ZBa#cai<0kyuYN`0|=^g3A8@6nWx~&x*CW({TQ%oeC|-raFO`N-Zv3=Z0DU zPqzZR;_WNweKL*bjQpyL5?$S|;Vv16^lsZB*24puc!N*Cs&8t@@yW1dOB8*HJbHSZqu-_U8xO93J8Pqw_}m zZ-cjDYb!tGk1+ColUummddcDSoBsgN=a;*e%S8LDiG4U(Qb|AiRF&&mnpJ64h1b=D zJRgZwL*BXK3zpyYGo5Z-S8;!M=}4pv@WjKxyw7Ptc2~PBl5P2kU2b|sbYCOUZ;?CB zD5yFPhWuYp#%^}c$@Eb=S!z3Rex%L1h1onP-9+m3@iuhq4X&V@?Gh_<>S7lHb(ais zT~*6W&2lNf6D!TZXPi{^2iB*k^&cxFS_)H|RC(#d?Rwdkb>K7OO#! zOMW7btm?n;yG!Jc{$_873wYG#RC_w=5&5zw$jR30kIoP7I$mKO2SbetI_r0%v z0cUqS#2~Q{KF5(!;TB6fXrcmx6_m4nc0Q(l-N{Xkpl}pYRXmU>WMdSS7$R}y6UCLz zptgKllvgpdpHvFdm|4x|?Oz#{HnrTJ3#j(bV%#?v2d4|D;h7xPmRoi9^7^1|zlYee zTtsKneFM2#-#ym^GARWpuoQVXRkYx}PealCcGR;YpxAWiv}T9MT+RcMDR$>~I5qlu zPKDc?p@7;gMs2F5_9PSb(Vy`4JYoq})cz%TX;k^apYawS@Q2u)`-%KU{>ra`9Ge!} z{NWYuRc?>Exg&l$ht?o7bjIHA^!~-4zh204h$Z2*rRXl7q-@_^6=_4=^N&)MpN-Kj zfTO1`?9QtzhYDmXg711V>WXW^Uq>}fl7Eoj>~NYPGY1|izT73yoA?i^=8rk01*9&KW#Kg z{{ZBge-lS_mfp-*9OWcb;6*RVHN7&(oz}(JK@YXa#;(%NB+9b$>R)U@pCQ|h+mMl&s-WoZ#~?AV)MnvAg{`CiYB6qE|w7P7%i+BR}f_4;;2eev6}r& z66h!Cxej$ndDo&({WM6$e zH%u&y>AN0L%e^D2U%<6ZZVxZ*Dm%|pTlA|(`KJRkxI*EHsprTlJ9omEcYlFC#g+Ev zFCQYCeRVeTFU^?*-lvhxHE3^Q$|o!5-!mt0m#{{ zEfs0;apYBbES-{QpI>pfdZWFxBK*#_V`^VSx zqcy)J+{t5-eIN<|wbj@3nHwg%j2R{Mnl%7upY4oOSR~ai89v0G+1=z(In{eLk)-}9 zeY2d+p3>&HdW4!K_Qv~!agiip#m2cDc_|fRWil(44H}tUO~*9_^ko)xuERF5nYz6r zw}%T&$ZvAAg`^fV>)y8-E3g*r&CcIIIH9-&KUtt^$N}2{r8PWtgu=(5G)Z zcgs7~j8+%r{HK!LXl-|J`ha)zyIxm9y(u`?0v5|!#e*fYM>zp=i;Yi|WD&R^V^|`P zhiB|oArZL-bft$&vfx#?z+R*dah28gMqR4ZV}W`bwWO79y7Dw>XKSd6ilbCgaNXwH zX|t04;o2gIS4sDe06Wq6B?$68axL3fO{N*QOSg3{=Gr$F?eIG$xAl?Qtk)j*pG0UiHDj$`YU}DpyzV8$#>ZpCjtW`N z1-0=Lvw8sf6FUr=@8YR@obnRa+Q$+%e46nFpsA2uJc7LXkJ3Di&$OxHut|;$T-Fhi znlfPfwe!&QE}q&}&uc5Am8Pw5IE6ZpF?ZE2<-<;YIa;c@L86p>;0 z?(1$xw`F$A{Y(DZ!(S<--}Xez>Irs5=}& z5kJSZBdQbkST@ ziBXcmsj{l>m6y;b?8Xm-VsWBYydYjlI<_NXEW?$6p@^#0#rG_b;MAITDzcl49Apr3 zPmI*M9D1qBSP;l6RV2hRoX#|KZFXv=>WrS}<1u{J%H___b!h5I z8KC1t_kK*J-XhvxD20$elC38<=p;4RR95di6l+@Pz9PbPYq8GVwcK0~?<_+%AITWh z*4nL_Z66&gUV21vKdWaKr*7IbW_Xpc){ATFe4G7EYM`)%q)jo`IXZX*ONjIe@g5Pg zo&csz2@(+?If!`pV;*W~@zk*ej-tuubS}`$W;}QWW-!k$p?VPRS$zdJ?ur)bW2t^| zVHo4uri|ZDLdF5HpSN$*BJHzo+fPy2e8$@-bc6Sx zI7r8F1Ql*D_V{IMa{mBBH&$R&k$}xjoRu6zlG>Rc>Ji``P^;Tk7YB48mLNqOJ*ZUS zffKPr#z9qJz_!K$p|jt+bThbppwh9o!&d5!@=*eWEBO*CV$ zBkU@?;BzJ~pe0bfVG~mv$ezWXt;9?jlT-MtXONyE*|E{9x=9vr{{TC(_d@f1$#QI5 zF@zNX9*qwZnu}IBky>&3g!i%oJH>tA7o%uZh@&6A{-#dZ<7maqIhr#iBQi%Ef>S|{iPH2IoPS`bWigRN17?Adrf>v)D+iiC|k9Q?Pe@L zv~gqkh3Fa^N^3r*Q+G+${z7Rhh&hF>*0C8~jd#=$?xHmXkXu*;mF4F^%ZXPZ6PE^{ zIj0O+%aXSUWbUIYIDJYHiYrYb7CS3o!L9TSXse090FTpBipYpi%Joj-C3lBmu_sM( zl17}*U{>pobMAk@59N2gh2E zu4}U96{@9wKEUD%%0f&CxC;+-345-$B^rv?+_xr}${=e{F z@&~xxcYBdZZrt#AQLX#{U6lHj?(!Gfu{me?3yiZ9LUj?EWU7k?I@1Vc_K`<4iYiuV zC(x@cWWpJH6S&j8P@a^LT3XE$HdZ?#6-jH!5IUMR)Cz^x(I0CxmHJ!SQYbT&O`v54 zqnS$3j50Q5yB)6^D$cgQvk#jwzE;O%`%sguH`#A)?Omj~g=YLUjxv>On#JmAe>@Py>PX-Nc&q+jUCykpL1}}N!UltU zvwR`Ucy%x|>_mKIWn~f1rv&rVnwA|wZ!eiY8c!?F_Dbs2O2AN-3fK!o_qNpg@*K9wf#0P@hNS!hWYK^x?1bycP8Ta z+GrikuWDPVjf`*FUCRg}Ffn$0%7m)NBas~+0joSr;uR@J zBIhLW%GZjtsHOtsqNuLfW{)Dnge??P-GDCJqiLj~?_7~@v+LU#HEH6fNd*&C{7 z&H5XMd0uAL%wxgAiZsTDU z#6}4}Y~vgFg0xy&PA@2Zl*ahs^(Y&aoR+gX8ATl5E4hwq(Db%c(rCo)YB)BU63*uV zrk*ve*0C9j^}*WRIC0`pxGvyKlT0$+65Q_&k9U~D$T~}6!f8b(mAOX2nI&53!s^W5 zjMbLSj{ABC2<>)lzB?;yBZnQ zAj>rx=xHnTw+}JNJ}V_RQ%9m^hSd3vYn#awjmQTukZGxjhk{(4lTSvTR}hniCk*v& z8HjyAOm#u}4Ryts6UygQ<3!i10j`LJ$9m!BYLE6&8T(`(1=x3CPg-bC+YN1I29zqy zb&?fpq1~x*0M%QCNe@(^n3=ZlzT#(SiYAx6$0`g|l0?y|9Ih!YI>V`7c>0@I-ALQO zG#mn!y4O}$-?}tZ{w%(4chPK{NoXKAHh?F`mgLMnoeyH-qtM%H_bci8g7LMEGDI4< zzx|2{ytC2N6>(8T!unkC#YXrL~qm zIU>Y0Wg?xpbsgk8u!tQnx`caB58ADL%=$A$Mua6!eMTFLpLb&8sG7BEEU8K^B~5gp zVOr_yf*)~e^N2NS7vg2wTTR))ys6d-^kVK|f;=$7Kaq`?NZB=IzD z#F5|)Tgax>w`EU}FS%_r^}B#XedXeEf3R;^0*9E-4;VCBWx zsM{sR4J48#4~XD96%CIkudK5l{w zzTN;{;2{`mDY;4B3{K|#R+vSkUA=M+6iWQ`=jHTDPJhC7fMP24R zQppKNkZ_hg18r_y0Ri47bK(_QR+xL-R;;1jz0)OS4IIY`5OD-56R!nX)^g6a`h5F4 z*KfTbTWxtE*FC0C$av5UiB7J`NAxj1U&g{~>s&ulnkU=3gu89s;x=342Pb$Q95O9D zRllal@yhrfePtUSK7G*U1C6t)Hx8YZn_pA>ZMcxwHztBy&~gu_;)GwSfEi&eD0P(JU>vRV z>myE+$F)>&^cZznv@2cme&v0hl&)Fq7>04lK7b0C6ULnV6|7!{=$N;jbbgyQhoSarl^Mjb=U zN$g&wr3@r_{_1ZbqWTU5p5V0bhXzt<D0Sn2BR~XTb52kj!K>oAk%g|2v^)S#_RdWaz}Y2^re^}v zq=CYT>aknFxwUEYJ?{3WO01#Ko)`<@WK$U2D#zl(+sOdg)ik=d=L4O(MqESa8VTa^ z*NavQ$mw>=KNElB_Ism-O)E^T%i=f87At36!G|IAzmPRr_LyYI?I^Gn^xP~4SSu}g4#Yr`^T^%_{Y+^ zjB<=3jO^BjYJy9f^Ig{Nubtl$Yi9>22QB8 zfQqK%9X&Mq8LD9~#uUa^YLQzVxVm;Oqj@b(wQ3ssniUG&TY1L}(8j4s*SocVG8tS z#Zz@+MBpah$fngn?T8E#9^+aRWXqmUx4krSpt5N|EFaP;M=>>&PX8~o0i>m>gGm;A`5sN}gtlEbQP=oxbSdExv} zE4<#C=`ZsC0GJl<8!oXP#kpEc!1&~82ec~B&T3;l>-n$wf~BuGyfk_Hgbm84xe34W ztxEc4U#1RJNrTC`Y7}cdr2xD0M)40lR}or5UnVX-R`Dfiv}luSw4=AV8Y7p~qweBcm%8D` zt~m}%-G3eOUfNJ*G5IM@ZOE_VsJY&3sJ&JbQd|pV>8zgCLX!Z=+{vSsiW$T`<9BfT zSVJxhJ~ld^%fUe7-NQA}#L&VCW4MX&%4+wFYs0xzvIRY@b!2;ALXp*7DYtKqF^3Q*=N&XkA;PtHJ@WHr&Sl%+k@G8_UQ|rSr zd!8x5`?NpcZ*1+;rAfKk9PPtklO{wWmx7$@5+NbPh24VQ7aT1Z%w;vd?m1QQi}j2X#R@l&S+kZz3|s;q$i^_o{mu`CJ5bF2lnHx4Lw1 zWyE+rr^G)HvRj&JNv3S{_8eMher0Rg%gB#`!^A%jyzg&SrsB^*qH4$xT(PI(#%c~d z%PDP6EWKWOFn2UuvqP|Ze5bWbMXn69AED(4cWt0LHKbY_Xy>GPk6k=yK zH8S`X?M$nu>do$rev{}%?3ozE0JOUJYd)|15$7Ia`PpKkzJyy$Qtvm?btd8|0}VFl zU63EHirgdK{zy5csU2FBS69^AdfWqnU^Q|3l(Uu#h^F6NNf{%|&NM@8mvHW)x6UQS zr`W6DZZHii$v&HNIi5jF7>d3oFleC2DH0ISl_EzNBmq;9N^uKY>o~o`!Z2u0Zv&qP zj1)DE+D|3j-xIrxvf_9hQ(QgZmkZExc;zvzruyMV%i3sYS@Ii4`>0PHznE0K5}Jo$Cn9%$woTUFz4uLaY~3@v{@7Yz2-+L9I?S1 z^&%e_szl1qOg087P|w-1t+aV5;)edwj%{MeS&BRMtTOiY4XbaTaJV2x3rn%$cn@kx zGFWOkJRH-eZ0>raewTN;1T&{ z2i8o>_^%kRyDydFp^@cBtGFu%gmVjg*Dbb*)RnZZx@ zG0z=7C+Qmbd?rUU@!PPzS5OXV(Tii@2PcG8H(sE8x}vurOKqa3jIwu)THM#)_A zON~l5R{=)^f}?sdOCgd96UP{<+yETW>N3b28|WnJJ?7v1UCUwd%Ep(lc7=YRAAk=6pnH#ERe4@po@|1^Xm$4R9uzVT!Y{ zOmL)-Yw_O6!NH;ZmEX^8*7sVg>M^9A+G35;^Ay2W)$Q3R{1_$BIH<0PVzEWQ#Gw|% zBLQr+sv9_$B8B%aEpTu&DyzaR*A&S`^sxZu$Vaseu_iIlrN#nnx|4E=!%T#*a422W z#g**w^)=A3*ma`~8FDGwfZwn116|@@Se9E&&er%3LE+9h4k!ijaq0)RUUl_DIM~>+ zIJ}@&&m}25o-#O)8<|3Fke#DD8|kd6S67%pE}mZnE2&l%Yc0kr#)=v{lAzyk66zgn zI0ZB-Dz-`+Q9_H;SsP;e`#}pGa=}^(mV{QVY`zJ>_S=_fQBF8U_s4Ci!w;yzk^@X=Mno!%E)Ti~ zO9!Zbax7ZzVK=ceJ>|5$$ahDo5nMXQak71_{7txmL8n8p#PZ~;PhI52LQf?!_ha5V zKz!!dUAXl5##>xnEF-g+2_beLY`T0w`@TB8o@4aP9vGv&BYx>SpOxGjjFAkVOxpIR z+eBSV0)%5FN<&gmmGSX394@<{13VE)@#} zR`Q@ZgJe<dlU^tc7bJG9M4J7vBLrbJ+ zz;RvJb{VU$?OXn!J;{3x?O?E9MHA&{4s%PjHiMew0q!l5{QHlR7oWL5uy1Jv%-2#h zNFXir{6WOxo!BZ%;z-GF=3sjR8rKSgnvp??^rOZb=lQ1%=Rln5%E0K&MdtuB+d3Hm ze2(t0k0+v}yO&gMyk_Hz?erWLG8g(q zzYWy8<24M`p`e8WL*6O6l2O-q~~$Z~y;Vv~5>eJO!ug_HbEIBIy~+`T7HWl5=e z9&zR3>4Sp%m_7Ob0H}8c?U5ZjO|1>V7zYuPR=;0iw~yvz^!!h@z1c6RjJF%ut)cYd z0g*AGtZ2XhG7C{%v2nr~Wlb`hdv;u0_a71b6%PAZ!aUpNi%wCQ(e6(mQd zLdio35`r9k_wT(js;3#T58Yj3|q{{Y++?HH$b z{7bOi{{T`LMSX2AmEydU)RA%<5SOVqb52AQ?31Y`K_iT>5w|5O;bfXTEQQ9v&>A=< z^&@W~aI&fC4H;X-T41M&5OHe`SSv9@80Ok6fK$E@(t+3ev-cbLx^BtZn8yQgr;GU> zWaD>wjbFfcKoc5zIK5>m^{6W`s&z)PM5J5y%J-H}~N zrscg`#vP>VcVeMA5KC?gprYNI#_=Yb7z<-L$Z!MNRaf0EgX&uw4;8LHC690DNN|^S zl+OJ9F@r%;!(ZYa*6=CwYs)MnWZIi->oIE>w|)+0kwZgY$y)Z-Fld&ADh?g14ErYT z?kh-)k{VMb@|+;sGj-PH@QP09yUlv?0i=8aD^)5cms?dghBM`JSqYpz^-s_sR z-d74AYBJJDbBc#0C#R-%$JO&$xanh_K=$GgI+taRKNC;A6|tnJ@-F`XQ7xdm*&REa z&|2M9Cz7Ara*K`(Z;0QoTI^0q6yApFy{cWBOGjL_@>#sJhMJJm+^%TRWTT7@^PXo; zyZe;W&%iqSt2W5NBUAf=D?cA&MqXc*>cgg4T)XRyy@ZcKL)(Y(LoM->_@krwzPkR2 z3t!heTa6tYjO`=%Ah+nwAv!-b)t6Yw5kIQ7TY;ocrQ8FB5G!c0dKz6%$+YZvQo%eI zR`*~!DVp{UL?IV96HQj_HZP({gp*7LNL`aHE>A`uGsJO3~{KdO4n)ZccWLQvD~l#^5%RnY7g21D7oY@784O}kQ;Ee9djpR=&H#cgGGwSrVz;khL>W~fdxd-B;%A)_f|V^+)0cRY)+<*0Pz7^i&Bms zQ_p;!tD@hOhE_YHWEdKbApT(wyI%l=@FCv1ILkY?o|lkXZhmPkYe;77rvjV;!M0L3c;|WU!D}n8=`r?8>gal1zA+Qssm^c}6)E1>#WrTr(%wi|^1xh1C3j)c zlgL|bp>9#P>|NM5EP?U*SFt<*8z3z`>B<=#xk0{}cJEp@FpS68s$T@wLK?Pqv@B(`gczPFEO;K#&1N@f zHaeEBqpL{;<+r6b@5Cq%Ffv|wzp2|S`W}Iyv)r-jcmpFn2?xY)l=BN4x2=v)Z==fS z2sK3}7yxlYVEb8X9mv}4ue_sejV3;FIJF$r+QY}7wPL@!pqHt(*ypkq`%n>Xq-i7d z4kY%i?~U>Xsg@!GdZ!Xh0w2E$VsZZ3;Tc;(&8<1vnt9(P+)ym>pn*LdsOLQbKuLv zUMS&I^}x~s$s)!xslTMDGMMb9c+Lw=Fn&~B+IMNROw!t)F~p>7M#&RIJh^M4w9YRIY`#G5q~gC!xx4~-Ntq{jdPmr7~qvA zNf}9WVU}B!%RFvyaXb^;*+1^=LwGlNYBexZu|6^$x25Wa*4vv+D;fKhnDR;cz0 zNnX>F=uy6(hwitp-fv=Yl1CR3XmL5IDT8tD1bN>-8sY85a#%j1b;~xZ18ZzPE5??J z(IlX%k8|q4J{HG)oy~9y^y1Fq*KU(~yI^hI@9ozTBhJ3m%B$|>n{AEhONG%E8~gd3 z4~&lGZN)_cozs4z7hB$LQuw!H@!qWgHsFQy45HY)Wuw=YkI`dCp~8OcDo0Pej{=CkgavZ;JW2_(W(zgdkp<-$UMGUg-#mq>q+TuD^R52C zfM0ex1}durmX4Me5gXjf8j2bqn-*j@LX_MDVc?)^@WYRIjl4a3$W#{S;Lkh5)A&7_>?)WhEQyfQJUoPbrQG?quClFJ#| z+cwdf-HgXG%dr61yS?Mkqh+1%9)l|l-s0L!9a#8;BFgeoyH+z_GViut#eEoaO&!E4 z-p)+U#ZI<1!X|1t@CwCrWF6I;Tgf9N5`#jES3>j>$fmGcww=kBZO~7QVcv*CU86s< zuHf=HXhdnO8rkWsnQ;@MkX5b}M>V42%GSY7Ei;$(9?t!?>BXbrIMfxt(6LHCGs=9< zlcsrH1W2+n>>BDOzB63HA**wQi~6@XNI)WVZ*!mKKZ4jsYDZJZcjp`2qQT zUwWsGtD#PYmmcCyGlqJ63>mEI*Q|wW_e(cxA6040A(qVmYc3`tp6EPRoOy}o2;X?B@yKfhEuP{r zF2Q-Pkmg2`OX^4?ZSz#+nj2E&gJE!KxZ$@*c)9qGYV z%5fhU=Ya8G(A`cgYjdlJ7<*Jb;&y{v-E4M1i_ON`8Va3qHwE0w(3UWH=v23Et?27{ zM3HVRnqh;ZgcnqM5c_qfET);G)SF0B?!4NWAeV2oxSinmd^$nzS&gq7IV?14^)_P% zp5#1c<8`^)M}22&>9OCa;vK{+7UrDmlZ=t*dR9|x6qK`)T{jm|`j0JSg9o%{Rgl=$ zaAnV?4-1q>1mexkB-Py2SWC5%&cATj!|J)$?Ee6nIk&U1X*71bU(|A!YV7nYok6!Z zb&1kJ;Js+ahM~x__$P0NbyQNa>_$83aZ=@(pRH$%OF?6G2mu zTyQvNtm5;4;YB8JKR7e0Sg?PIoYG-2FqtbJ*NU|J6I#I5jglNgJJ0R6GM^MVB1qU6 z&2jthYHjzp3KdEZkkU*}Fid zMZnOMHK%QztD!Zvsw#75OR%=L>D`oI8>OF;D}>)_=#MJ8$!%Z!PFZgR{dd+3h1E6? zKU~h?p{Boj7i_)TK1lTK9d)frUaaiT(FARR7U_yG8pe)8Bti=abL5`Wr>4E6*OiJ4 z!+qoY5c~EPaD)0D9(KOz@P}-+wz7}Xw~R5PlB3k#YidH3h^zug?QWu(AevY;E0Q6d zswT9&LR2E-SviXdM43V1F1F?n)%yfKUny!)23OGz$fc(h2f8&ENF1G7AZX{1Lbxg@>$m6zGLFI_|qj*B;ap;~D-+xE+i z!u7CQHl+ETzz$^r+uDtB%$cCm)RnIhM^4)IyKS1-MFX_$V9mqYqvTqBZI@$Y=j)eZFt>r!8 zBrH=R?d>LpCsb1C4 z49Z_ygoZ5$l~BP=iue7hJvUCLUqr^}U;# z^n8Mgz{V2nX_tDMxirCxsNZeeUke&tiw-353R%K7bm~7jWq?a%x!Stc_BLGF$SCOE zDltN>*JylX(N5etb8_i-KKEjIyV%W4whpVLjDIgMs#~z*9@!0_j<0Fw7?;Fd3Aes? z`AvpnX?j0)F@;YM=B%HQjA#DPC6%4OqKdHbc zxsa#{;@x_CZ+z^#+^ymPI5{1^p5jYVj4F$oDsQK9K)hY!)as=Mup^dnyI7Wqw6A^yvDS8WsB~wI?nN>xBWxt z#l?{Zv0I0Yu0Im9^Nac*C%J;efBR0No?zYvV^6rNanr4TNYD2@x&4s;000pFi;dK4 zWW1L$DCr4PDAynKqp{?z`3G9gXYlO(GjT4go?$H%=Tb6Nb}g$Pac^J8?Pu$rKZwKp zcUeiMn@cR?b`5l{10LYATT_G1IX0R)F<*4@JK1*bq}${yzr2Z-()r_z6GO~ZV0^7! z^2}BmJtM>2Uc30FJCkje+2VIj`FjQcg@W1Fa!oUP4T#vVl07Y~Phgr6P;ti`R#xg< zA0y#5o*4r!9SNpEHZ#FHtw@IM67X&y^Ne26#TnMy#|)aOW9b0cKqtRtQ-0YY-eNMs z1b6Ko6OeadTI~-bDqbHkDsTA6-m<>qn%~;XZ1=%(!pT}_SXZFw?I~f!@OkdmoTBj7 z8Wp}LMdBi@IjuDt3GiojHL^tJ2MUC0or6Dqwg`(zMI$u9QiF&*q`kr>{{XzEUlFU0 zNm>Iy10b5lnMiRH;T6=wrOE0;lQs39ABI8PLhL8dTqDpoQ8GId!F0X{GIYU*mmGO< z$Cn&IaQrkkGn#x*_@aAwv@~-#l&_JkheFD!B8H7EqQqdX*As^}wyb?B+M+c??2fIh z8-|*MQV$4nke{x%**bG(F+}=a-UA#U979e7s@pdtxawH0DX}lpPMa)@?srYBkMUL6 z(Js6_xMlTbFY*r|m+i#g>Q_-1q5l9IYVV0BhJ!WR6ZYYcRyXne4(WT6MT6U`1Pql_jZ`CnUCfjR6+BToX#+8&;#B>)1aA3ARIr~W`an{s;KObCS=#!TDd0I+ z-&4zo@^)z+*xFv>MzF!(r0|CU9JvGY7VF5g!l&em+IlLUlaq4Tm-s#LFveX|0 zV~={+>uW}(^FDv`es=F6K3*Z{iR|BqMk{7mu~^HJD^!jhJ{DeC&1msf%^R3UcvIN2 zhehDzy#sLlo2c&giF_fFIjskwC1RBE|JPZ26lZcEHc01k|LXEcfye@`b_ef|m zLtDs+V3yuDY6K_4Dey-*4z1e2-A^>riAQzce;%OOx1Ip*Bz5Gp7(&C~Z|1cc)OIhK zW)W4dnKXN>n?u^zjb3S9z>HI6+BXQd3wFxWS5w3|sUEY7!Ijye)hrF+ zW}~S4724|u&5w4Ar&~$^J`}3LWs_#Y0H;1q}xfKpDXC$!Ah)RYubKbex!w=5H z+z*jW^>f2cv34I2mMd-dN zmpd`?1$k&fs`Duomvt9fTsg0{WEProG^qfuP|?y@!)KHE4PIxaX?iJr)J}pk zn_;6cw<{M=Z9P9cKwdQ-2VCh z0EpHIdg}B3L#GS?h>Q{hsWDTdaSAIgzL|TTHv^qdKAEbRQ$~yY?^7X^@$UrBy ziYK*vy-O?GkJ}W2r07nG+QfG@`%@+K-B|?0zgKChb$#>UvQ=~FSZ$-&ts@Syv9^V# zgcioy{iR3yd1sO*WB8IuzQGtH)nhvwLHH@-rr)64u@>dL+T1bB)L&eP1mdgP=d z#!I!ZhkBNhmb(~T<^%Cqt*uox!sOMYroLoXcEC5)j}|`>MV7X=5^AT;7#woGH&B%f zTScb?$gb@KmASSQes5iC@I{{U~evYFQREG&C?a3h#rfvLF}q|-d(b4pdVniWd}m`kI}i&m1Iobb%; z+Tijy77{$!Q5vS;722c>gs>MMGqXjZa*!I@nr6yksfEWLTyQ(x5;{ zIj2-chmub3iQV55&78F9lu+|rd zIL+O}{dv|7lvLPTyVHfd0~&ucKB#-Pe30Gkg{@0|tm?N@TlDVCa&Crx0Tjw_FQPoY zxJzpP0OE6AjoEK{_p9G{_{;1qUFt~V<g~^Sh_`9@Y~kLudekbT^FDI(erC@hbCZ8c=!F32 znXVZkkbD4FLG`4WQCY2#mJ1m&#T2SX7CSjGX;-Bs+Bz#IF6$dJvUR*WoFhyZp|7aR zRz+v-yRzJb<*)A2;>+&k8#i5u`_*UUp}O8$_?Z0~ojV`Is(n10T?u56ywRvrc_WN)Z4^b>eW_y{i78-bZEs2wfab131sf(0b#d#-=)!&z z4kU3aMW?UZ^**H4!?k7gBsURTL<`9E-Q;Hz+O?XMy9i&^JOHw?Jibg^>`K&CQcDQB z_*g^EpT2#i*lQ2MK4HOKma=jAg14zths^1gvbIJw+z3^pP8o@^IAa*_p$g)T5mH5; zWxVwn=)B@GR4;}eKwEWT9|8-#a5yo< zy{*E(#bIvhPf}9npiQOInFNM7OX$-WPwgMteI(hX zYh>K_YrCfrS2eEC-t0InH9MCyWUqx#mk~poZ>Jp#WZ0Y^Ekx6H^+e8@fPMF(M?V^&Jr6$uASl_7C+qI-4!sz1%8a9LQQO8nG(22={ zNz`_&ttHfXHx)c|W$+V`ZsEQO;`nTSrV!xbC@@zk)9rkUo(v80@@U%Vq7);{N_Xtx z7t0vhL{7ilpPYj8^rdnIPy9!nS75% z@!N{k^F15PFZp?o!FQDYlCk@`o!qXW*B<5Ex`W-@78-%!<`!mk;IUPi2Z~a|r2VOp zmI=Vyl3c>l!{ZTC4H{wu}*xMRh!sTv{TX`ddNfDe*$2dKPGIK4Y5Z@*{a9O%TJH z*9tgQE>0nIE@9OX_9u5|sQmm-HsXg&f`^*tAA!z416g0{yfK+4MPO9085CilGz^k; zBVo|8rzJE|!%JAQ!CkH*4{agK1WKqJKD37{74)!<>ftXIf(gt zRSk*yBGpm#VINOAb(>{_Zs%geJz3|zbA8=sWO@sF#^(E}H#qhUuB5%d zO7W9HG*N6z3$cF_P57sUmCw5eaOj?svFP1~9lF_r*KiNHm)>*8;Vx_t{w%7D(K7~SOj}+`THhn0Gq9Ia8`!PI@*^xZ zQe>{e%nKOgv02N2PnG5Rsw>}7tOefD4eLc^w0&#Fg=hCHc*u8Ju)dMK7rQ%Saj6ZV zRA;f6sTs}PKW^-mvK_N^RCfaiLI|ZKGv$o8hf#X-XN;(u)bM6zi3ufvsDO z3)$L?AlqT>eRnxw7Ryb#-)Xn>qNAlhxgpGz=X={u*=3u3J!MpIfi9%RpK{MzAmwo< zva@B!-~!kjTXJan#d_YDY>#8)yy+)F4x`X4khm z8}hK95%ar{M>RF`^)V^0KT`xRhRO%rTsur`6+Np*uS=YiS5Y=EP>Yi&x0}Vy*5UKj zATazUa1G?W15Zs?6%z@uBWuSHgGphTxknEM>yXBCj=0->8Ioi? z%6aivn^4-Lz|PIUTR4&h8$cD!Nc~8o zYWjgUE2hJ?hhls{3I*uCF1IT%3G#8oGAEOCd*GmqhO~pI_AgKI)Fjd7`<+J6?t6>l z1%-?RW^uu6HE69P5w_M$K5NJR<l5bu%`C13DC$`3SGe_JPw6NshMLW~gSQ8@6vhD5l ztsH!CxX>TcRE`;A=kX0Q9%)r%Sv4{hB7xZz?polMEBNza(e?{EI5^;1d90T1nzAi4YqYkzB${Qxj{g8DY%XJPp≪ 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 Z0H#B*9181k+sPNHr;kr+AISa>|JjdZ<#Yf5 diff --git a/examples/example 16 - Displacement/LightRotate1.png b/examples/example 16 - Displacement/LightRotate1.png deleted file mode 100644 index 44966cfed50a834b276533f8c34adff03fb5e33a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 213699 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 ZfLBC}NRr`DM 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

    c!kmnT3fWq}n8 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

    D* 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%0DH{%cI44m`nP!5L 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